Commit graph

591 commits

Author SHA1 Message Date
Meta Vens
64d63cb417 Merge steward orders 1 (r3): an order is one systemd job; refusal reads the named unit only
Soul cut-steward-orders-1.s5 holds at 77e2295. Not installed: steward-orders-2 installs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:57:39 +01:00
Meta Vens
77e2295e97 Steward orders: refuse Upholds and ConsistsOf units, pin the rule's gaps, README names the residuals
A unit with Upholds= is refused for start and restart (systemd would start the
upheld unit in a full transaction). A wrapper with ConsistsOf= is refused for
stop, restart and reload with a typed Refused::Wrapper naming the first member,
so it cannot report ran while touching nothing. Tests pin empty BoundBy, a
single show per refusal, no show for a refused name and each posted reason.
README: the one-job rule's residual full transactions. Removes the unused
BTreeMap import and the never_loop in the host actuator test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:32:30 +01:00
Meta Vens
fb1e7b5dd9 Steward orders: README states the one-job rule; pin the end-to-end argv
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:45:08 +01:00
Meta Vens
8ebe0208a6 Steward orders: pin the one-job rule on the real unit set and a real user manager
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:41:56 +01:00
Meta Vens
a859914b0b Steward orders: run every unit verb as one job and check only the named unit
Delete the transaction model (Edge, EDGES, action_target, Transaction, the
early-boot rule). Every unit verb runs systemctl <verb>
--job-mode=ignore-requirements -- <unit>; refusal_for reads one systemctl show
of the ordered unit: its names, the host-ending names, what fires when it
ends, and who is bound to it. Targets are no longer orderable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:40:58 +01:00
Meta Vens
4894ad20df README: an order's transaction follows emergency actions and OnFailure/OnSuccess; stopped boot units are refused
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 21:52:41 +01:00
Meta Vens
879b76a842 Steward orders: pin every emergency action spelling to its target
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 21:50:23 +01:00
Meta Vens
631fb7836b Steward orders: pin the new show properties; the unknown-action probe counts runs instead of expecting none
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 21:29:13 +01:00
Meta Vens
d29bf93be6 Steward orders: refuse a start or stop whose unit ends by emergency action or isolates; boot and recovery units are never started from stopped
refusal_for now reads SuccessAction, FailureAction, StartLimitAction and
JobTimeoutAction (each mapped to the target it runs, so reboot, poweroff,
halt, kexec, soft-reboot and exit, with -force and -immediate) and OnFailure
and OnSuccess as units a touched unit fires, followed through what they pull
in and what those fire. An action it does not know fails the order closed.
A stopped DefaultDependencies=no unit in the transaction is refused (Via::
EarlyBoot): rescue.service ends by isolating default.target, which no edge
describes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 21:26:29 +01:00
Meta Vens
d9710c988a Steward orders: the ledger reads an order only under its own schema too
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 06:35:43 +01:00
Meta Vens
caacbb4bba Steward orders: the end-to-end test waits 10 s for its posts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 06:35:31 +01:00
Meta Vens
9653d270e5 Steward orders: pin the ledger schema guards, invocation ids and post backoff; tests fail fast instead of waiting
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 06:16:04 +01:00
Meta Vens
8a1beb5c87 README: an order is gated by the steward bound at execution; the socket is the steward's; root reads
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 05:35:30 +01:00
Meta Vens
7e15bf1a7b Steward orders: the Synapse deadline test fails instead of hanging when the deadline is gone
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 05:33:23 +01:00
Meta Vens
572f9e6aa4 Steward orders: the end-to-end test keeps serve's umask until it has read control.cc
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 05:31:34 +01:00
Meta Vens
56edad95c1 Steward orders: one steward gate for fresh and recovered orders; the orders unit leaks no group or umask; root reads; kernel-attested issuer; end-to-end serve test
execute refuses, with a record and a post, an order whose principal or issuing
uid is not the steward bound now, before grammar, scope and brake; the brake
is asked for the bound principal only. idunn-orders.service drops Group= and
UMask=: bind_socket gives the socket to the steward uid at 0600 and serve sets
Idunn's own umask, so a deploy order writes control.cc 0640. Root may show and
list, never order. The issuer unit is the first unit under system.slice, never
a name the peer chose below it. Synapse waits for a reply within one deadline.
due_posts takes the deploy-state reader so a finished deploy's post is tested.
Tests: the gate both ways, root, per-order posts, deploy result, intake and
Synapse timeouts, parse_serve, user_uid, socket and store modes, and the whole
service as root with a fake systemctl, systemd-run and homeserver.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 05:03:17 +01:00
Meta Vens
ca439a29ff Pin the systemctl show property list and unquoted backslashes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 04:17:12 +01:00
Meta Vens
27ca875194 Steward orders tests: clear four clippy hits in the module
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 03:53:41 +01:00
Meta Vens
be3b95bc21 Import BTreeMap for the transaction facts cache
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 03:50:20 +01:00
Meta Vens
cea17c06a7 README: a unit order is refused by the systemd transaction; a package order installs only what it names
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 03:49:36 +01:00
Meta Vens
ec6222e2a1 Steward unit orders: refuse by the systemd transaction, install exactly the named packages
An order is refused when the closure systemd would build for it reaches an
always-refused unit: a start pulls Requires/Requisite/BindsTo/Wants/Upholds and
stops Conflicts/ConflictedBy, a stop takes down RequiredBy/BoundBy/RequisiteOf/
ConsistsOf/PropagatesStopTo/StopPropagatedFrom, a restart does both. A refused
unit already running is left alone by a start. Names are unquoted from
systemctl show; a unit systemd cannot show fails the order.

