Static release target: StaticRelease binding, carry, atomic flip, control record v5 #2
Loading…
Reference in a new issue
No description provided.
Delete branch "eureka-self/static-release"
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?
Follow-ups
idunn-deploy-provenance:follow_up:chat-mind-20261113T125202436Z-t35andchat-s6737-6737; cut_specidunn-deploy-provenance:cut_spec:cut-static-release-forward.r1. Forward half of Cut A; theidunn rollbackverb is the next cut.[static_release]target declaration andStaticReleaseworkload binding (no unit, no service): a release tree sealed and installed by the existing machinery, a per-site config file carried as a copy at flip time (outside the sealed digest, sha recorded in the flip evidence), an atomiccurrentflip in Starting behind the same brake authorization as a service. A failed flip before the rename ends FailedBeforeFencing withcurrentuntouched; after the rename nothing may abort (retry,last_errorvisible inidunn status).idunn.deployment_transaction.v5, new key 37flip) with the v4 legacy layout, lift on read and history, and the boot migration. Forward-only: an Idunn that predates v5 cannot read a migrated store. Pinned bytes test updated deliberately; v4 fixture kept.Tests: 14 static-release tests plus pinned/lift/migration tests (v4 store on a temp copy boots to v5; v5 untouched); full lib suite 555 passed / 107 failed, the 107 being the root-only tests that fail identically on base (uid 985 host). Soul: first pass found v5 uncommitted, a post-rename abort hole and surviving mutations; all fixed; delta pass accepted
dc86c63; final round (be98521) is a test and docs only.Not verified: root install and harden of a static release, real docker materialize for a static target, any run against a live
control.cc. Known gap: unbounded retry after a flip intent on a permanent fault (follow-up: bounded retry with an operator-decides state). Deploy nothing.🤖 Generated with Claude Code
install_release and validate_installed_release read the release root through WorkloadBinding::release_root(), so a static release installs through the same copy, digest and harden path as a systemd one. StaticReleasePort { observe_current, carry_and_flip } with FilesystemStaticRelease: reads the operator's site file (regular file, not a link, 1 MiB cap) and hashes it before anything moves; writes <release>/<destination> by temp + rename at mode 0444 outside every artifact digest; then renames a fresh symlink over current_link (a stale flip link a crash left is replaced; a real directory in the link's place is never replaced). observe_current refuses a link that names anything but a release under the release root. Tests on a tempdir stand-in site (fake vite dist with .br/.gz twins, fake site config): cargo test -p idunn --lib drivers::tests::static_release_ (5 passed). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>A static release is the same DeploymentTransaction in three phases: Sealing, Starting (carry and flip, behind the deployment brake) and Complete. It has no Expected, activation, workload, warming, isolation, fencing, leasing, ready or routing, and creates no AdmittedGeneration. DeploymentTransaction gains key 37 `flip` (FlipEvidence: release, previous release, carry source, carried sha256, time). Adding a key changes the bytes of every record, and the control store refuses a record that does not re-encode to what is stored, so this is schema idunn.deployment_transaction.v5. The v4 layout is kept as LegacyDeploymentTransactionV4 and lifted by the existing mechanism (read_transaction_record, history decode, and the boot migration, which rewrites v4 records in control.cc to v5). Migration is forward-only: an Idunn that predates v5 cannot read a migrated control.cc. Also: is_static() and brake_subject() (the brake names the binding's runtime id and the sealed release, read by deployment_authorization, durable-authority validation and status); validate_static; advance_sealing skips readiness_class and expected_projection for static; advance_starting delegates to advance_static (intent with the previous release read from current_link, carry_and_flip then record, observe link == release, then Complete with Admitted{generation-<tx>} and post_commit_cleanup(SkippedNoIncumbent, source Pending)); a failure in Starting takes the existing pre-fencing abort; Engine.static_release Arc<dyn StaticReleasePort>. Docs: a Static release section in deployment-authority.md and a scope line in deploy-provenance-target.md. Tests: control_plane::tests::static_release_ (3), a pinned v4 record lifts and re-encodes as the pinned v5, a v4 control store copy in a temp dir migrates to v5 and an already-v5 store is untouched byte for byte, and the pinned-bytes test now pins v5 with the v4 bytes kept as a legacy fixture. The test runner is a stand-in over the real seal_artifact behind a cfg(test) Engine seam, because DockerRunnerDriver workspace ownership requires root. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>