Add distributed first-embodiment activation - #126
Conversation
|
@compaii Independent review requested for exact head |
compaii
left a comment
There was a problem hiding this comment.
Independent review of exact head 3eb9de74c2119df689659c3b477ef8354f3e96d5.
Verdict: changes requested. The positive path and release gates are healthy, but four contract invariants still fail.
Blocking findings
-
First-embodiment holder shares do not authenticate the exact request.
create_root_share()signs only the embodiment credential body (operator_first_embodiment.py:291-295);request_idis an unsigned wrapper field (:296-302). Aggregation checks that wrapper value (:351-366) but cannot prove that the holder approved it.Reproduction: obtain two valid shares for request R1; create target-signed R2 with the same credential body but a new request ID, nonce, and extended expiry; change only each share wrapper's
request_id. Aggregation and final validation accept R2 after R1 has expired, while both root signatures remain byte-identical. The same gap allows reassociation with another incarnation authorization that uses the same credential.This violates issue #127's requirement for per-holder approval of the exact request and weakens the stated freshness boundary. Add a holder signature/attestation over a closed share body that includes at least the request ID and credential signature, then reject request-ID, expiry, nonce, and incarnation reassociation in regression tests.
-
Enrollment activation time is not bound to the signed transition.
validate_activation()usesbody["issued_at_ms"]for request and credential-time validation (operator_rebirth.py:1080-1095) but never requires it to equal the transition's signedissued_at_ms(:1095-1104).Reproduction: change activation
issued_at_msfrom1800000000040to1800000000041, recompute the content-addressed activation ID, and validate. It is accepted while the signed transition still says1800000000040.Require equality with the verified transition timestamp (or derive the activation timestamp from it). Add a regression and inspect the analogous recovery activation path for the same invariant.
-
advance-bundlecan emit a candidate from an unverified runtime document and an invalid peer endpoint.The CLI passes
--base-runtimedirectly toapply_activation_to_runtime_bundle()(operator_rebirth.py:4045-4060). That function checks onlybundle["manifest"], the history list, and a bounded endpoint string (:1663-1705); it does not verify the runtime bundle as a whole or apply native peer-endpoint validation.Reproduction: a three-field mapping containing only the matching manifest, an empty authority history, and peer targets is accepted with
file:///etc/passwd; the returned candidate has noschemaorcontrol_head.Validate the input with
authority_from_runtime_bundle(), require its exact authority to matchbase, validate the endpoint with the native peer-transport contract, and validate the completed candidate before writing it. -
Intermediate ancestor symlinks are followed by the new first-embodiment output path.
_owner_directory()normalizes the path and checks only the final directory component (operator_first_embodiment.py:102-115). A secure tree containingalias -> realis accepted when preparing underalias/parent/output, and files are written underreal/parent/output.Issue #127 explicitly requires symlink/alias attempts to fail closed. Resolve the path through stable directory descriptors (or verify every ancestor without following links) and add an intermediate-component regression. Check the shared rebirth filesystem helpers for the same class.
Reproduced positive evidence
- Exact head/tree:
3eb9de74c2119df689659c3b477ef8354f3e96d5/064ccdb25543ab947c3ae20628f1d51ea4c64078. - Base:
bf5f7415f075af09442973144bc529f4c5ce7985; merge tree clean. - Focused first-embodiment suite: 5/5 pass.
- Full source suite: 644 tests pass, 8 skipped, Python 3.13.5.
- Compileall, Ruff format/check, mypy, and
git diff --check: pass. - Reproducible build matches the declared artifacts twice:
- wheel SHA-256
f0ea8eb60773c7fd686a04ef077dba56b08423fd7853976e3dee73532a5fa7bb - sdist SHA-256
498d2ce226e95c2aa300b1f7e4fafa38806b1047e66a83d38c38f7e75096d88f
- wheel SHA-256
- Distribution allowlist/metadata verification: pass.
- GitHub CI is green across Python 3.11-3.14 and coordination.
No deployment or host mutation was performed.
compaii
left a comment
There was a problem hiding this comment.
Supplement to the CHANGES_REQUESTED review on 3eb9de74c2119df689659c3b477ef8354f3e96d5. Two further findings confirmed independently after the review; the decision is unchanged.
1. Blocker — installed first-embodiment CLI hangs on a FIFO input
src/daimon_matrix/operator_first_embodiment.py:142-151
_document() opens the path at line 145 before establishing it is a regular file. Opening a FIFO with O_RDONLY blocks before the fstat() S_ISREG rejection can run, so a named pipe as --genesis (or --request/--holder/--profile) hangs the CLI instead of failing closed. This applies to every subcommand that reads a document through _document.
Reproduction against the installed wheel:
daimon-first-embodiment prepare --genesis <fifo> --profile <regular.json> \
--password-fd 0 --output <out>
Result: timeout (2.0s), vs a regular-file control that returns immediately.
The shared helper already does this correctly: operator_rebirth.py::_owner_file_descriptor (:2007-2042) performs lstat() and the S_ISREG check before opening. The new module diverges from that in-repo safe pattern rather than introducing a new class of problem. Fix by mirroring the lstat-first (or O_NONBLOCK + post-open identity/type) sequence in _document, and add an installed-CLI FIFO regression with a timeout.
2. Major — distribution verification does not bind the new module's bytes to source
tools/check_distribution.py:308-358 (sdist source-parity loop) and :460-519 (wheel source_map)
Both byte-parity loops skip from operator_genesis.py directly to operator_rebirth.py, omitting operator_first_embodiment.py. The module is present in both allowlists (so _assert_exact passes and the artifact ships), but its shipped bytes are never compared against the source tree. A source-divergent operator_first_embodiment.py payload inside the wheel or sdist would pass the current package-integrity gate.
The artifacts I built are byte-correct (wheel f0ea8eb6…, sdist 498d2ce2…, matching the PR hashes), but the CI "package" gate does not prove it for this module. Add the module to both parity maps and a regression that rejects a mutated payload.
3. Non-blocking evidence note — two-isolated-container qualification is not committed
.github/workflows/tests.yml:148-194 installs the wheel but never invokes daimon-first-embodiment; tests/test_operator_first_embodiment.py:399-446 exercises both runtimes in one process via a loopback thread, and tests/test_dm070_multihost.py:59-60 skips the repository's only named "two installed processes" test (pre-V7 fixture). The issue #127 "two isolated containers" rehearsal is therefore asserted only in the PR body, not as a reproducible committed runner/receipt. Recommend committing a reproducible installed-wheel V7 two-container runner and its closed receipt (including the negative CLI cases), separate from this PR if desired.
No deployment or host mutation was performed.
|
@compaii Nueva revisión solicitada sobre el head exacto
Gates locales del head: focalizado 40/40; suite completa 647 descubiertos, 626 pass, 21 skips declarados, 0 failures; Ruff/mypy limpios; secret scan limpio; build doble byte-idéntico. Wheel |
|
@compaii Actualización de evidencia, sin cambio de head: completé la calificación descartable de dos contenedores con el wheel exacto de
Receipt público local cerrado por hashes: |
compaii
left a comment
There was a problem hiding this comment.
Independent review of exact head 52945123ec4d323c03eaafe216dce8a1d7e48565 (fix commit over 3eb9de74).
Verdict: approve. All six findings from the CHANGES_REQUESTED review are fixed and independently re-verified.
Finding-by-finding confirmation
-
Root-share request binding — fixed.
create_root_sharenow signs a closed share body (being_ref,control_head,request_id,request_sha256,credential_signature) with a holder attestation (operator_first_embodiment.py:325-338);aggregate_activationandvalidate_activationre-verify each attestation and cross-check the approved signatures against the credential's root-authorization set. Independent probe: reusing two valid shares against a re-signed request (extended expiry, new nonce) is now rejected withfirst_embodiment_share_rejected. Regression:test_root_approvals_cannot_be_reassociated_to_a_new_request. -
Activation time bound to the signed transition — fixed. Both
validate_activation(operator_rebirth.py:1097-1099) andvalidate_recovery_activation(:1643-1645) now requiretransition.issued_at_ms == body.issued_at_ms. Independent probe: a+1tamper with recomputed activation ID is rejected. Regressions intest_dm078_rebirth.pyandtest_dm078_recovery_rebirth.py. -
advance-bundlevalidates the full V7 bundle — fixed.apply_activation_to_runtime_bundleandapply_recovery_activation_to_runtime_bundlenow derive the source authority viaauthority_from_runtime_bundle, validate peer transport through the nativehttp_peer_round_tripparser, and re-validate the candidate against the successor authority;_activate_target_runtimere-validates before writing custody. Independent probe: a minimal three-field bundle is rejected (invalid_rebirth_runtime_bundle) andfile:///etc/passwdis rejected (rebirth_runtime_peer_transport_invalid). -
Ancestor symlink rejection — fixed.
_reject_symlink_ancestorsis wired into_owner_directory,_document, and_owner_file_descriptorin both modules. Regression:test_intermediate_symlink_and_fifo_inputs_fail_without_writes(no write occurs through analias/parentpath). -
FIFO fail-closed — fixed.
_documentnow classifies withlstat()and rejects non-regular files before opening, then opensO_RDONLY|O_NOFOLLOW|O_NONBLOCK;_owner_file_descriptoralso opensO_NONBLOCK. Independent installed-wheel probe: a FIFO as--genesisnow returns exit code 2 in ~0.7s instead of hanging. Regression in-suite plus a CI smoke (dm087_fifowithtimeout 2). -
Distribution parity — fixed.
operator_first_embodiment.pyis added to both the sdist parity loop and the wheelsource_mapvia a shared_assert_source_parityhelper (tools/check_distribution.py). Regression:test_first_embodiment_distribution_bytes_are_source_boundrejects a mutated payload.
Reproduced gates
- Focused suites (first-embodiment, rebirth, recovery, package-scaffold): 40/40 pass.
- Full suite: 647 tests, 0 failures/errors (8 skipped in this environment, which lacks the daimon-cluster/hermes-agent pinned checkouts).
- Reproducible build byte-identical across two independent runs:
- wheel SHA-256
da1274be3b03b5e213d715f718c7de14af50a89087985839fbc80fe0f49646d6 - sdist SHA-256
6378ca1f490c2d714c864cdaf76fb05582fa6191a30648280ff33807d70c773c
(both match the PR body's declared hashes).
- wheel SHA-256
tools/check_distribution.pypasses;git diff --checkclean; worktree clean.- GitHub CI green: tests 3.11-3.14, conformance, hermes-contract, package, pull-request.
Note (non-blocking)
The two-isolated-container qualification is now evidenced by the closed receipt in the PR comments (first activation 245602fa…, second enrollment c274b476…, single imported historical event 6a7aecd0…). It is still not committed as a reproducible runner in-repo; adding one remains a worthwhile follow-up but does not block merge.
No deployment or host mutation was performed.
Issue
Closes #127
Claim-ID: 42901987-69b6-43fc-9da0-da5bb3b0204c
Deployment: not deployed
Outcome
Adds a reproducible, fail-closed path from threshold-separated genesis custody to a runnable first embodiment. The same separated root holders can authorize later embodiments without copying a root seed or holder package to a target or keyless aggregator.
Invariants
Validation
52945123ec4d323c03eaafe216dce8a1d7e48565were byte-identical.52945123...: separated 2-of-3 custody, first activation, second-enrollment activation, revision 1→2 bundle advancement, native encrypted peer pull, and exact import of one historical event. Both daemons were stopped and container port isolation restored. The unsigned real-host preparation from3eb9de74...remains superseded and inactive.Tests
python -m unittest discover -s tests -v: 647 discovered, 626 passed, 21 declared skips, zero failures.python -m ruff format --check ...andpython -m ruff check ...: passed.python -m mypy --strict ...: passed.python tools/reproducible_build.py ...: two byte-identical builds, with source parity inspection.Build identities:
52945123ec4d323c03eaafe216dce8a1d7e485650af4dfdb3506cfe826ee53533f67eee88fb96389da1274be3b03b5e213d715f718c7de14af50a89087985839fbc80fe0f49646d66378ca1f490c2d714c864cdaf76fb05582fa6191a30648280ff33807d70c773cSecurity and rollback
No live being authority, production route, or service was changed. The unsigned real-host preparation from the superseded head was moved aside together with its local credential and was never root-approved. Rollback is to reject or revert this commit; no real genesis transition needs reversal because none was performed.