Require exact workspace release proofs and durable cleanup backoff #675
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/anima-a2-release-receipts"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Exact-owner release proof now covers never-bound manager-owned allocations, while cleanup outages/fences remain retryable and partial-work retention has a resource bound.
Targets main independently. Supplies Anima S1; no dependency on output/telemetry. No PR merge, deployment, live recovery or canary.
Review fixes
Manager-owned unbound resources receive first-party deletion/absence receipts; uncertain creates/commands still need explicit reconciliation. Fence waits use durable wait_attempts rather than the12 real-failure escalation counter. An audited admin-only re-arm endpoint resets cleanup without releasing ownership. Temporary partial-work retention on non-retain profiles expires after24h; a30s manager sweep performs UID-fenced deletion, with admin inventory and serialized duplicate expiry. Small owner/audit proof records are permanent by design.
Exact consumer contract
Workspace release v1 (A2; Anima S1)
An authenticated session manager calls
POST /v1/allocations/{session}/release-proof:workspacemay be null before binding. The manager validates the stored principal,profile and exact binding when supplied. It returns a durable
AllocationReleaseProof:State is
released | retained | absent. A non-absent proof namesallocation_idand actual workspace. It requires
executor_receiptor the request ID of anexisting authenticated explicit operator absence reconciliation. The executor
receipt is
{schema_version:1,session_id,workspace_id,generation,receipt_id, released:true,files_retained:bool}; the receipt is saved after fencing new effects,observing no unresolved operations and stopping helpers. The manager saves that
exact receipt before resource cleanup, allowing restart/lost-response recovery
without asking a replacement executor to certify its predecessor's effects.
Explicit operator accepted loss uses the existing nullable field
reconciliation_request_id(a nonempty string), withstate="released".The authenticated manager copies this ID from its durable
allocation_release_attestation/<session>record. That record is written only byadmin allocation reconciliation with
observed_absent=true, statuscompleted,quiescent owners, an exact allocation-request fingerprint and bounded evidence;
the operator/evidence audit remains durable under that request ID. Lost-executor
recovery also verifies resource absence through Kubernetes.
This attestation accepts file loss even if
request.preserve_files=true, sinceretention cannot be claimed after absence. It does not change the requested
preservation intent or fabricate
files_retained=true/a retention deadline.The proof retains the original bound workspace when known. Any requested binding
must still match exactly, including generation;
proof.workspace=nullis validon this path when
request.workspace=null(with a nonnull allocation ID).An empty/missing reconciliation ID cannot authorize this exception. An attached
executor receipt must still identify the exact released session/workspace and
generation; contradictory release/identity receipts are rejected. Receipt-only
preservation still requires the existing retained/files-retained proof.
For a cancelled bound turn whose pod is absent, the supported sequence is admin
allocation reconcile (explicit accepted-loss evidence), admin session cleanup
rearm (exact
expected_first_blocked_at), then the normal cleanup tick. Themanager persists the attested proof and the session lifecycle exposes it with
workspace_released=true. Replays return the same proof, including its audit ID;no replacement executor is asked to certify prior effects. Deploy this #675
follow-up before Anima #801's matching validator. No live recovery is authorized
or performed by this change.
absentis only returned with a null requested workspace, after the manageratomically records a permanent tombstone under the allocation lock. A delayed
Allocate for that session is refused. A bare HTTP 404, missing/Completed pod,
transport failure, old terminal allocation or age is never a new proof. Legacy
manager routes cannot provide the new proof and fail closed during mixed rollout.
The session lifecycle response retains
workspace_released. New optional fields:workspace_release_proof: the validated proof above, durably committed withworkspace_released=true.cleanup:{schema_version:1,first_blocked_at,last_attempt_at,attempts,cause, next_retry_at:u64|null,operator_required:bool}. Times are epoch milliseconds.Cause is allowlisted:
publication_pending,turn_pending,transport,proof_unavailable,unknown_outcome,owner_or_quiescence_conflict,cleanup_busy,cleanup_unavailable. No raw endpoint/error text is included.Cleanup uses a separate attempt counter, exponential 1s..300s durable backoff and
operator-required escalation after 12 failed automated attempts. Repeated ticks
before the saved deadline do not send another release or refresh first-blocked.
The owner fence remains on exhaustion. Existing operator reconciliation remains
explicit; no automatic recovery, claim release or effect replay is introduced.
Pending/unknown repository publications and nonterminal runtime turns prevent the
release call. Failed/cancelled turns request
preserve_files: after exact executorquiescence, the allocation becomes retained with files intact. A resource whose
deletion already started cannot attest later file retention. Existing archive and
core acceptance obligations remain. Consumers must not finalize on
workspace_released=false; historical bool-only receipts remain historical.The brief's WI-568 pointer was checked: current Akh WI-568 is unrelated RSI-1
(
01a14a7c-820c-7d20-b37d-4855572117ad), so no duplicate snapshot path was created.Source synthesis E01/E04/E06 does not establish deployment or live recovery.
Deployment and an authorized canary with original session UUIDs remain pending.
Review additions: non-absent proofs may use
manager_release {schema_version:1,session_id,allocation_id,request_id,resource_uid?,absent_observed:true}only for an unbound allocation the manager itself deleted/observed absent under its allocation lock. Ambiguous outstanding creates/commands still require explicit reconciliation. Absence without any manager-owned allocation remains a tombstone proof.Cleanup now separates
wait_attempts(durable poll backoff) fromattempts(real failures). turn_pending/publication_pending/transport/busy waits never exhaust the escalation budget. Admin-only POST/v1/sessions/{id}/cleanup/rearmaccepts{request_id,expected_first_blocked_at}; idempotent audit and clock guard reset retry counters without releasing ownership.Temporary preserve_files on a non-retain profile expires after 24h (
retained_untilin proof). Manager sweeps up to64 expired allocations every30s after exact executor quiescence, with UID-fenced resource deletion; failed expiry remains visible via admin GET/v1/allocations/retainedand retries. Explicit retain_on_release profiles keep their existing policy. Receipt/proof/tombstone records are permanent small audit/owner-fence records, not bulk captures; expiry does not erase the historical proof and its stated retention deadline.Validation
Current follow-up head:
80464684ecc2b9afb7c9978aab8841d14dc55971.Fable review of Anima #801 reopened this cross-repo case after the earlier #675 approval: cancelled turns request preservation, but operator-attested absence produced a released bound proof which the old validator rejected. The existing nonempty
reconciliation_request_idis now the explicit accepted-loss exception for state=released, with the same exact expected binding checks. It is durably copied from admin reconciliation; no schema field or version is added. A null actual workspace is valid when the request workspace is null. Any supplied executor receipt must still agree on released/session/workspace/generation. Receipt-only retention requirements are unchanged.Anima #801's implementer received the exact field semantics and full dependency head. Roll out this #675 head before the matching Anima validator; no deployment or live recovery was performed.
Prior local validation at operator-attestation head
0363aa65518210a22ca0eb220d269f832ed85350(predates the CI fixture follow-up below):Local receipts: attestation-types-final.log, attestation-services-final.log, attestation-sandbox-final.log, attestation-negative-control.log. Exact-head Solstice CI remains a separate merge gate; no blind rerun or shared CI incident investigation. No merge, force-push, deployment, Talos/Ptah edit or provider canary.
CI4363 follow-up
Normal follow-up head:
80464684ecc2b9afb7c9978aab8841d14dc55971. Main67786deb93a2fe1bc421cbba2477c9c021aea2b0(merged round16 #673) was integrated via ordinary merge7960cbcd046076d70a26b466e3cec10e88fac0cd; round16 paths match main exactly. No force push.Authoritative Solstice request
468c4fe6-e438-4225-a987-ef60b4c69703, categorystep:verify-independent-daemon-profiles-and-platform-contracts, tied to exact old head0363aa65518210a22ca0eb220d269f832ed85350, identifiesarchived_cleanup_cannot_occupy_all_dispatch_workersat tests/sessions.rs:1817: timeout waiting for cleanup notification. The service library passed189 tests/7 ignored, sandbox integration passed6, then sessions integration passed28/failed1. The runner executed the tests; this is a stale mock route, not infrastructure or the new cancelled-bound operator sequence. Reported failing job.The mock now handles
/v1/allocations/{id}/release-proof, consumes the typed request, checks exact session/workspace identity and constructs a validating executor proof before signaling. The regression also asserts no slow cleanup RPC completed before active work dispatches. Original3s/4s timeouts and30s blocked RPC remain unchanged. Production release/attestation contract is unchanged. #676–#678 still use legacy/releasewith matching mocks and do not have this mismatch.Validation: rustfmt and git diff checks passed. Both local attempts stopped during compilation under the disk guard, before any test executed; no local pass is claimed. The focused retry used only
-p akh-session-services --no-default-features --features session,sandbox --test sessions archived_cleanup_cannot_occupy_all_dispatch_workers -j4 -- --exact --nocapture, dev/test debug0 and incremental0. CoS authorized pushing this ordinary commit and using exact-head Solstice CI when it could not fit. CI remains required; no blind rerun. Logs/hashes are recorded in ci4363-source-evidence.json and ci4363-validation.json.Own target was verified without open files and deleted;32.83GiB free after cleanup, peer targets untouched. Guard stop31.30GiB preserved the31.25GiB floor. Anima #801 implementer was sent the new full head for its dependency pin;
reconciliation_request_idsemantics are unchanged. No PR merge, deployment, live recovery, Talos change or Ptah implementation edit.