Skip to content

API: Read models

Capability state: every operation in this file is staging-durable. Read models project durable membrane evidence into Koerper-safe summaries. They never expose raw database rows, raw connector payloads, raw biometric material, or cross-tenant graphs.

The read-models cluster is the surface a Koerper renders against when it needs list, detail, or dashboard views over durable membrane state. Each route reads through the membrane (no SQL, no DB driver, no cross-tenant access) and returns a projection that survives schema and atom-shape changes.

A Koerper that renders state should call these endpoints rather than reconstructing projections from raw commit.recent results.

All read-model endpoints require the bearer token. They are all GET, take no request body, and return outcome: "verified".

Active standing grants for the authenticated tenant.

GET /v1/read/standing/active
state: staging-durable
sdk_role: Koerper-safe active standing read model
request_record: (empty body)
responses: standings | receipt
{
"operation": "read.standing.active",
"outcome": "verified",
"body": {
"standings": [
{
"standing": "standing:anna_geschaeftsfuehrer_fixture",
"actor": "human_person:anna",
"company": "company_geist:rheinwerk_calibration",
"office": "geschaeftsfuehrer",
"powers": ["..."],
"status": "active",
"source": "fixture_world | local_overlay | remote_durable",
"standing_created_by_human_presence": false,
"production_admission": false
}
]
},
"receipt": {...}
}

standing_created_by_human_presence is always false. HumanAuth presence does not create standing.

const standings = await client.readActiveStandings({ tenant });

Active mandate records for the authenticated tenant.

GET /v1/read/mandates/active
state: staging-durable
sdk_role: Koerper-safe active mandate read model
request_record: (empty body)
responses: mandates | receipt
{
"operation": "read.mandates.active",
"outcome": "verified",
"body": {
"mandates": [
{
"mandate": "mandate:...",
"principal": "...",
"delegate": "...",
"scope": ["..."],
"status": "active",
"production_admission": false
}
]
},
"receipt": {...}
}

Mandate state is always separate from session identity; a Koerper must not derive mandate from a bearer session.

const mandates = await client.readActiveMandates({ tenant });

Derived period-close readiness from durable obligations and closure surfaces. The read model is the membrane-safe equivalent of the “can I close this period?” question a back-office UI would otherwise need to answer client-side.

GET /v1/read/economy/period-close-readiness
state: staging-durable
sdk_role: derived period-close readiness from durable obligations and closure surfaces
request_record: (empty body)
responses: readiness | receipt
{
"operation": "read.economy.periodCloseReadiness",
"outcome": "verified",
"body": {
"tenant": "tenant_node:rheinwerk_calibration",
"ready": false,
"open_obligations": [
{
"obligation": "obligation:...",
"invoice": "invoice:...",
"amount_cents": 11900,
"currency": "EUR",
"source": "remote_durable",
"commitment": "sha256:..."
}
],
"open_closure_surfaces": [
{
"closure_surface": "closure_surface:...",
"kind": "receivable",
"status": "active",
"required_evidence": ["payment_observation"],
"source": "remote_durable",
"commitment": "sha256:..."
}
],
"period_closes": ["period_close:..."],
"required_resolution_evidence": [
"payment_observation",
"steuerberater_review",
"closure_clearance"
],
"raw_db_exposed": false,
"raw_connector_payload_exposed": false,
"production_admission": false
},
"receipt": {...}
}

ready is true only when both open_obligations and open_closure_surfaces are empty. A period-close UI should block the close button until ready: true.

const readiness = await client.readPeriodCloseReadiness({
tenant: "tenant_node:rheinwerk_calibration",
period: "2026-04",
});

Connector evidence gap summary. Lists the required evidence kinds for the tenant alongside which kinds are present and which are missing, without exposing raw connector payloads.

GET /v1/read/connectors/evidence-gaps
state: staging-durable
sdk_role: connector evidence gap summary without raw connector payload exposure
request_record: (empty body)
responses: gaps | receipt
{
"operation": "read.connectors.evidenceGaps",
"outcome": "verified",
"body": {
"tenant": "tenant_node:rheinwerk_calibration",
"required": [
{
"kind": "invoice_payload",
"present": true,
"evidence": ["evidence_bundle:..."]
},
{
"kind": "steuerberater_review",
"present": false,
"evidence": []
}
],
"gaps": [
{
"kind": "steuerberater_review",
"present": false
}
],
"evidence_kinds": {
"invoice_payload": ["evidence_bundle:..."]
},
"raw_connector_payload_exposed": false,
"raw_db_exposed": false,
"production_admission": false
},
"receipt": {...}
}

The required-evidence list (currently invoice_payload, payment_observation, steuerberater_review, closure_clearance) is fixed in the fixture runtime; production scope will derive it from the admitted authority package.

const gaps = await client.readConnectorEvidenceGaps({ tenant });

Proof bundle manifest history for the authenticated tenant. Returns manifest commitments and audit-kernel summaries; raw DB rows, raw connector payloads, and biometric material are never disclosed.

GET /v1/read/proofs/history
state: staging-durable
sdk_role: proof bundle manifest history without raw DB, connector payload, or biometric disclosure
request_record: (empty body)
responses: proof_history | receipt
{
"operation": "read.proofs.history",
"outcome": "verified",
"body": {
"tenant": "tenant_node:rheinwerk_calibration",
"manifests": [
{
"bundle": "proof_bundle:...",
"manifest_commitment": "sha256:...",
"redaction_verified": true,
"audit_kernel_present": true,
"production_admission": false
}
]
},
"receipt": {...}
}
const history = await client.readProofHistory({ tenant });
  • They do not expose raw DB rows.
  • They do not expose raw connector payloads.
  • They do not expose biometric material or credential bytes.
  • They do not return cross-tenant data; the bearer’s tenant scope bounds every projection.
  • They do not flip production admission. Every read model returns production_admission: false today.