2026-10-04 20:33:24 +02:00
|
|
|
# Revision-specific lifecycle review handoff
|
|
|
|
|
|
2026-10-05 00:48:07 +02:00
|
|
|
2026-10-05; INFD-WP-0007-T02/T05. The initial handoff is deployed and
|
2026-10-05 01:14:08 +02:00
|
|
|
human-accepted. Browser document authoring and direct handoff retrieval below
|
|
|
|
|
are deployed in service image 7f5c6cb2; discovery uses owner compact-sitting v13.
|
2026-10-04 20:33:24 +02:00
|
|
|
|
|
|
|
|
## Headless contract
|
|
|
|
|
|
|
|
|
|
`POST /v1/decisions/{id}/review-requests` accepts `version` and `options`, with
|
|
|
|
|
an Idempotency-Key. Options have exactly `submitter`, `memo_class`, `review_group`
|
|
|
|
|
and `approval_intent` (the existing intake action/principal/purpose/target object).
|
|
|
|
|
A fresh `lifecycle.request_review` policy observation covers the complete command;
|
|
|
|
|
`context.review_routing` exposes these routing/act facts to the PDP. Publication
|
|
|
|
|
is required for that current revision. Publication itself never initiates review.
|
|
|
|
|
|
|
|
|
|
The service atomically retains one immutable `review_requested` event per source
|
|
|
|
|
revision, its source attribution, and an intake envelope under a fresh review
|
|
|
|
|
memo id. Retries return the retained request; different commands for the same
|
|
|
|
|
key or a second request for that revision conflict. This creates neither an
|
|
|
|
|
approval nor a disposition. The envelope and event fit within 256 KiB. An admitted
|
|
|
|
|
workload submits the exact returned envelope to the existing private intake.
|
|
|
|
|
The envelope is also retained in authorized event history for recovery.
|
|
|
|
|
|
|
|
|
|
The handoff currently supports the platform tenant, English organizational
|
|
|
|
|
`approve` memos at the current renderer release, and the intake's nonempty UTF-8
|
|
|
|
|
packet profile. Unsupported projections are refused rather than dropping fields.
|
2026-10-05 00:48:07 +02:00
|
|
|
The admitted State Hub dispatcher performs explicit forwarding. Browser packet
|
|
|
|
|
authoring and handoff preparation now have a source implementation; broader
|
|
|
|
|
L0/L2 binding and automatic discovery remain separate contracts. There is no automatic submitter or default
|
2026-10-04 20:33:24 +02:00
|
|
|
workload credential. A caller-selected submitter is a routing request, not identity.
|
|
|
|
|
The local use of intake's shape validator does not grant admission: intake always
|
|
|
|
|
reauthenticates the workload and reloads its actual grant and recipient mapping.
|
|
|
|
|
|
|
|
|
|
## Immutable snapshot and uncertainty
|
|
|
|
|
|
|
|
|
|
The original lifecycle memo remains unchanged. Intake alone assigns the named
|
|
|
|
|
human and the engine-returned approval pins to the protected review snapshot.
|
|
|
|
|
The snapshot's local version is one; the immutable request and presentation
|
|
|
|
|
content link it to the original source id and revision. The human review page
|
|
|
|
|
shows that source revision. The shared Decision Memo schema and signature rules
|
|
|
|
|
are unchanged; the source link is provenance, not a new authorization claim.
|
|
|
|
|
|
|
|
|
|
Before reserving engine creation and before local loading, intake checks exact
|
|
|
|
|
envelope equality, the designated submitter and source currency. Any change
|
|
|
|
|
fails closed. Existing durable `creating`/`created` receipts retain uncertainty;
|
|
|
|
|
a lost create reply is never automatically reposted. A revision during creation
|
|
|
|
|
can leave an engine object with a retained receipt but no reviewable snapshot.
|
|
|
|
|
This needs existing explicit recovery/reconciliation, not an automatic retry or
|
|
|
|
|
an inferred revocation. Approval Engine remains the sole approval-state owner.
|
|
|
|
|
|
|
|
|
|
Direct import and revision of reserved review snapshot ids are refused. Source
|
|
|
|
|
revisions invalidate subsequent presentation, acknowledgment, disposition and
|
|
|
|
|
entry reservation. Once an entry is in flight or unresolved, source revision is
|
|
|
|
|
blocked until the original attempt is resolved. This serializes local mutation
|
|
|
|
|
against external entry attempts without pretending to make the network atomic.
|
|
|
|
|
Historical accepted evidence remains available; a successor inherits no answer.
|
|
|
|
|
|
|
|
|
|
## Outcomes and human workspace
|
|
|
|
|
|
|
|
|
|
`GET /v1/decisions/{id}/outcomes?version=N` requires a fresh `lifecycle.outcomes`
|
|
|
|
|
check. It returns the correlated intake delivery state, source staleness and
|
|
|
|
|
recorded dispositions with their submission state and confirmation timestamp.
|
|
|
|
|
These are local evidence and transport states, never cached approval validity.
|
|
|
|
|
`prepared`, `in_flight` and `unresolved` are not confirmed acceptance.
|
|
|
|
|
|
|
|
|
|
The workspace displays authorized outcomes and links a ready, current handoff to
|
|
|
|
|
`/review?memo_id=...`. That route still requires its independent review PDP checks,
|
|
|
|
|
verified human identity, fresh presentation and required acknowledgments. Agents
|
|
|
|
|
can prepare, forward and retrieve; they cannot answer. No lifecycle accept route
|
|
|
|
|
exists. Audience access and the named human review entitlement are separately
|
|
|
|
|
checked by their existing policy consumers; a workspace link grants neither.
|
|
|
|
|
|
|
|
|
|
## Evidence and delivery
|
|
|
|
|
|
|
|
|
|
The request event enters the existing lifecycle commitment queue. Intake posing,
|
|
|
|
|
presentation, disposition and submission evidence keep their existing independent
|
|
|
|
|
outboxes and receipt requirements. The integration test creates an approval via
|
|
|
|
|
the real Approval Engine API, records a signed-fixture human entry, retrieves the
|
|
|
|
|
confirmed result for source revision two, and delivers lifecycle and review
|
|
|
|
|
commitments to the real Audit Core receiver. Identity and PDP transport are
|
2026-10-05 00:48:07 +02:00
|
|
|
synthetic. Native initial-audience grants, forwarding, human acceptance and
|
|
|
|
|
restart/audit evidence are recorded in ../evidence/2026-10-05-lifecycle-cutover/.
|
2026-10-04 20:33:24 +02:00
|
|
|
|
|
|
|
|
## Migration and rollback boundary
|
|
|
|
|
|
|
|
|
|
Opening the store upgrades schema 4 to schema 5 transactionally, adding unique
|
|
|
|
|
indexes for review snapshot identity and source revision. Existing evidence is
|
|
|
|
|
preserved. The version change deliberately causes older Store implementations to
|
|
|
|
|
refuse the database: they do not enforce these source guards. Before activation,
|
|
|
|
|
retain the normal database backup and image/config pins. An older-image rollback
|
|
|
|
|
requires a compatible restored database plus reconciliation of any subsequent
|
|
|
|
|
engine side effects; it cannot safely discard new review/entry evidence. A
|
|
|
|
|
reviewed forward fix remains preferable once new handoffs have been written.
|
2026-10-05 00:48:07 +02:00
|
|
|
|
|
|
|
|
## Browser authoring and retained handoff retrieval
|
|
|
|
|
|
|
|
|
|
New browser drafts explicitly select organizational human approval or discussion
|
|
|
|
|
only. Existing rendered forms without that field retain the earlier draft type;
|
|
|
|
|
there is no silent conversion of existing records. Discussion drafts cannot
|
|
|
|
|
enter the approval handoff. The shared structural profile check is descriptive,
|
|
|
|
|
not an authorization grant.
|
|
|
|
|
|
|
|
|
|
A text document is appended through the shared revise command with its actual
|
|
|
|
|
UTF-8 bytes, digest and optional required highlight. The complete form is limited
|
|
|
|
|
to 64 KiB by the existing adapter; large/binary packets remain available through
|
|
|
|
|
the bounded API. Previous packets and highlights are preserved, and a new
|
|
|
|
|
revision requires new publication. Comparison shows changed documents/digests
|
|
|
|
|
and acknowledgment text as well as the question and brief.
|
|
|
|
|
|
|
|
|
|
The browser prepares the same immutable request with an explicit approval purpose
|
|
|
|
|
and responsible principal. Its initial routing is State Hub / decision-record /
|
|
|
|
|
net-kingdom-admins. This route is checked by the existing PDP, and intake still
|
|
|
|
|
authenticates the actual submitter and assigns the configured named recipient.
|
|
|
|
|
Preparation alone does not enqueue, create an approval, notify or bind.
|
|
|
|
|
|
|
|
|
|
`GET /v1/decisions/{id}/review-requests?version=N` returns the exact retained
|
|
|
|
|
`event_id`, `review_memo_id` and `envelope`. It requires a fresh `lifecycle.events`
|
|
|
|
|
decision for that revision, preserving the permission already required to read
|
|
|
|
|
the envelope in history. Missing requests return 404; invalid/nonpositive versions
|
|
|
|
|
return 400. Reads do not create requests or repeat external effects. Historical
|
|
|
|
|
exports remain historical: intake refuses a stale source revision.
|
|
|
|
|
|
|
|
|
|
The browser equivalent `/decisions/{id}/review-request?version=N` downloads
|
|
|
|
|
only the envelope as an attachment. It uses the same service check, without
|
|
|
|
|
credential copying or a public privileged forwarding API. A prepared current
|
|
|
|
|
request links to this download; a loaded request links to protected human review.
|
|
|
|
|
The original idempotency identity survives download, retry and process restart.
|