| 1 | { |
| 2 | "status": "PROPOSED interface choices, not authority approval; no implementation or deployment", |
| 3 | "sources": [ |
| 4 | { |
| 5 | "name": "approved-maintenance", |
| 6 | "revision": "6a81dacfe4949520efce8fb55dec1dbec8e43bfd", |
| 7 | "path": "/home/paulca/amadan.net/carlos/platform/.claude/worktrees/overnight-maintenance-design/implementation/maintenance-exec.md", |
| 8 | "sections": [ |
| 9 | "CLI/API surface", |
| 10 | "Private transport", |
| 11 | "Environment pinning", |
| 12 | "Durable guard and lifecycle", |
| 13 | "Resume" |
| 14 | ] |
| 15 | }, |
| 16 | { |
| 17 | "name": "launch-delta-unreviewed", |
| 18 | "revision": "caf47fb", |
| 19 | "path": "/home/paulca/amadan.net/carlos/platform/.claude/worktrees/overnight-maintenance-launch/implementation/maintenance-launch.md", |
| 20 | "note": "4605a54 base approved; caf47 delta has no approval verdict" |
| 21 | }, |
| 22 | { |
| 23 | "name": "platform-foundations", |
| 24 | "revision": "11a303996d5503d29ede77598243ddc66f735279", |
| 25 | "root": ".", |
| 26 | "paths": [ |
| 27 | "internal/maintenance/envelope.go", |
| 28 | "internal/maintenance/input.go", |
| 29 | "internal/maintenance/result.go", |
| 30 | "internal/maintenanceguard/types.go", |
| 31 | "internal/maintenanceguard/store.go", |
| 32 | "internal/privatefile/privatefile.go", |
| 33 | "internal/provision/maintenance.go", |
| 34 | "internal/console/authcli.go:411", |
| 35 | "internal/console/stepup.go:249", |
| 36 | "internal/console/stepup.go:396", |
| 37 | "internal/console/apiconfig.go:251", |
| 38 | "internal/edge/storedoor.go:100", |
| 39 | "internal/host/agent.go:2772" |
| 40 | ], |
| 41 | "note": "This proposal branch is based on this merged revision; these exact existing primitive sources are included in its review archive." |
| 42 | }, |
| 43 | { |
| 44 | "name": "Home-prepared-protocol", |
| 45 | "revision": "7e282e2a363b9cc90cd74dd97809e6613a699af8", |
| 46 | "root": "/home/paulca/amadan.net/oficina/home/.claude/worktrees/overnight-provisioner-prepare", |
| 47 | "paths": [ |
| 48 | "internal/provisioner/prepare_linux.go", |
| 49 | "internal/provisioner/installations_linux.go", |
| 50 | "internal/operator/protocol.go", |
| 51 | "internal/operator/open_linux.go", |
| 52 | "cmd/oficina/main_linux.go" |
| 53 | ] |
| 54 | } |
| 55 | ], |
| 56 | "approved_requirements": [ |
| 57 | "Exact account/app/primary-host scope; no first-visitor authority", |
| 58 | "Private JSON stdin <=65536; argv 1..32 and aggregate <=8192; result <=65536; default timeout300s hard600s", |
| 59 | "Existing CME1 P256/HKDF-SHA256/AES-GCM binding and CMI1 exact-byte framing; no new crypto", |
| 60 | "Input encrypts to deployment secrets public key; result to durable per-request CLI key; console never gets private decrypting key", |
| 61 | "Fresh browser current-owner review, immutable preflight/env/artifact/record/recipient pins; bearer is not fresh consent", |
| 62 | "No execution until matching durable guard+record projection, lifecycle, checked lease/stop/DB/containment prerequisites", |
| 63 | "Private payload expiry24h; immutable nonsecret receipt retained; lost/unpublished output is unavailable or ambiguous", |
| 64 | "Explicit retry and resume; no implicit command rerun or fence clearing" |
| 65 | ], |
| 66 | "new_wire_choices": [ |
| 67 | "All endpoint paths and schema definitions", |
| 68 | "Client-generated separate random request_id and attempt_id before encryption", |
| 69 | "Target GET and two-step server preflight then browser approval", |
| 70 | "Retry creates a linked new PLATFORM request/attempt, with unchanged APP operation bytes; no new app-level authorization", |
| 71 | "Closed pending-local JSON format and explicit file flags", |
| 72 | "Specific resume proposal object and status vocabulary", |
| 73 | "Environment plaintext closed map-entry schema inside existing DirectionEnvironment envelope; this plaintext shape is proposed, not an existing codec", |
| 74 | "Proposed worker publication interface, intentionally unavailable pending authenticated enrollment design", |
| 75 | "Server-derived stable lifecycle OperationID and constant-depth authoritative lineage-head CAS, separate from platform request/attempt IDs and private app operation ID" |
| 76 | ], |
| 77 | "endpoints": [ |
| 78 | { |
| 79 | "method": "GET", |
| 80 | "path": "/api/cli/apps/{account}/{app}/instances/{host}/maintenance/target", |
| 81 | "request_schema": null, |
| 82 | "response_schema": "target", |
| 83 | "authorization": "human-owner-cli", |
| 84 | "success_http_status": [ |
| 85 | 200 |
| 86 | ] |
| 87 | }, |
| 88 | { |
| 89 | "method": "POST", |
| 90 | "path": "/api/cli/apps/{account}/{app}/instances/{host}/maintenance/requests", |
| 91 | "request_schema": "prepare", |
| 92 | "response_schema": "prepared", |
| 93 | "authorization": "human-owner-cli", |
| 94 | "success_http_status": [ |
| 95 | 201, |
| 96 | 200 |
| 97 | ] |
| 98 | }, |
| 99 | { |
| 100 | "method": "GET", |
| 101 | "path": "/api/cli/apps/{account}/{app}/instances/{host}/maintenance/requests/{request_id}", |
| 102 | "request_schema": null, |
| 103 | "response_schema": "status", |
| 104 | "authorization": "human-owner-cli", |
| 105 | "success_http_status": [ |
| 106 | 200 |
| 107 | ] |
| 108 | }, |
| 109 | { |
| 110 | "method": "GET", |
| 111 | "path": "/api/cli/apps/{account}/{app}/instances/{host}/maintenance/requests/{request_id}/result", |
| 112 | "request_schema": null, |
| 113 | "response_schema": "result", |
| 114 | "authorization": "human-owner-cli", |
| 115 | "success_http_status": [ |
| 116 | 200 |
| 117 | ] |
| 118 | }, |
| 119 | { |
| 120 | "method": "POST", |
| 121 | "path": "/api/cli/apps/{account}/{app}/instances/{host}/maintenance/requests/{request_id}/retry", |
| 122 | "request_schema": "retry", |
| 123 | "response_schema": "prepared", |
| 124 | "authorization": "human-owner-cli", |
| 125 | "success_http_status": [ |
| 126 | 201, |
| 127 | 200 |
| 128 | ] |
| 129 | }, |
| 130 | { |
| 131 | "method": "POST", |
| 132 | "path": "/api/cli/apps/{account}/{app}/instances/{host}/maintenance/requests/{request_id}/resume", |
| 133 | "request_schema": "resume", |
| 134 | "response_schema": "resume_proposed", |
| 135 | "authorization": "human-owner-cli", |
| 136 | "success_http_status": [ |
| 137 | 202, |
| 138 | 200 |
| 139 | ] |
| 140 | }, |
| 141 | { |
| 142 | "method": "GET", |
| 143 | "path": "/a/{sqid}/apps/{app}/instances/{host}/maintenance/{request_id}/review", |
| 144 | "request_schema": null, |
| 145 | "response_schema": "HTML immutable nonsecret review", |
| 146 | "authorization": "browser-current-owner", |
| 147 | "success_http_status": [ |
| 148 | 200 |
| 149 | ] |
| 150 | }, |
| 151 | { |
| 152 | "method": "POST", |
| 153 | "path": "/a/{sqid}/apps/{app}/instances/{host}/maintenance/{request_id}/approve", |
| 154 | "request_schema": "approval_form", |
| 155 | "response_schema": "303 Location: /a/{sqid}/apps/{app}/instances/{host}/maintenance/{request_id}/review (same new request; review page renders current status)", |
| 156 | "authorization": "session-CSRF-current-owner-fresh-auth", |
| 157 | "success_http_status": [ |
| 158 | 303 |
| 159 | ] |
| 160 | } |
| 161 | ], |
| 162 | "wire_rules": { |
| 163 | "schemas": "schemas.json; every object additionalProperties=false, all listed fields required; nullable only where declared", |
| 164 | "json": "UTF-8; reject duplicate keys, case aliases, trailing data, invalid/noncanonical encodings, out-of-range/noninteger numbers; parse int64/uint64 without float64. Request JSON schema is not a runtime parser implementation.", |
| 165 | "scope": "Canonical configured HTTPS console origin, exact controlname account/app/host; path selectors and every body selector agree. No alias, wildcard, path route, selector default, environment override or executable path.", |
| 166 | "bytes": "Envelope strings are unchanged canonical StdBase64 CME1; envelope digest is SHA256 of exact ASCII envelope bytes, declared new wire convention. Public hashes never cover argv/stdin/environment plaintext. Recipient is SHA256 of raw P256 public point per existing RecipientFingerprint.", |
| 167 | "caps": { |
| 168 | "prepare_body": 131072, |
| 169 | "status_body": 16384, |
| 170 | "result_body": 98304, |
| 171 | "approval_form_body": 4096, |
| 172 | "worker_environment_publication_body": 2097152, |
| 173 | "private_pending_body": 196608 |
| 174 | }, |
| 175 | "headers": { |
| 176 | "all": "Cache-Control:no-store,no-transform; X-Content-Type-Options:nosniff; exact JSON Content-Type where JSON", |
| 177 | "review": "Referrer-Policy:no-referrer; same-origin form action; no private payload or result data in HTML", |
| 178 | "result": "No caller-specified redirect or ciphertext URL; response uses authenticated console connection" |
| 179 | }, |
| 180 | "errors_http": { |
| 181 | "400": "invalid-request", |
| 182 | "401": "not-signed-in", |
| 183 | "403": "service credentials refused before membership-dependent details; fixed generic body", |
| 184 | "404": "not-found for inaccessible/missing account/app/host/request", |
| 185 | "409": "conflict or result-unavailable", |
| 186 | "412": "precondition-failed", |
| 187 | "410": "payload-expired", |
| 188 | "429": "rate-limited; bounded Retry-After", |
| 189 | "503": "unsupported or unavailable; no worker provenance means unavailable, never assumed success" |
| 190 | }, |
| 191 | "approval_forms": "application/x-www-form-urlencoded; exact fields in approval_form, one value each; reject unknown/duplicate fields. csrf uses existing console field and is never copied into durable approval metadata. Browser Origin/CSRF checks must match normal console/router contract; any stronger Origin rule needs explicit integration tests.", |
| 192 | "metadata_digest": "New proposal: deterministic Go encoding/json serialization of the declared version-1 typed object in schemas.json property order, no indentation or appended newline, normal Go HTML escaping; sorted unique required-contract arrays and sorted unique environment entry names. Compare exact stored bytes for reference digests; no float64 intermediates.", |
| 193 | "approval_endpoint": "The single review/approve path uses the NEW request_id for operation, retry, or resume. Server immutable request kind determines the required operation or compatibility/resume checks. Predecessor is metadata, never substituted into the approval path. Missing/mismatched kind/pins refuses.", |
| 194 | "browser_scope": "Use existing accountApp sqid routing and resolve sqid to exact account before comparing stored scope; sqid is not an account slug. Approval redirects 303 to the same new request review URL /a/{sqid}/apps/{app}/instances/{host}/maintenance/{request_id}/review. Owner and fresh-auth gate order is unchanged. Existing resolver accepts an unambiguous account name as well as sqid; emitted URLs use canonical sqid. accountApp alone is member-readable and insufficient: maintenance handlers must perform the explicit owner gate with identical missing/nonowner HTTP404 before fresh-auth, including missing-app response normalization.", |
| 195 | "predecessor_agreement": "Initial POST /requests requires predecessor=null. Retry and resume require non-null predecessor; predecessor.id equals path request_id and its digest equals that exact predecessor request reference (not an outcome ID). Server resolves that request to its immutable authoritative outcome and current lineage head; every body selector must agree. Missing outcome, stale predecessor or mismatch refuses. New body request_id is distinct from predecessor/path request_id.", |
| 196 | "result_semantics": "GET /result resolves status.outcome from authoritative current request metadata. Pending resume, including compatibility-checked/resume-ready, returns409 result-unavailable; it never returns the intermediate checker receipt as resumed. Before a final outcome status.result_state=pending and result_envelope_digest=null; historical compatibility/evidence refs may be non-null. For final resume outcome, return that final outcome/ref and exact retained checker envelope whose digest is copied unchanged from compatibility_outcome; server verifies both immutable receipts and linkage under the same request/attempt/scope/recipient. No checker output yet or lost output yields409 unavailable; expired private payload yields410. Final failed/ambiguous resume may expose an existing validated checker result but state remains failed/ambiguous and CLI must not report resumed. Operation result semantics remain exact command ciphertext under its final outcome. Result envelope alone never establishes outcome or admission. After final outcome status.result_state=available with non-null digest while payload exists; expiry sets expired and preserves immutable digest/ref, loss sets unavailable without inventing payload. Schema does not force available forever for resumed because private ciphertext expires after24h; resumed admission history persists.", |
| 197 | "required_contracts": "Resume requires1..16 sorted unique names, each matching maintenanceguard.ValidContract lowercase grammar; reject unsorted input without silently normalizing signed request bytes. Require a superset of retained guard contracts before preparing/approving or starting a process. Empty/invalid/duplicate/unsorted/floor-removing sets refuse before any spawn." |
| 198 | }, |
| 199 | "cli": [ |
| 200 | { |
| 201 | "command": "carlos maintenance prepare --account A --app APP --host H --input ABS_FILE --pending ABS_FILE --label LABEL --timeout 300 -- ARG...", |
| 202 | "behavior": "Resolve authenticated target, read private 0600 regular bounded exact JSON, generate IDs/key, SealInput, durably save pending, then upload. Explicit shell-free argv only; worker supplies executable and DB path. No private argv in public status/logging." |
| 203 | }, |
| 204 | { |
| 205 | "command": "carlos maintenance status --account A --app APP --host H --request ID", |
| 206 | "behavior": "Read-only current-owner status. Optional bounded watch polling; Ctrl-C stops polling, not operation." |
| 207 | }, |
| 208 | { |
| 209 | "command": "carlos maintenance result --account A --app APP --host H --request ID --pending ABS_FILE --output ABS_FILE", |
| 210 | "behavior": "Current-owner fetch of authenticated receipt plus exact ciphertext, local binding verification and OpenResult, exclusive durable private output. Never stdout; no arbitrary ciphertext input flag." |
| 211 | }, |
| 212 | { |
| 213 | "command": "carlos maintenance retry --account A --app APP --host H --request OLD_ID --pending OLD_FILE --new-pending ABS_FILE", |
| 214 | "behavior": "Fetch authenticated immutable predecessor outcome; verify exact retained signed input bytes by private hash; generate new platform IDs/key/envelope under new binding, save new pending before POST. New owner approval mandatory. Does not generate new Home operation or signature." |
| 215 | }, |
| 216 | { |
| 217 | "command": "carlos maintenance resume --account A --app APP --host H --request OLD_ID --artifact VERSION --required-contract NAME... --check-input ABS_FILE --pending ABS_FILE --timeout 300 -- CHECK_ARG...", |
| 218 | "behavior": "Allocate new transport request/attempt and recipient key; SealInput preserves private non-serving checker argv and exact JSON stdin; save pending before resume POST. Fixed executable is the pinned serving release. Same browser owner gate approves exact checker ciphertext, artifact/environment/record and required contracts. No CLI approval. Checker command selection must match the reviewed app compatibility contract; arbitrary migration/server argv cannot be relabeled as a checker." |
| 219 | } |
| 220 | ], |
| 221 | "ordering": [ |
| 222 | "Target GET is read-only, human-current-owner authorized. Public deployment encryption key comes from authenticated console Config.SecretsPub source, not silent terminal env override. Pin target artifact signed manifest and record identity/revision; target response is not preflight or approval.", |
| 223 | "Client creates independent cryptographic32-byte request/attempt IDs and per-request result key. Read exact input privately; SealInput with binding Version1/DirectionInput and deployment recipient. App operation IDs remain only inside private signed stdin.", |
| 224 | "Build exact prepare JSON once. Store private key, IDs, fingerprint, exact body, input path/private hash in exclusive0600 pending file outside repositories. Check file sync/close and parent sync before POST. Interrupted file is preserved; a read is not durability proof. Future pending loader must validate all bindings and execute a checked durability barrier before resend.", |
| 225 | "Authenticated POST creates immutable server request bytes and server metadata once. Same request ID with identical body returns same request/digest/expiry. Any differing bytes/scope/recipient/attempt gives409. Lost response resends identical body; do not re-encrypt. Client-supplied predecessor is only a reference and never execution authorization.", |
| 226 | "Coordinator assigns exactly one authenticated enrolled box to immutable request/attempt. Preflight reads existing DB/record/artifact/config without stopping serving, restoring, seeding, or EnsureAdminToken. Worker returns encrypted DirectionEnvironment snapshot plus authoritative preflight facts; console cannot decrypt the map.", |
| 227 | "Immutable request digest is SHA256 of the deterministic server encoding of the validated prepare object; it includes randomized ciphertext/digests but no raw stdin hash. Exact upload bytes remain the idempotency comparison. Each preflight/publication/approval reference digest binds its exact stored immutable bytes. Server builds immutable approval candidate digest from request reference, assignment, preflight reference, exact pins and result recipient; browser displays these nonsecret facts and fixed warning that inputs remain private. Never render arbitrary argv or plaintext hashes. The candidate MUST also bind server-derived lifecycle_operation_id, exact expected lineage-head revision (explicit absent sentinel for initial operation), and exact predecessor request and resolved outcome references (explicit null for initial operation). These typed fields participate in candidate_digest, not merely page display. candidate_revision identifies this immutable candidate, not an independently refreshable head. Step-up replay rereads those exact expectations and CAS cannot substitute a newer head.", |
| 228 | "POST approval: session, CSRF using existing form field csrf (never persisted; step-up injects it from current cookie), current owner byte-identical404, requireFreshAuth last. Existing stepup can replay the session-bound single-use held POST through router; exact candidate digest/revision survives and every owner/pin check reruns. Missing pins never mean approve latest. Browser intent is the original explicit POST, not CLI token auth_time.", |
| 229 | "Worker rechecks current owner authorization and immutable candidate, exact record revision and private merged environment equality, artifact signature/hash, guard/projection/lifecycle and lease/containment before durable executing state and one spawn. The approved private snapshot is actual command environment. Any changed source or pin refuses; no refresh of approval in place.", |
| 230 | "Capture bounded stdout; independently verify Wait, process-tree cleanup, lease, DB, checkpoint/restore and semantic receipts. SealResult is only encryption. Publication and terminal outcome require the authenticated-worker path below; missing publication never becomes invented empty success.", |
| 231 | "CLI fetch verifies authenticated server outcome and stored reference digest, assigned worker provenance established server-side, request/attempt/scope, approved record/artifact/environment/input ciphertext hashes, recipient and terminal outcome, then decrypts. Save output durably before optional explicit key cleanup; failed output retains pending key.", |
| 232 | "Home completion adapter additionally checks existing signed app receipt against retained installation/role/generation/authorization stream and exact prepared operation. It finalizes encrypted result record and independent floor before accepted-head CAS. A local parseable file, CME1 success, or browser approval alone cannot advance Home accepted state." |
| 233 | ], |
| 234 | "worker_provenance": { |
| 235 | "status": "UNRESOLVED DESIGN DEPENDENCY; no endpoint may publish accepted execution until this is implemented and reviewed", |
| 236 | "existing_options": [ |
| 237 | { |
| 238 | "source": "internal/edge/storedoor.go:100 and TunnelHub.VerifyDynamic", |
| 239 | "facts": "Dynamic fleet name plus bearer validated against current fleet box table; fleet account mapping checked. Store door excludes control/maintenance and instance record writes. A narrowly scoped typed endpoint could reuse verified fleet identity, but token/enrollment is not universal and cached revocation semantics require explicit review." |
| 240 | }, |
| 241 | { |
| 242 | "source": "internal/host/agent.go:2772 openDeployStoreEnv", |
| 243 | "facts": "Shared/root boxes currently prefer deployment bucket/directory credentials. These are broad store access, not an authenticated per-box worker result channel. They cannot establish exact worker origin by themselves." |
| 244 | } |
| 245 | ], |
| 246 | "minimum_new_interface": { |
| 247 | "authentication": "AuthenticateWorker(request) must derive current deployment_origin, box_id and enrollment_generation from real supported enrollment, never body strings. Authority to create enrollment and revocation propagation remain unresolved. Do not mint universal credentials or reuse human/service CLI token.", |
| 248 | "assignment": "Read immutable server assignment bound to deployment/box/account/app/host/request/attempt, current placement and current owner approval. Wrong box, revoked enrollment, stale generation or lost lifecycle cannot publish.", |
| 249 | "paths": [ |
| 250 | "POST /internal/maintenance/assignments/{assignment_id}/preflight", |
| 251 | "POST /internal/maintenance/assignments/{assignment_id}/outcome" |
| 252 | ], |
| 253 | "preflight_body": "schemas.json preflight_publication; principal/assignment supplied by server context, body copies must agree. Proposed environment_private plaintext is bounded to existing MaxEnvelopePlaintext=1048576, with unique variable names; empty values allowed. This plaintext schema needs review and adds no new encryption format.", |
| 254 | "outcome_body": "schemas.json outcome_publication; publication_id is random immutable receipt identity, reused byte-exact after lost response. All reference digests rederived and checked; no generic bucket-key or result-upload CLI endpoint. Missing result envelope cannot assert success; empty application results depend on reviewed app contract, Home rejects empty. Checked worker coordinator, not an HTTP boolean, establishes execution_evidence.", |
| 255 | "publication": "Store private encrypted payload create-only, finalize immutable receipt with its digest and exact approved refs, then CAS current attempt terminal pointer only for assigned generation. Crash before pointer leaves orphan ciphertext/receipt, no accepted outcome. One publisher; identical retry idempotent, changed receipt conflict. Compatibility-check success in a resume request is intermediate: CAS only the historical compatibility_outcome reference, never the final status.outcome pointer. The resume_checker_transport publication and result_semantics rules specify the subsequent final receipt and unchanged ciphertext linkage.", |
| 256 | "readback": "Console result handler resolves current attempt and immutable receipt through trusted internal store and verifies receipt/payload digests plus authentication provenance. Human CLI may read ciphertext but cannot publish outcome. No signed offline worker receipt format is invented here." |
| 257 | }, |
| 258 | "opaque_references": "worker_assignment, worker_evidence, execution_evidence and resume_ready_evidence are opaque server-internal immutable references. Their storage encoding and validator are dependencies of the future enrolled-worker coordinator, not wire objects defined here and not assertions of an existing assignment store. Server computes/checks ID and SHA256 over exact retained internal bytes. CLI compares authenticated references for binding only; it cannot independently validate their contents or present them as credentials. No worker token, signature format, endpoint authority or offline proof is introduced." |
| 259 | }, |
| 260 | "retry_and_cancellation": { |
| 261 | "upload_disconnect": "Unknown acceptance: recover same pending and repeat exact original prepare. No operation starts without browser approval.", |
| 262 | "preflight_timeout": "Remains unavailable/refused without app mutation; no signature, Home expiry, input expiry or approval expiry extension.", |
| 263 | "execution_disconnect": "HTTP client disconnect does not cancel durable worker ownership. Worker timeout/lease loss invokes checked stop and publishes failed/ambiguous when possible; never automatically retries.", |
| 264 | "retry": "New platform request linked to immutable predecessor receipt. Same exact app stdin/argv required: client validates retained private hash; worker independently compares decrypted predecessor input with new input while private predecessor payload exists. Expired/missing predecessor payload refuses retry; operator may prepare a separately reviewed recovery request preserving Home idempotency, never rewrite old authority. No fresh Home signature is generated by carlos.", |
| 265 | "concurrency": "One exact active request per retained lifecycle ownership. Concurrent retries may prepare but only approved matching claim can execute; no last-writer-wins head. Existing incomplete lifecycle claim must be recovered explicitly rather than stolen.", |
| 266 | "resume": "Original operation may have succeeded, failed, or become ambiguous; resume eligibility requires checked stop/containment and a NEW independently successful app-specific non-serving compatibility-check command from the pinned serving release, under the retained guard/lifecycle/lease. Private checker argv/stdin use unchanged CMI1+DirectionInput; stdout uses CaptureResult+SealResult to the newly durable per-request CLI key. Approval pins exact checker ciphertext, artifact/manifest, environment snapshot, record identity/revision, predecessor and required contracts. Validate checker exit plus app-specific compatibility result, then integrity and final checkpoint/restore evidence. Publish immutable resume-ready evidence while guard remains in the existing ResumeRequested phase; do not invent a new guard enum. Only then start exact serving artifact and hand lease to replication, verify health/version, and CAS matching resumed guard+projection. Failure keeps serving admission closed. Migration success is not compatibility proof; checker cannot rerun the original mutation. On final checker/handoff failure use existing ResumeRequested -> Failed/Ambiguous transition with same request/attempt/pins; only a new explicitly approved attempt may then resume from that phase.", |
| 267 | "expiry": "Server immutable payload expiry24h from first accepted upload; idempotent resend never extends it. Proposed preflight review expiry5min; expiry requires fresh preflight/new candidate and explicit review, never silently renew old consent. Execution must begin before candidate expiry; child and operation deadlines independently bounded." |
| 268 | }, |
| 269 | "Home_integration": { |
| 270 | "actual": "7e native prepare emits exact signed JSON on inherited anonymous write pipe only, after local journal+floor durability, with public state local-request. It is not a regular-file writer or network submit command.", |
| 271 | "needed_adapter": "A future native submission adapter supervises that pipe, captures <=65536 exact bytes with cancellation, writes exclusive private input file, then invokes shell-free carlos prepare or its library. No terminal redirect of secrets, no LLM handling. On capture cancellation replay exact saved Home request.", |
| 272 | "actions_ready": [ |
| 273 | "directory.initialize", |
| 274 | "credential.owner-seed", |
| 275 | "directory.seed-team", |
| 276 | "directory.provision-consumer" |
| 277 | ], |
| 278 | "actions_refused_until_evidence": [ |
| 279 | "directory.verify-consumer", |
| 280 | "directory.activate-consumer" |
| 281 | ], |
| 282 | "launch": "caf47 unreviewed context owns fd3 and verified artifact fd4; platform hashes exact stdin and binds request/record/artifact/env plus DB identity/deadline. Home verifies private signed stdin, role/origin/action from approved pinned environment, exact opened SQLite file and self executable. Home cannot independently compare worker-owned expected environment/record digests against invented duplicated flags.", |
| 283 | "authority": "Home operator signing/floor, platform browser owner approval, worker execution provenance and application result verification are separate checks; none substitutes for another.", |
| 284 | "completion_classification": "Only authenticated execution_kind=operation outcomes for the exact prepared Home mutation may advance its accepted authorization head. Compatibility-check and resume receipts are separate proof/history and cannot be consumed as successful mutation results." |
| 285 | }, |
| 286 | "dependencies_before_mount": [ |
| 287 | "Review this new wire proposal; caf47 launch delta remains unapproved", |
| 288 | "Concrete shared/root and fleet worker authentication/enrollment with revocation and exact assignment publication path", |
| 289 | "Immutable request/approval/attempt storage and CAS terminal state machine; receipt validators and durable private-payload expiry", |
| 290 | "Complete all ordinary writer/lifecycle/config/adoption/always-awake admission fences; record serialization alone is insufficient", |
| 291 | "Actual worker preflight environment capture/compare and signed artifact, existing DB, lease/cgroup/checkpoint/restore/semantic-receipt executor", |
| 292 | "Checked resume and durable supported-contract floors across startup/adoption/rollback", |
| 293 | "Native pending-file format/loader checked resume-durability barrier and Home submission/completion adapter; supported non-Linux custody still absent", |
| 294 | "Independent whole-code review, native/cross/CI and isolated deployed rehearsals before any real DB operator invocation", |
| 295 | "Actual app-specific non-serving compatibility checker in pinned serving artifact, private checker-result validator, and resume-ready evidence publication; prior mutation success cannot satisfy this" |
| 296 | ], |
| 297 | "acceptance_cases": [ |
| 298 | "Changed request/attempt/scope/direction/recipient rejects existing envelope; existing golden vectors unchanged", |
| 299 | "65536 input/result exact boundary succeeds; 65537 refuses; JSON/metadata/base64 expansion is accounted separately", |
| 300 | "Crash or sync failure before pending durability makes zero upload calls; reopen alone cannot permit upload; same-ID changed bytes conflict", |
| 301 | "Lost upload reply plus repeated exact request returns same IDs/digest/expiry, not duplicate command", |
| 302 | "Every service role refused; nonowner byte-identical404; stale browser with validCSRF still steps up; missingOrigin/crosssite POST refuses; ownership changed during stepup refuses", |
| 303 | "Changed approval digest/revision, record ETag, artifact hash, box overlay or recipient prevents spawn; no EnsureAdminToken or restore side effect in preflight", |
| 304 | "Worker publication by CLI bearer, wrong/revoked/unassigned box or naked result ciphertext never produces accepted outcome; orphan payload/receipt does not advance terminal pointer", |
| 305 | "Cancelled stdout capture, child never readsstdin, descendant holds pipe, overflow, nonzero exit, lost lease all terminate/check containment and preserve ambiguity correctly", |
| 306 | "Result wrong authenticated receipt/ref/ciphertext digest/binding refuses before output; exclusive output existing/symlink/failedsync never overwrites or deletes pending key", |
| 307 | "Retry binds immutable predecessor, unchanged app bytes, new explicit approval, same app operation; no counter/signature regeneration, no expiry extension", |
| 308 | "Resume cannot run mutation; every partial guard/projection/startup/replication write keeps admission closed until both resumed records and health agree", |
| 309 | "Home actual prepared pipe to private input and byte-exact stdin preserved; received ciphertext without authenticated outcome cannot finalize encrypted result/floor/accepted head", |
| 310 | "Existing record without projection remains compatible; malformed projection protects existing registry state without new serving authority", |
| 311 | "Fresh actual shared-box/fleet enrollment and revocation rehearsal required; static synthetic WorkerPrincipal fixtures are not provenance proof", |
| 312 | "Failed/ambiguous original mutation can reach resume only after independent compatibility checker plus integrity/checkpoint success; successful original migration without new checker cannot resume", |
| 313 | "Checker wrong argv/serving artifact/ciphertext/recipient/environment/record pins prevents launch; checker failure, malformed output, timeout or lease loss prevents resume-ready", |
| 314 | "Retry/resume new request+attempt retain same trusted lifecycle OperationID; forged root, missing head, stale predecessor or simultaneous forked approval cannot replace claim or execute", |
| 315 | "Lineage lookup uses bounded current trusted references, never arbitrary-depth predecessor traversal; crash during head/guard/projection updates stays fenced", |
| 316 | "Maximal 32-argument CMI1 frame73868 bytes plus CME1 overhead97 yields98620 base64 characters, accepted by both input schema fields; old98616 cap rejects it.", |
| 317 | "Browser sqid resolves through accountApp; mismatched stored account refuses before fresh-auth and 303 returns exact review route.", |
| 318 | "Changing lifecycle OperationID, expected head revision or predecessor outcome invalidates candidate_digest and held-POST approval; no latest-head substitution.", |
| 319 | "Retry null predecessor and retry/resume predecessor differing from path reject before draft creation; predecessor digest means request reference, not outcome reference.", |
| 320 | "Resume-ready has no final outcome and GET result returns409; final resumed outcome links immutable checker outcome/evidence and returns unchanged checker envelope. Failed handoff never reports resumed or clears guard.", |
| 321 | "Failed checker publishes final failed/ambiguous outcome with null compatibility/evidence references and transitions ResumeRequested to Failed/Ambiguous; fresh new resume from that phase succeeds only with all new approval/execution checks.", |
| 322 | "Empty/invalid/duplicate/unsorted required contracts and attempts to remove retained contracts refuse before any process starts." |
| 323 | ], |
| 324 | "lifecycle_lineage": { |
| 325 | "stable_identity": "Server derives lifecycle_operation_id from the retained trusted initial request anchor (proposed equal to initial platform request_id) and existing Guard.OperationID/lifecycle claim. New retry/resume request_id and attempt_id never create a new app claim or replace OperationID before Resumed. Caller has no lifecycle-operation-ID write field.", |
| 326 | "lookup_bound": "At most four bounded trusted objects: current lifecycle claim/head, current guard, root anchor, exact current predecessor receipt. Head/root references are server-maintained CAS data outside app prefix; no recursive traversal of caller-supplied predecessor links. Missing/inconsistent lineage refuses. History remains immutable but is not walked to authorize a request.", |
| 327 | "head_transition": "Preparation can create competing drafts without changing active lineage. Approval compares exact expected head revision and predecessor receipt, then CASes single current head for the new request/attempt, bound to same lifecycle operation and guard generation. A lost CAS or stale forked approval refuses before execution. Crash retains explicit incomplete transition for idempotent recovery; no timeout unlock or replacement claim. Candidate digest binds stable lifecycle_operation_id, exact expected head revision and predecessor request plus server-resolved outcome references; step-up replay cannot replace these with current values.", |
| 328 | "source_boundary": "This lookup/head shape is a proposed wire/integration choice; approved guard.validAdvance already requires unchanged OperationID until Resumed. Atomic cross-object transition and crash recovery still need implementation/review; this is not a claim of cross-object atomicity." |
| 329 | }, |
| 330 | "resume_checker_transport": { |
| 331 | "input": "Exactly maintenance.Input{Arguments:CHECK_ARG,Stdin:private JSON}, EncodeInput/SealInput to approved deployment key with new request/attempt and DirectionInput. Worker supplies executable and database path; no caller environment or fd/path authority. Generic limits remain 32args/8192 aggregate/65536 stdin.", |
| 332 | "output": "Exact <=65536 bytes on dedicated stdout, captured to EOF and encrypted with existing SealResult/DirectionResult to new request recipient. App-specific checker JSON/schema and compatibility validation belong to reviewed serving artifact contract. Platform does not accept an arbitrary compatible=true body or a caller-uploaded checker receipt.", |
| 333 | "authority": "Approved serving artifact must actually expose the intended non-serving checker; no guessed Home command or unmounted dispatcher is treated as implemented. Worker executes/checks it under the same fence/lease and authenticated provenance as mutations; independent integrity/checkpoint follows success.", |
| 334 | "publication": "Checker success publishes immutable compatibility-checked outcome with execution_kind=compatibility-check and private checker result. status.compatibility_outcome retains that reference; status.outcome stays null while final resume is pending. Resume-ready evidence links that exact outcome, immutable approval candidate, final checkpoint/restore and exact serving pins. status.resume_ready_evidence is set only after validated publication, with guard still ResumeRequested. After handoff, exact health/version and matched resumed guard/projection, publish a NEW immutable outcome state=resumed, execution_kind=resume, referencing compatibility_outcome and resume_ready_evidence; CAS status.outcome to it. No receipt is overwritten. Final result_envelope_digest is the SAME checker ciphertext digest, encrypted under the same resume request/attempt/key; no second command/output or re-encryption. Historical compatibility receipt stays reachable from final outcome. Failure after checker success may publish final failed/ambiguous resume outcome with existing compatibility/evidence links but never resumed; serving stays fenced. A checker failure publishes final failed/ambiguous execution_kind=compatibility-check outcome in status.outcome, with compatibility_outcome=null and resume_ready_evidence=null; only successful checker validation produces compatibility_outcome. If bounded output was captured and authenticated it may be fetched with the failure outcome; absent output is unavailable, never fabricated. Either checker or later handoff failure advances the matching ResumeRequested guard to Failed/Ambiguous with unchanged request/attempt/pins and next generation, preserving denial and allowing a separately freshly approved new resume. Failed CAS/publication leaves recovery-required uncertainty, never automatic execution or serving.", |
| 335 | "expiry": "Fresh approval and exact checker input expiry are checked independently. No retry/resume extends prior Home authorization, payload expiry, worker lease or operation timeout." |
| 336 | }, |
| 337 | "revision_note": "R3 addresses two new R2 blockers against guard.validAdvance/ValidContracts, plus routing/reference syntax clarifications. R1 seven blockers remain resolved. No implementation or deployment approval.", |
| 338 | "status_and_guard_mapping": { |
| 339 | "authority": "Status is per request workflow metadata, never serving admission authority. Guard phase plus matching projection remains authoritative. Draft retry/resume does not change the predecessor guard. The mapping below distinguishes workflow overlays and guard phases; do not infer absence or clear a guard from draft/refusal/expiry.", |
| 340 | "awaiting-preflight, awaiting-approval": "No new guard transition. Initial request has no fence; retry/resume retains the current predecessor guard and denial.", |
| 341 | "approved": "Owner gesture accepted, before durable requested fence (initial/retry) or ResumeRequested transition (resume); no command may launch from this status. Existing fence remains intact.", |
| 342 | "requested, quiescing, fenced, executing, succeeded, failed, ambiguous": "Operation workflow states map to identical guard phases after matching durable references. Resume checker execution is a substate under ResumeRequested, not a backward move to Executing. Final failed/ambiguous checker or handoff advances ResumeRequested to Failed/Ambiguous with the same request/attempt/pins and next generation, exactly guard.validAdvance. These phases remain denied; subsequent fresh-owner resume uses new request/attempt from Failed/Ambiguous with stable OperationID.", |
| 343 | "resume-requested": "Guard ResumeRequested after fresh resume approval and required CAS; all checker, validation and serving handoff steps remain denied.", |
| 344 | "resume-ready": "Workflow substate only; guard remains ResumeRequested. Immutable checker outcome and resume-ready evidence exist but no resumed claim.", |
| 345 | "resumed": "Only after exact serving health/version, lease handoff, and both matching guard Resumed and record projection. No premature success pointer.", |
| 346 | "refused, expired": "Pre-execution refusal/expiry creates no fence and clears none. Previous active guard remains unchanged. After fence acceptance expiry cannot undo it. Command/lease/checker/handoff failure publishes failed/ambiguous with checked stop evidence and CASes the matching guard to Failed/Ambiguous; uncertainty keeps admission closed. No timeout takeover or automatic retry." |
| 347 | } |
| 348 | } |
| 349 | |