carlos / platform Public

Serialize worker revocation against each assignment publication

Paul Campbell pushed by paul@keymail.dev 76414c08bfd9927503e8f57c894ec53c00652424 parent 38326fa
1 file changed, +50 −28
  • implementation/maintenance-worker-identity/proposal.json +50 −28

CI passed — run details

diff --git a/implementation/maintenance-worker-identity/proposal.json b/implementation/maintenance-worker-identity/proposal.json
index 52c5d5aca..d0a64d9e1 100644
--- a/implementation/maintenance-worker-identity/proposal.json
+++ b/implementation/maintenance-worker-identity/proposal.json
@@ -1,30 +1,52 @@
{
- "status":"Proposed integration contract; no authenticated worker or endpoint implemented by this file",
- "parent":"Maintenance protocol5f18cdd / platform117; Fable investigations worker-identity-design and worker-identity-design-r2 are proposals, not approvals",
- "scope":"Initial shared/root platform boxes only, exactly one eligible enrolled box for the target region/pool. Customer fleet targets and ambiguous multi-box placement refuse. Do not distribute deployment decryption keys to customer machines.",
- "enrollment":{
- "registry":"Reuse fleet_boxes token-hash convention but distinguish ops-owned platform fleets with additive fleets.kind='platform'; legacy/default kind='' remains customer. Never infer kind from name or reinterpret an existing customer fleet named platform.",
- "generation":"Add credential_rev, changed on admit/reactivation/token/status mutation, independent of tag rev. All increments guard signed-int64 overflow. Durable per-box enrollment head in deployment store binds current generation and token hash; fresh SQLite record must match it exactly. Snapshot rollback cannot restore authority. Recovery through explicit owner admit advances from durable head generation, not lagging SQLite.",
- "authority":"Only current human ops-account owners may create platform-kind fleets or admit, read credential metadata, rotate, detach or tag platform workers. Check actual principal kind plus current RoleOwner via apiSystemOwner. Account membership alone is insufficient. Existing CLI/browser fleet mutators must route platform-kind changes through the worker coordinator, or refuse them; no raw token rotation/status bypass.",
- "isolation":"Platform-kind fleets excluded from tunnel auth, store-door maps, customer placement and ordinary app creation placement. Existing customer fleets retain behavior and API defaults.",
- "bootstrap":"Updated platform worker generates a per-box 32-byte random credential once in its protected local state, persists with exclusive creation/0600 and checked fsync before publication. Publish only token hash plus label/placement/random candidate ID. Ops-owner carlos workers admit selects a concrete candidate and confirms current inventory/placement; worker polls supported self endpoint. No plaintext token in console, terminal, logs or enrollment object. Existing credential is never silently replaced on process restart.",
- "console_discovery":"Console publishes an authenticated deployment console-origin record using existing platform release signing primitives; worker validates against its existing root release public key. This requires explicit format/domain review before implementation, and cannot be replaced with an unsigned bucket URL.",
- "rotation":"Explicit owner detach/re-admit, with a new candidate ID and fresh credential generation. No automatic self-reactivation. All owner mutation commands must deliver and verify completion through CLI/API without follow-up box administration. Bootstrap agent polls are product implementation, not instructions for a user to SSH."
- },
- "assignment":{
- "owner_box":"Use stable logical box label (existing valid 1-32-character name), not fleet/label or fleet name. Existing guard continuity keeps OwnerBox fixed; replacing physical hardware under the same logical label requires explicit owner re-enrollment and a new credential generation. Changing logical label for an existing guard is unsupported until a reviewed guard migration.",
- "immutable":"Server creates assignment bound to deployment origin, fleet/kind/account, logical box label, enrollment generation and token-hash identity, app/account/host, request/attempt, record identity/revision and exact placement observation. Request body copies do not select principal or assignment.",
- "placement":"Region/pool metadata only establishes eligibility. Target refuses unless exactly one active enrolled shared/root worker matches authoritative deployment placement and current inventory. No first-claim selection. Owner approval binds assignment digest. Serving authority additionally requires global guard/projection, proven local stop and continuously retained per-host lease; enrollment never proves stop or lease ownership.",
- "stop":"Use reviewed FenceAndStop and retained lease/executor evidence; missing activator entry is not stop evidence. No remote stop or inference from elapsed lease TTL. Checked quiescence must precede execution."
- },
- "publication":{
- "fresh_auth":"Authenticate bearer against freshly read registry and durable enrollment head on every self/preflight/outcome request; derive deployment/box/generation server-side. Never use cached tunnel auth or human/service CLI tokens.",
- "serialization":"Initial coordinator is a single console instance. A checked exclusive process lock over its registry plus per-worker in-process lock spans fresh authentication, payload/receipt persistence and terminal pointer CAS, and also owner enrollment/rotation/revocation. Admission explicitly refuses a multi-console deployment. Lock failure disables worker mutation endpoints; it must not degrade to unlocked operation. This is a scoped single-console contract, not a distributed lock claim.",
- "durable_revocation":"Before changing SQLite or returning successful revocation, persist create-only tombstone for the old generation and CAS durable enrollment head. Authenticate/publication refuse tombstoned generation even after registry restore. Crash between store and SQLite fails closed. No auto repair from stale row. Owner re-admit uses current durable head as generation floor.",
- "linearization":"Terminal pointer CAS while serialized and current active generation is the acceptance point. Revocation waits for an in-flight publication to finish its CAS or fail. A historical accepted result remains accepted after later revocation; result readback checks its immutable generation binding and accepted attempt, not current token activity. This does not retroactively cancel a result accepted before revocation.",
- "binding":"Persist bounded encrypted payload create-only, derive exact immutable receipt digest, verify all scope/assignment/approved artifact/environment/input/recipient refs and checked worker execution evidence, then CAS only the matching attempt pointer. Changed replay conflicts; identical publication-ID retry is idempotent. Neither arbitrary bucket writes nor body booleans establish accepted execution.",
- "limits":"Direct root edits or hostile broad deployment-store writers are outside existing platform trusted-writer boundary; do not claim this mechanism protects tenants from a compromised platform root. Separate console IAM is a tracked platform security improvement. Worker enrollment does not fix cross-tenant shared-UID issues126/127."
- },
- "review_questions":["Confirm single-console admission/locking can be mechanically enforced from actual console deployment metadata, not an unchecked configuration boolean; otherwise publication needs distributed serialization before mounting.","Confirm existing signing library supplies a suitable authenticated console-discovery envelope without new worker receipt authority.","Verify every platform-kind fleet mutation and auth/placement reader is covered, and durable generation recovery is safe across each crash boundary."],
- "required_tests":["customer namespace collision preserved","member/service/other-account owner denied platform enrollment","platform worker token never accepted by tunnel/store door","stale/rotated/detached/token-swapped generation denied from fresh registry plus durable head","snapshot rollback cannot revive revoked generation","wrong box/request/attempt/placement publication denied","revocation racing publish respects acceptance boundary","publication crash/idempotent retry and pointer conflict","single-console lock/admission refuses unsupported topology","bootstrap restart preserves credential and duplicate/conflicting candidates refuse"]
+ "status": "Revision2 proposed; supersedes rejected38326fa7. No runtime worker or live credential.",
+ "parents": "Maintenance protocol5f18cdd / platform117; Fable investigations worker-identity-design and worker-identity-design-r2 are proposals, not approvals",
+ "scope": "Initial shared/root platform boxes only, exactly one eligible enrolled box for the target region/pool. Customer fleet targets and ambiguous multi-box placement refuse. Do not distribute deployment decryption keys to customer machines.",
+ "isolation_prerequisite": "Do not create/persist/activate worker credential or accept private maintenance input on a box with unisolated tenant processes. Existing isolated-exec design revision13 (platform126) owns tenant mount/PrivatePIDs/IMDS/cgroup isolation and must supply observed runtime/layout checks. File0600 owned by carlos cannot isolate secrets from current flat same-UID children. No competing isolation implementation or unchecked feature boolean.",
+ "identity": "Dedicated maintenance workers, not customer fleets. Reuse canonical per-box token-hash/label conventions only; never put worker credentials in fleet_boxes or human/service auth. Therefore existing fleet tunnel/store/placement doors cannot confer worker authority and need no platform-kind extension. Customer fleets remain unsupported.",
+ "authoritative_storage": "Deployment store only for worker admission/revocation and publication state; SQLite never supplies authority or monotonic generation. Existing trusted control-store boundary applies: root signatures authenticate writers but do not by themselves prevent replay of old signed objects by a privileged store administrator. Do not claim anti-rollback against that stronger attacker.",
+ "head": {
+ "key": "control/maintenance/workers/<logical-label>/head.json",
+ "wire": "Closed bounded root-signed control record using existing release signed-wrapper/signature mechanics, disjoint required kind/schema. Contains deployment origin, ops account, logical label, physical box identity digest, generation, token hash, status(active/revoking/detached), placement, candidate identity/digest, audit metadata, and at most8 registered immutable assignment references.",
+ "updates": "Create-only first admission. Every update uses exact head ETag CAS. Generation advances only on explicit owner re-admission and refuses overflow. Assignment registration CAS requires active head and matching generation. Revoking/detached head cannot register assignments or authenticate new requests.",
+ "label": "OwnerBox is stable logical box label, preserving guard rules. Inventory-friendly labels collide in status.Label; candidate also binds physical box identity digest. Initial collision refuses; physical replacement requires explicit owner re-admit selecting current head and expected old identity, new candidate and generation. Never silently reinterpret a label.",
+ "owner": "Every admit/detach/read administrative door requires current human ops owner through actual apiSystemOwner. Human/service CLI tokens cannot authenticate worker publication. Authenticated worker endpoint derives deployment/box/generation from verified head and bearer, never body strings."
+ },
+ "assignment_state": {
+ "key": "control/maintenance/assignments/<assignment-id>/state.json",
+ "purpose": "One authoritative typed server-internal CAS record per immutable assignment, covering preflight, compatibility intermediate, execution outcome and resume publication. Their accepted references live in this record so each publication and revocation contend on THE SAME object, independent of console count.",
+ "wire": "Bounded closed object with immutable assignment digest/scope/enrollment generation, monotonic revision, disabled flag, and fixed optional accepted preflight/compatibility/execution/resume references. No generic object key/write API. Type validators enforce approved protocol per-kind field/phase rules. Only trusted console code writes it; no offline worker receipt format is added.",
+ "create": "Create immutable assignment and initial state, then CAS active worker head to register its exact reference. Until registered, state grants no execution/publication authority. Failed registration leaves inert orphan. Immutable assignment binds record/account/app/host/request/attempt/placement/worker generation; owner approval later binds exact preflight and assignment.",
+ "publish": "Authenticate current head and registered assignment; read enabled assignment-state snapshot. Recompute/verify approved request/record/artifact/environment/input/recipient/worker-evidence bindings, persist encrypted private payload and immutable receipt create-only. CAS accepted reference into the SAME enabled assignment state using its ETag. This CAS is the acceptance point. CAS conflict requires fresh validation; never retry against a disabled snapshot. Identical publication-ID retry is idempotent; changed bytes conflict. Accepted result does not grant serving resume.",
+ "projections": "Guard advances and public status/result projections happen only from accepted authoritative assignment-state refs. A projection alone is never accepted provenance. Missing/delayed projection is unavailable or pending until deterministic reconciliation. Current request/attempt checks prevent old accepted refs from entering a newer operation. Compatibility intermediate and final resume refs remain distinct as approved protocol requires; neither can be replaced with a terminal guard CAS alone.",
+ "close": "Removing a reference from head.open requires assignment state already disabled/closed, preserving accepted refs. A stale in-flight publisher therefore cannot publish after removal. Maximum8 open assignments bounds revocation work."
+ },
+ "revocation": [
+ "CAS head active->revoking, retaining exact open references and generation; this closes new registration/authentication. This starts revocation but does NOT claim all in-flight publication is yet cancelled.",
+ "For each registered assignment, CAS its authoritative state to disabled while preserving accepted refs. Publication and disable CAS share the same object: whichever wins is ordered first. A publisher authenticated before head revoking can still win until that assignment disable CAS; this is an in-flight accepted historical result, never a claim that head change immediately stopped it.",
+ "Keep matching instance guard denied. Where matching guard is Requested/Quiescing/Fenced/Executing/ResumeRequested, advance to Failed/Ambiguous through actual allowed edges, preserving identities/pins. Do not pretend guard change proves process stop or releases lease. Terminal accepted results remain historical. Stale/absent guard is not authorization to construct or alter another attempt; assignment disabled remains authoritative denial and reconciliation closes matching later-created guard.",
+ "Worker coordinator continuously checks assignment/enrollment validity and cancels active supervisor on revocation, uses checked tree termination and retains fence on uncertainty. Fresh owner recovery/resume still requires proven stop, retained lease and checkpoint/checker path; no automatic un-fence or mutation retry.",
+ "Only after all registered assignment states are disabled and matching deny projections reconciled, CAS head revoking->detached and clear open refs. Before then status remains revoking. Any console can idempotently resume a crashed revocation from retained head/open refs, without a process-local lock or second-console assumption."
+ ],
+ "bootstrap": "After observed isolation gate, worker durably creates once a random32-byte token in privatefile.CreateExclusiveDurable storage with protected parent, checked fsync and no replacement on restart. Candidate contains only hash, random candidate ID, physical identity/label and placement; publish through supported agent control-store path. Signed console-origin discovery uses reviewed existing root release signing wrapper, explicit kind, canonical HTTPS origin and persisted monotonic discovery watermark. Ops-owner workers admit selects exact candidate via supported CLI/API; no operator SSH/SSM step. Conflicting candidate/label refuses. Explicit detach/re-admit controls rotation; no self-reactivation.",
+ "assignment_and_execution": {
+ "owner_box": "Use stable logical box label (existing valid 1-32-character name), not fleet/label or fleet name. Existing guard continuity keeps OwnerBox fixed; replacing physical hardware under the same logical label requires explicit owner re-enrollment and a new credential generation. Changing logical label for an existing guard is unsupported until a reviewed guard migration.",
+ "immutable": "Server creates assignment bound to deployment origin, fleet/kind/account, logical box label, enrollment generation and token-hash identity, app/account/host, request/attempt, record identity/revision and exact placement observation. Request body copies do not select principal or assignment.",
+ "placement": "Region/pool metadata only establishes eligibility. Target refuses unless exactly one active enrolled shared/root worker matches authoritative deployment placement and current inventory. No first-claim selection. Owner approval binds assignment digest. Serving authority additionally requires global guard/projection, proven local stop and continuously retained per-host lease; enrollment never proves stop or lease ownership.",
+ "stop": "Use reviewed FenceAndStop and retained lease/executor evidence; missing activator entry is not stop evidence. No remote stop or inference from elapsed lease TTL. Checked quiescence must precede execution."
+ },
+ "new_tests": [
+ "two consoles publishing and disabling the same assignment in every CAS order",
+ "head revocation crash before assignment disable permits only already-inflight race until disable and never reports completed revocation",
+ "preflight/compatibility/execution/resume all use same authoritative state acceptance",
+ "missing head registration/orphan assignment denied",
+ "publication after assignment removed denied by closed state",
+ "all8 assignment refs retained/re-driven across revocation crash",
+ "projection lag cannot turn unaccepted receipt into success",
+ "wrong generation/box/attempt/recipient publication denied",
+ "signed control type confusion rejected",
+ "flat-layout/host-PID-visible tenant denies worker credential activation",
+ "candidate physical identity collision and explicit replacement rules"
+ ],
+ "review_request": "Assess distributed revocation/acceptance invariant and exact fit to approved opaque-reference protocol. In particular publication accept-before-disable stays historical even if projection finishes later; no claim that signed head alone prevents privileged-store rollback. Recommend concrete corrections before implementation."
}