Package installs run apt-get --no-remove with ?exact-name(<name>) per package
and a final dpkg -s step that fails unless every named package is installed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 03:49:26 +01:00
Meta Vens
7d5cd85728 Reword a test comment so the no-brake-release tripwire reads clean
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 02:33:12 +01:00
Meta Vens
1a3634e046 Document idunn order and add the idunn-orders unit
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 02:33:02 +01:00
Meta Vens
e50a721dbc Steward orders: typed package, unit and deploy orders from one steward, in a sibling root unit
idunn orders serve takes orders over a root-only socket from the steward uid, records
order/start/outcome/post in its own orders.cc, and posts acceptance and result to
#operator as a retried projection. Unit orders may act on any unit except the compiled
always-refused set (idunn-*, mind-self@*, mind-persona@*), matched on a unit's Id and every
name, and for stop and restart on the units systemd stops with it. A refusal names a field
and a code, never the value. A started order is never run twice. Deploy orders commit
through the same primitive as idunn up.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 02:33:01 +01:00
Meta Vens
024f2d7a09 Workload: incarnation units are collected when they end, so a failed candidate no longer stays loaded and marks the host degraded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:54:26 +01:00
Meta Vens
8400d0712f Merge idunn/runner-failure-evidence: a failed runner keeps its evidence
Cut idunn-deploy-provenance:cut_spec:cut-runner-failure-evidence.r1,
reports h1-h3, Soul s1-s3. The docker runner kept only stderr, so a step
reporting on stdout failed with an empty message (Vili's node --test). A
failed step's name and bounded stdout/stderr tails go to a root-only typed
store read by idunn status; errors and the journal carry no output; one
allowlist escape at the status sink.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:32:18 +01:00
Meta Vens
1518cfb13c drivers test: read the kept evidence through show_status, the one status sink
Fixes the test build broken by 549f4be (render is private now).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 07:18:51 +01:00
Meta Vens
549f4be093 Runner evidence: one allowlist sink for status, quarantine only on a decode failure, a displaced set-aside is journaled
Status writes everything it prints from the evidence store, including the
unreadable-store line, through one function (emit): printable ASCII and tab
pass, every other code point is a \u{..} escape and every invalid UTF-8 byte
a \x.. escape. The bidi and C1 class lists are deleted.

The writer reads the store through a seam. An I/O error leaves the store in
place, keeps no evidence and names its kind; the store is set aside only when
bytes that were read still read the same on a second read and do not decode.
A set-aside that displaces an earlier one says so on the journal (last-written
time, no content). Tests pin a failed set-aside, its no-echo, the I/O seam and
the replacement.

Not yet built or run; verified in the next job.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 07:16:09 +01:00
Meta Vens
4a68df520f Runner evidence: set an undecodable store aside; escape bidi and pin C1 in status
The writer moves a store it cannot decode (corrupt, or a newer schema) to
runner-evidence.unreadable.cc, root-only, one slot replaced by the next, and
opens a fresh store; the journal names the file and none of its content. A
store that cannot be read at all is left in place and the write fails as before.
Status escapes the bidi controls (U+061C, U+200E/F, U+202A-E, U+2066-9) in
tails, subject and runner, and a test pins U+0080-U+009F.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 03:15:45 +01:00
Meta Vens
134c1fb5a2 drain_tail tests: a scripted reader pins the Interrupted guard
An interrupted read is retried with no byte lost, a persistent read error ends
the drain instead of spinning, and a non-interrupted error after data is
returned. Kills the three Interrupted-guard mutants (false, !=, true).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 03:15:45 +01:00
Meta Vens
54a75ef9b0 Runner failure regression: a stdout-only report is kept with an empty stderr
The vili failure: node --test wrote only to stdout, stderr was empty, the step
exited 1. Pin the cap at the literal 32 and the Debug impls that keep tails out
of text.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 02:36:34 +01:00
Meta Vens
7ef31ee699 Runner failure engine tests: declare readiness, read both control stores
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 02:18:06 +01:00
Meta Vens
22bd904ed9 Runner failure tests: named step, bounded tail, never echoed, private store
Drive the real DockerRunnerDriver over a fake docker program, through the
engine's Sealing path: the second step is named with its exit status, both
tails are kept in a 0600 store capped at 32, no error, control.cc or journal
line carries the output, status escapes control bytes, an unwritable store
does not stop the abort, and control.cc's record bytes equal those captured at
base 804ed75.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 02:16:03 +01:00
Meta Vens
ef82355bab Runner failure: a typed, bounded step failure kept in runner-evidence.cc
DockerRunnerDriver::docker no longer buffers whole streams or interpolates
stderr into the error. It pipes both streams through an 8 KiB tail and returns
RunnerStepFailure (subject, runner, status, tails); the engine's pre-fence
path is the one writer of runner-evidence.cc (0600, newest 32) and journals a
line that names the store and no output. idunn status --command renders the
record with control bytes escaped.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 02:11:14 +01:00
Meta Vens
78086705a0 deploy-provenance map: runner failure evidence (body facts R1-R8)
Imagination for cut runner-failure-evidence: the docker runner discards
stdout, so a step that reports on stdout fails with an empty message; the
tail moves to a root-only typed evidence store read by idunn status.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 02:04:37 +01:00
Meta Vens
804ed759c9 Merge idunn/isolation-credential-evidence: delivered credentials, not LoadCredential
Cut idunn-deploy-provenance:cut_spec:cut-cut-isolation-credential-evidence.r1,
report h1, Soul s1 (all claims hold). systemd 257 prints LoadCredential as
[unprintable]; the workload's credential directory, read from its MainPID's
root, must hold exactly the delivered names. Unblocks Vili's promotion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 16:05:26 +02:00
Meta Vens
dfdc226c25 Idunn credential rule: an unlistable credential directory is a refusal
cargo-mutants showed that treating every read_dir error as the empty set
survived. Test the non-NotFound case (the unit path is a file).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 15:14:15 +02:00
Meta Vens
ae6a1bea55 Idunn: judge workload credentials from the delivered directory, not LoadCredential
systemd 257 displays LoadCredential as [unprintable] for every unit, so the
conjunct was always false for a unit with only the presence identity and
vacuous for one with credentials. Delete the show argument, the conjunct and
its twin clause; the isolation conjunction becomes
require_systemd_isolation_contract. The credential rule is now
require_delivered_credentials: entry names of /run/credentials/<unit> in the
MainPID's root equal Idunn's launch names. load_credential stays a retired
wire slot (written empty, out of the drift list) so persisted records decode.

Not yet built or verified.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 14:54:15 +02:00
Meta Vens
def0b78378 Fixtures: systemd 257 show captures and pre-cut observation records
Real systemctl show output (Vili presence-only, Odin with one service
credential) and the two MessagePack encodings of a pre-cut observation, as
inputs for the credential-evidence cut. Nothing reads them yet.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 14:53:15 +02:00
Meta Vens
69eb3e6d6f deploy-provenance map: isolation credential evidence (body facts I1-I8)
Imagination for cut isolation-credential-evidence: systemd 257 prints
LoadCredential as [unprintable] for every unit, so observe_unit's comparison
never passes a target with no extra credential and proves nothing otherwise;
the rule moves to the delivered credential directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 14:51:10 +02:00
Meta Vens
112a7a5ebb Idunn unit: Vili's roots are optional so a missing target cannot stop Idunn
systemd refuses to start a unit whose ReadWritePaths names a missing path,
and none of Vili's three roots exist on Yggdrasil yet. Idunn's startup must
not depend on a managed target, so the Vili line takes the "-" prefix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 00:15:16 +02:00
Meta Vens
a3c6386aa4 Grant Idunn Vili's runtime, state and release roots
motion-pipeline:follow_up:idunn-unit-vili-roots: Vili's admission
(motion-pipeline:cut_spec:cut-vili-admission.r1) needs its three roots
writable under ProtectSystem=full, beside StreamPixels'. Lands before the
d3222e5 install, which restarts idunn-yggdrasil anyway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 00:14:39 +02:00
Meta Vens
d3222e5724 Merge idunn/tree-executable-members: tree artifacts declare executable members
Cut idunn-deploy-provenance:cut_spec:cut-tree-executable-members.r2, reports
h1-h3, Soul s1-s3. Members sealed 0555, the rest 0444; link containment
decided once in the digest walk (leading dotdot within depth, no absolute);
one seal step for collect and host. Real PBS CPython+torch and Blender trees
seal with all 1128 links kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 23:52:27 +02:00
Meta Vens
e8c4c69728 Seal tests: refused links whose targets resolve (absolute, escaping, after-a-name; file and directory)
Closes the live-target bypass: a judge guarded by exists() or is_dir() passed every dangling fixture.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 23:26:50 +02:00
Meta Vens
68d6f96808 Seal: one seal_artifact for both targets; link containment decided at seal by a shape rule
collect_artifact and host.rs materialize both call seal_artifact. digest_tree
judges every link with check_release_link (relative, `..` only first, climbs no
higher than the link's depth); validate_release_symlink and harden's link
judgement are gone. hash_file_exact owns the streamed-length check. A file
directly under a tree's top is pinned 0444.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 21:57:07 +02:00
Meta Vens
07616697af deploy-provenance map: link containment rule, host targets, shared seal path (r2)
Imagination r2 for cut tree-executable-members after Soul s1: link census of
the real PBS and Blender trees, why lexical normalisation does not prove
containment, the leading-dotdot-within-depth rule and its prior art, members
on host targets carried not applied, one seal step for collect and host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 21:54:00 +02:00
Meta Vens
fd040f09c1 Tests: an io error other than NotFound is not reported as a missing member
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 20:28:15 +02:00
Meta Vens
76cec0b540 Tests: the sealed-mode helper no longer redefines the module's existing mode_of
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 19:54:35 +02:00
Meta Vens
04ff2c8ce3 README: a directory artifact is sealed 0444 except its executable_members
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 19:53:16 +02:00
Meta Vens
022dbece5b Directory artifacts declare executable_members; the seal checks them, the receipt carries them, harden seals exactly those 0555
ArtifactOutput and ArtifactReceipt gain executable_members (the receipt field is
skipped when empty, so existing sealed release ids are unchanged).
check_artifact_modes is the one seal-time owner of mode declarations and runs
from both collect_artifact and the host materializer. harden_installed_release
drains the declared set and fails when a declared path was never sealed. Digests
stream through one hash_file_streamed helper; the encoding is unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 19:53:16 +02:00