Skip to content

Interface: AuditCausalHeaders

@kortexya/reasoninglayer


@kortexya/reasoninglayer / AuditCausalHeaders

Defined in: src/types/common.ts:147

Causal assertions a request makes about earlier audit records, carried on the x-osfkb-* request headers.

The engine writes one audit record for every audited request (a POST, PUT, PATCH or DELETE with a tenant) and names it in the x-osfkb-audit-record response header. A caller that knows how its requests relate states it here, and the ledger holds the claim: GET /api/v1/compliance/audit/causes/{record_id} walks it back, and GET /api/v1/compliance/audit/scopes lists the delegation scopes.

Wire mapping — each field is one header, sent verbatim:

Field Header
causedBy x-osfkb-caused-by
informedBy x-osfkb-informed-by (comma-joined)
scope x-osfkb-scope
sealsScope x-osfkb-seals-scope
sealCommitment x-osfkb-seal-commitment
sealSigner x-osfkb-seal-signer
sealSignature x-osfkb-seal-signature

The engine checks the assertion BEFORE the handler runs, so a refused assertion mutates nothing:

  • 400 — a header is unreadable (not a UUID, a commitment that is not 64 hex digits, a signer without a signature, an attestation or commitment without sealsScope).
  • 422 — the ledger will not hold the claim (an unknown cause, a commitment mismatch, a signature that does not verify).
  • 503 — the ledger cannot be consulted.

readCausalRefusal reads those bodies. A request with causal headers waits for its own ledger append before the response returns; a request without them is appended after the response, so its record can become readable a moment later. A GET is not audited, so the headers do nothing there.

const scope = crypto.randomUUID();
await client.sorts.createSort({ name: 'claim' }, {
causal: { causedBy: previousRecordId, scope },
});

optional causedBy?: string

Defined in: src/types/common.ts:149

The ONE audit record id that caused this request. Must already be in the tenant’s chain.


optional informedBy?: string[]

Defined in: src/types/common.ts:151

Further audit record ids this request drew on. Each must already be in the tenant’s chain.


optional scope?: string

Defined in: src/types/common.ts:153

The delegation scope (a UUID the caller chooses) this request runs inside. The first record that names it opens it.


optional sealCommitment?: string

Defined in: src/types/common.ts:163

The Merkle commitment (64 hex digits) the caller computed for the sealed scope. Only with AuditCausalHeaders.sealsScope. The engine refuses the seal (422) when it differs from the ledger’s own; omit it to let the ledger compute it and read it from the x-osfkb-seal-commitment response header.


optional sealSignature?: string

Defined in: src/types/common.ts:175

The base64 signature over the seal preimage (osfkb-audit-seal-v1\n<tenant>\n<scope>\n<commitment>\n, see sealPreimage). Only together with AuditCausalHeaders.sealSigner.


optional sealSigner?: string

Defined in: src/types/common.ts:169

The base64 Ed25519 public key that signed the seal. Only together with AuditCausalHeaders.sealSignature and AuditCausalHeaders.sealsScope.


optional sealsScope?: string

Defined in: src/types/common.ts:155

The delegation scope this request seals. A sealed scope accepts no further record.