Conversation
…d runner enforcement Adds the F1 execution fence: a persisted deployment-wide fence (open / draining / migration-locked / proof-only) in a new flowsafe_execution_fence D1 table with CAS transitions and proof-run binding, admin control routes on the maintenance-admin trust boundary, and fail-closed enforcement at every execution entry - run start and resume (runtime chokepoints plus pre-write DO route checks), schedule authoring and the pre-claim tick read, signal ingestion with a wake-to-persist degrade while draining, notification dispatch, approval decide ahead of the decision CAS, goal mutations, the background-task dispatcher (registration split from fence-gated dispatch startup so nothing claims under a lock; in-flight bodies suspend and resume after reopen), and the suspension-deadline alarm lane (uncharged, watchdog cadence). Seeding writes an explicit fence row with a required, defaultless initial state, healed on every protocol invocation: threaded through the deployment-identity protocol, seedDeploymentIdentity, the flowsafe-provision CLI, and fleet-control's provisioning surface and backend contract (kept out of the deployment spec digest). Refusals carry the stable EXECUTION_FENCED reason code end to end, including through the agent-host and stream routers. The workerd spike proves draining and locked refusals, decide-not-committed, kill/restart persistence, and reopen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… harden the fenced task-host lifecycle The fence option becomes a required ExecutionFenceWiring (store | 'none') on all eight leaf option types, resolved through one readExecutionFence authority, so an unwired surface is a compile error instead of a silently open one; every in-repo host (agent-starter including its conformance artifacts, spike, host-kit composition) now wires a real store. BackgroundTaskHost.manager is private behind a narrow read surface plus the fence-gated enqueue, so no path registers an ungated executor. The fenced boot lifecycle is hardened: boot and dispatch attempts are recorded synchronously (closing a shutdown race during the fence read and a double start/init interleaving between request and alarm boots), and the post-reopen resume sweep converges - boot-paced, alarm-budgeted, paged with restart-on-progress, per-row failure handling for core's concurrency-limit throws. Also: the admin credential gate is one shared function across the maintenance and fence routes; raw fence constants are single-homed on the deployment-identity-protocol subpath; fleet-control's seedDeploymentIdentity takes an options object and provisionDeployment validates the initial fence state at entry; missing-fence-table detection walks error causes; objective clear is exempt from the draining gate like schedule pause/delete; unreadable-fence refusals are pinned to never leak storage error text through the agent-host and stream routers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… and the proof-only producer Adds the start-reservation primitive: a host-supplied idempotency key is reserved in a new flowsafe_start_idempotency table (INSERT OR IGNORE + read-back, owner checked before target so a non-owner learns nothing) and claimed through a single conditional UPDATE that is the cross-isolate serializer - the claim lands before any start executes, so a retry can replay but never re-run. Replay resolves through five states with distinct refusal codes: the persisted run is returned as-is (reconciling, never re-filing, approvals), an unclaimed reservation is re-claimed onto the same server-minted run id, an in-flight start answers 503 PENDING via liveness probes on the owning objects (no timers), a claimed-but-absent run answers 409 UNRESOLVABLE with investigate-first guidance, and a settled-then-purged key answers 409 ALREADY_SETTLED inside a retention horizon floored at the run TTL (purge pairing plus an orphan sweep guarded by snapshot existence). Both start surfaces carry the key over the internal channel only; caller run ids remain refused; the execution fence's proof-only state gains its producer - a start carrying the fence's proof key is admitted and bound to exactly one run inside the runtime - and a fence refusal after the claim rolls the reservation back so a mid-start transition cannot strand keys. The workerd spike proves same-run replay across kill+restart, one run under concurrent same-key starts, and the proof-only admission end to end. Also lands the carry-over batch: shared per-binding fence-store factory, the last unswept approval-service leaf, a compile-time wiring census with negative controls, background-task boot/shutdown lifecycle fixes with a persistent sweep cursor, root-cause-only missing-table detection, the WeakMap test seam, and the admin gate's explicit delegation flag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…leteness guarantee Adds GET /admin/inventory behind the shared admin credential gate: seven work categories that must reach empty for a drain proof (nonterminal runs with owner annotation, waiting approvals, deferred schedule dispatches, due notifications, nonterminal background tasks with a fence-suspended sub-count, unsettled resource owners, open start reservations) and two standing categories reported for reconciliation (schedules, signal subscriptions). Read-onlyness is a property of the type - the database seam exposes no write method - and every category predicate derives from the production reader or purge that owns the same notion, with the terminal-run SQL shared between the retention purge and the inventory so the code that acts and the code that certifies cannot disagree. Completeness is maintained by census, not care: a table registry maps every flowsafe-owned table to a category or a justified exclusion, four census tests fail CI on any drift (uninventoried tables, phantom tables, restated names, declared-table vs issued-SQL mismatches), and genuinely invisible state is declared - the per-run recovery-journal crash window with its bound, and persisted idle signals, which the fence's own degrade rule deliberately carries across a migration for the new deployment to wake. The drain-proof contract ships as a typed constant in the index response: results are a lower bound, the proof is empty work categories across two consecutive sweeps at least one alarm cadence apart, and empty is reachable only from draining. Keyset pagination never skips or repeats, malformed cursors are refused rather than silently restarting a sweep, and the owner-annotation lookup is chunked under D1's 100-bound-parameter cap. An ownership-ordering pin proves in-flight starts stay visible: the reservation lands before the engine's first snapshot and settles only after a summary persists, so no instant exists where both categories read empty. Also: an execution-entry matrix test drives thirteen fence entries across all four states with a source census over all sixteen admission call sites; the wiring census extends to the start-reservation options (exposing and fixing two live defects - the starter's run object built without a reservation store, and thread objects reserving keys they could never settle); the spike proves exactly-once with durable execution counters; principal predicates move to an import-free leaf; a shared bounded cause-chain walker fixes a cyclic-error fail-open; and reservation requests take unknown input validated at the boundary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…inside the lease
ProvisioningBackend gains a required attestActiveRoute (BREAKING): the
provider's own truth about which release is receiving traffic, read-only and
lease-free. Plain backend: deployments.list -> exactly one version at 100% ->
versions.get digest binding (two rate-coordinated reads, no CLI). Workers for
Platforms backend: host routing -> routed script -> dispatch inspect.
attestConvergedActiveRoute bounds KV lag with two independent bounds (60s /
nine retries) and retries refusals; attestFleetRecordActiveRoute is the host
read (cache it). Attestation runs unconditionally on all five promote paths;
provision's ready-commit now commits the ATTESTED version.
Settlement: migrateFleet({ settlementFor }) and rollbackExternalRelease({
settlement }) call the host inside the lease, after attest + match and before
the settling put. settle() is at-least-once keyed by settlementKey; the record
persists settledSettlementKey (generalized nullable-column migration) so
routine converges skip settle but still attest. `prior` is defined per entry
(activeRelease on rollback). Branch A skip-when-settled stays write-free.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0131gd19xxXseRqsuNAjpUC4
…0.20 / fleet-control 0.4 Changesets (flowsafe minor, fleet-control minor) naming every consumer-visible break: required ExecutionFenceWiring on the twelve leaf option types, required initial fence state on seeding/CLI/provisioning, BackgroundTaskHost.manager removed, structured 5xx refusals passed through by the agent-host and stream routers, required startIdempotency wiring, ProvisioningBackend.attestActiveRoute and PlainWorkerRouteApi.inspectActiveWorkerRoute required, seedDeploymentIdentity options object, async provisionDeployment committing the attested version, and fail-closed post-promote attestation on every promote path. Docs: execution fence, idempotent start (all seven codes), drain inventory, control-plane routes, verified fence postcondition, attestation read budget (two reads plain / three Workers for Platforms), the settlement contract as the code guarantees it (at-least-once keyed, no package timeout, lease renews while settle() runs), the deliberate contract deviations, threat-model note, api-reference fleet-control section, do-runner navigation. Carry-over batch: fence-error author census + existsSync-checked delegated pointers; concrete 60s journal cadence; EXECUTION_FENCE_SUSPEND_KEY single-homed in do-runner (background-tasks re-exports); due-notification predicate hoisted into an import-free do-runner leaf shared with notification storage; milestone tokens scrubbed from every file this feature touched; isMissingReservationTable made file-local; showcase uses executionFenceFor; derived-chunk assertion in the 200-row inventory pin; seven-code taxonomy documented with the guard's scope; packed probes for every new flowsafe and fleet-control export; PlainWorkerRouteApi and PlainWorkerCustomDomain moved to types.ts with the client implementing the interface; typed nullable-column migration list; convergence message-shape tests; settlement-key provenance and lease-renewal docs corrected; PENDING_ ARTIFACT_VERSION at the provision sites; platform-only lost-write fixture pins its subphase; positive-control script surfaces spawn errors instead of a JSON parse error. Review-fix cycle: the control-plane route docs state both credential rules (fence and inventory never delegate to fleet capabilities); the alreadySettled JSDoc describes what the code computes (true only when a prior settling write recorded the key; false in the lost-write re-fire window); the drain docs name the enqueue admission under draining and replace the false lower-bound claim with point-in-time semantics; README and fleet-control.md sections re-homed under the right headings; the refusal guard gains a membership test; census walker deduplicated with per-site anchors and an alias-import rejection; scrub-broken comments repaired. Second cycle: DrainProofContract's reading field named for what it is (point-in-time, bidirectional) with the route handler and spike wording aligned; the two 400-class refusals gain reason codes (INVALID_EXECUTION_FENCE_REQUEST, INVALID_START_IDEMPOTENCY_ REQUEST); the census rejects qualified construction, subclassing and aliases and scans .tsx; the changeset names the RunRouterStartIdempotency arm rather than RunRouterOptions; config-table credential split; post-lock re-sweep guidance covers lock-parked work; observed-state propagation pinned. Third cycle: the keyed-start docs count eight reason codes and name the guard's seven-member union distinctly; the fence changeset claims INVALID_EXECUTION_FENCE_REQUEST only for invalid state or proof-key values; the run-owner recovery cadence is pinned by test to its constant; the packed probe covers drainProof.reading; the census rejects qualified inheritance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0131gd19xxXseRqsuNAjpUC4
…n scrub Comment-only. Rejoins the sentence split across lines in background-tasks/host.ts (alarm-wake paragraph) and the orphaned "`at` still" line in approval-api/service.ts sweepSLA. No code tokens change; lint and the flowsafe suite (2665) pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SP4MwdaWpy527Xj3M94F3p
release: version packages
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
anchorage-showcase-single-tenant | 93f0b51 | Aug 25 2026, 07:06 PM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes
devtomainto publish @proofoftech/flowsafe 0.20.0 and @proofoftech/fleet-control 0.4.0 (breakwater stays 0.13.0; agent-starter and showcase are private patch bumps).@proofoftech/flowsafe 0.20.0 (minor)
open/draining/migration-locked/proof-only) with CAS transitions viaPOST /admin/execution-fence,GET /admin/execution-fence, stable503 EXECUTION_FENCEDrefusals, and DO-runner-level enforcement on every execution entry. Newflowsafe_execution_fencetable (absent row readsopen).idempotencyKeyonPOST /runs, trusted agent-host starts, andstreamUntilPersisted()converge on one server-minted run; eight structured reason codes on the keyed-start surface;flowsafe_start_idempotencytable andSTART_IDEMPOTENCY_RETENTION_DAYS.GET /admin/inventory(work vs standing categories),INVENTORY_DRAIN_PROOF,INVENTORY_UNENUMERABLE,FLOWSAFE_TABLEScensus.executionFencewiring is required on every leaf host option type;startIdempotencyis required onRunRouterOptions/AgentThreadTopologyOptions/StorageInitOptions; provisioning requires an explicit initial fence state;BackgroundTaskHost.managerremoved.503/409+reasoninstead of a bare500); refusal message text no longer exposes internal plan identifiers.@proofoftech/fleet-control 0.4.0 (minor)
attestFleetRecordActiveRoute,attestConvergedActiveRoute,ActiveRouteAttestationError): refuses absent, two-version, or mismatched routing — fail closed (BEHAVIOR CHANGE vs 0.3.x).fleetSettlementKey(migrateFleet({ settlementFor }),rollbackExternalRelease({ settlement })),FleetRecord.settledSettlementKeypersisted (nullable column added on first open).ProvisioningBackend.attestActiveRoute()required;PlainWorkerRouteApi.inspectActiveWorkerRoute()required;seedDeploymentIdentity(…, { initialExecutionFenceState });provisionDeployment()requiresinitialExecutionFenceStateand is async on every path.@proofoftech/flowsafepublishes as the exact matching release (0.20.0).Checkpoints on dev: 14c5f88 fence · 6099f78 required wiring + lifecycle · 2aedc85 idempotent start · 0882d25 inventory · 7c5b261 attestation + settlement · 1212ba5 changesets/docs/review carry-over · 39154d2 comment wraps · 93f0b51 version packages. Full 21-step CI-mirror gate green on the versioned dev SHA.
🤖 Generated with Claude Code
https://claude.ai/code/session_01SP4MwdaWpy527Xj3M94F3p