Skip to content

docs(adr0041): resolve the baseline trust-domain question and narrow two false D3 claims (BACKLOG #1679) - #1184

Merged
wshallwshall merged 1 commit into
mainfrom
claude/builder-ac13-baseline-trust-domain
Sep 16, 2026
Merged

wshallwshall merged 1 commit into
mainfrom
claude/builder-ac13-baseline-trust-domain

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

BACKLOG #1679, act 5. Acts 1 to 4 shipped in PR 1159 and are not rebuilt here.

PR 1159 deliberately left one question open and recorded it as an owner decision under ADR 0041 AC-12/AC-13: should a RECORD baseline that sits inside the adversary's own install be trusted at all, and if not what out-of-domain anchor replaces it. It is not an owner decision. The record leaves no defensible second option, so this replaces the open paragraph with the resolution and narrows two claims that are false in the shipped code.

What changed

  1. ADR 0041 D3 gains a resolution section, "The baseline's trust domain". The wheel's own RECORD stays the baseline. No runtime out-of-domain anchor is adopted.
  2. Two false D3 claims narrowed.
  3. New behaviour, AC-14: one WARNING log line on the disarmed-tripwire shape.
  4. docs/CONFIGURATION.md links to the resolution instead of selling hard enforcement with no boundary. The fact is stated once, in the ADR.

Nothing was mirrored into docs/SECURITY.md — it carries no startup-attestation claim to narrow, and a copy there would create a second home for a load-bearing fact.

Ground 1 — any in-process anchor is circular

_loaded_module_files sources from messagefoundry.__path__, so integrity.py is inside the set it attests. It attests itself and nothing else attests it.

Verified in the tree, not carried from the brief:

  • attest_engine — exactly one caller, run_startup_attestation, in its own module.
  • run_startup_attestation — exactly one caller, the ASGI lifespan in messagefoundry/api/app.py.
  • No CLI subcommand. Positive control: 40 add_parser( calls in messagefoundry/__main__.py, zero of them named attest.

An adversary with venv-write rewrites integrity.py in one write — the same primitive that re-seals RECORD. So any anchor the engine consumes at startup is consumed by code that actor already owns. That kills an operator-supplied pin, this ADR's own deferred signed manifest used as a runtime check, and Sigstore-as-runtime-anchor, in one sentence. It is a logical collapse rather than a cost, so it holds even if the anchor were free.

Ground 2 — the precedent

The project already ruled the structurally identical question, admin-authored Python executed in-process, at trust boundary 5. The answer recorded there is a deployer-owned filesystem ACL rather than a cryptographic control. Cited by number only; that document is withheld from public checkouts and none of its text is reproduced here.

What the resolution states

  • The residual, plainly: the control detects an INCONSISTENT in-place edit and cannot detect a CONSISTENT one. An edit that also re-seals RECORD passes clean. Accepted.
  • Where the out-of-domain anchoring actually lives: ORIGIN is anchored at install time (the hash-locked non-editable wheel and its provenance, checked by the installer); DETECTION is anchored by the off-box audit tee, so an actor who owns the venv does not own the evidence.
  • What still earns the control its keep: the shadowed-package shape needs no venv write at all, only a messagefoundry/ directory resolved ahead of site-packages. AC-13 therefore raises the bar against an actor strictly weaker than the stated adversary. That is a real gain, not a consolation.
  • The premise it rests on, recorded as an assumption and not answered: that the install root can be made non-writable in the intended deployment shape. Ground 2 hands the question to a filesystem ACL, and nothing in these sources establishes that ACL either way. Owner/deployment question.
  • Six declined alternatives, tabled with their reasons, so none is reintroduced: an operator-supplied record_pin, an editable_install_allowed key, a publisher-signed boot manifest, a repo-recorded digest, folding the RECORD digest into a startup_integrity row and diffing against the prior one, and a per-boot heartbeat row.

The two false claims

"Enforced production default" for the non-editable hash-locked wheel. Nothing enforces it. [integrity].enabled defaults true, fail_closed_on_drift defaults false, a declared-editable install is exempt under either, and no code path anywhere refuses to start on one. Verified: grep -rn "editable" --include=*.py messagefoundry/ returns 35 hits in integrity.py, 6 in __main__.py (web console provenance, unrelated), 5 in settings.py (the [integrity] docstrings), and nothing that refuses. Narrowed to "recommended".

"At startup (and on demand)". There is no on-demand surface. No attest/integrity CLI subcommand (control above) and no API route — POST /status/integrity-check is the store's SQLite PRAGMA quick_check, a different control. The phrase is dropped from the ADR (two places), docs/CONFIGURATION.md and the integrity.py module docstring. Filing either surface is separate work and is not done here.

AC-14 — one WARNING line, described honestly

Under fail_closed_on_drift=true, the declared_editable branch of run_startup_attestation returned with no log, no audit row, no alert, and never refused. A first deployment that opted into hard enforcement on an editable install would start with its tripwire disarmed and nothing in the boot log to read.

It now logs a WARNING naming the reason, and the reason token is what carries the cause into the boot-log posture readout.

This is a MISCONFIGURATION control and it closes no hole. An adversary with venv-write plants one direct_url.json or rewrites this check in the same single write. What the line does is tell an operator that the opt-in they set is not in effect.

AC-12 is untouched: still no refusal, no audit row, no alert, so a dev checkout is never bricked. The warning is keyed on the opt-in, not on editability, so the default alert-only posture stays silent — warning on every dev run is how a warning stops being read.

The failing test, and its exact output before the fix

Test written first, run first, red first:

$ .venv/Scripts/python.exe -m pytest tests/test_startup_attestation.py -k "declared_editable_under" -q
F.                                                                       [100%]
================================== FAILURES ===================================
_____ test_declared_editable_under_fail_closed_warns_and_names_the_reason _____
...
        store = await open_store(sqlite_settings(str(tmp_path / "ed_fc.db")))
        sink = _RecordingSink()
        try:
            with caplog.at_level(logging.WARNING, logger="messagefoundry.integrity"):
                out = await run_startup_attestation(store, sink, fail_closed_on_drift=True)
            assert out.declared_editable is True and out.attested_nothing is True
            warnings = [r.getMessage() for r in caplog.records if r.levelno == logging.WARNING]
>           assert warnings, "a fail-closed opt-in on an editable install must not start silently"
E           AssertionError: a fail-closed opt-in on an editable install must not start silently
E           assert []

tests\test_startup_attestation.py:827: AssertionError
=========================== short test summary info ===========================
FAILED tests/test_startup_attestation.py::test_declared_editable_under_fail_closed_warns_and_names_the_reason
1 failed, 1 passed, 25 deselected in 2.14s

The 1 passed in that run is the paired arm, test_declared_editable_under_the_default_posture_stays_silent, which asserts the default posture emits nothing. It passes before and after, which is what makes it a guard against over-correction: a fix that warned on every editable install would turn it red.

After the fix:

$ .venv/Scripts/python.exe -m pytest tests/test_startup_attestation.py -q
...........................                                              [100%]
27 passed in 2.24s

Checks run

From this worktree's own .venv (stdlib venv, installed with --constraint constraints.lock, messagefoundry.__file__ verified to resolve inside this worktree).

Check Result
ruff check . All checks passed
ruff format --check . 1301 files already formatted
mypy messagefoundry Success: no issues found in 274 source files
pytest tests/test_startup_attestation.py 27 passed
pytest tests/test_settings.py tests/test_security_posture_defaults.py 218 passed
pytest doc gates (test_doc_guards_lane, test_doc_ref_handle, test_docs_cite_no_refused_config_keys, test_docs_security_pathways, test_operator_docs_no_warning_sign, test_ledger_check, test_docs_runbooks) 398 passed
pre-commit (all hooks, at commit) Passed

Skipped: the full pytest suite. It does not finish inside one turn. The slices above cover every file this change touches.

CI legs a human must read after I exit

Every hosted-runner leg, since none of them run locally — in particular windows-service-smoke (NSSM), the gated SQL Server and PostgreSQL suites (tests/test_startup_attestation.py feeds _assert_startup_attestation_tamper_evidence into both), and the full-suite legs on all three runners.

Notes

  • docs/BACKLOG.md is untouched. It is a public stub in this repository with zero numbered items.
  • No ADR number was allocated; this amends ADR 0041 in place.
  • No backlog number was allocated or cited beyond #1679.
  • Nothing vaulted is reproduced. Trust boundary 5 is cited by number only.

…two false D3 claims (BACKLOG #1679)

Act 5 of BACKLOG #1679. Acts 1 to 4 shipped in PR 1159, which deliberately
left the baseline's trust domain open and recorded it as an owner decision.
It is not one: the record leaves no defensible second option, so this
replaces the open paragraph with the resolution.

Ground 1, and it is sufficient alone: any in-process anchor is circular.
_loaded_module_files walks messagefoundry.__path__, so integrity.py is
inside the set it attests. It attests itself and nothing else attests it.
attest_engine has exactly one caller, run_startup_attestation in its own
module; that has exactly one caller, the ASGI lifespan in api/app.py. An
adversary with venv-write rewrites integrity.py in one write, the same
primitive that re-seals RECORD, so any anchor the engine reads at startup
is read by code that actor already owns. That is a logical collapse rather
than a cost, and it holds even if the anchor were free.

Ground 2: the project already ruled the structurally identical question at
trust boundary 5, where the answer is a deployer-owned filesystem ACL and
not a cryptographic control.

The residual is stated plainly: the control detects an inconsistent in-place
edit and cannot detect a consistent one. The out-of-domain anchoring that
does exist is named: origin at install time, detection by the off-box audit
tee. What still earns the control its keep is named too: the shadowed-package
shape needs no venv write at all, so AC-13 raises the bar against an actor
strictly weaker than the stated adversary. The premise the resolution rests
on - that the install root can be made non-writable in the intended shape -
is recorded as an assumption, not answered. Six declined alternatives are
tabled with their reasons.

Two D3 claims were false in the shipped code and are dropped rather than
left standing. "Enforced production default" for the non-editable wheel:
nothing enforces it, so it now reads "recommended". "At startup (and on
demand)": there is no on-demand surface, no attest CLI subcommand and no
API route, so the phrase is dropped throughout.

New behaviour, AC-14: under fail_closed_on_drift the declared-editable
branch returned with no log, no audit row and no alert, so a first
deployment that opted into hard enforcement on an editable install would
have started with its tripwire disarmed and zero signal. It now logs a
WARNING naming the reason. This is a MISCONFIGURATION control and it closes
no hole: an actor with venv-write plants direct_url.json or rewrites the
check in the same single write. AC-12 is untouched - still no refusal, no
row, no alert - and the warning is keyed on the opt-in, so the default
alert-only posture stays silent on a dev checkout.

The CONFIGURATION.md fail_closed_on_drift row now points at the D3
resolution instead of selling hard enforcement with no boundary. The fact
is stated once, in the ADR, and linked from the module docstring and the
config reference.
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Three subjects found while doing this and deliberately NOT built here. Named in words, with no number cited, because none is allocated.

1. security_loosenings cannot see [integrity] at all, so one shipped key silently disables this control with no posture deviation reported. Verified: security_loosenings(sec, store, auth, alerts, secret_rotation, cleartext_hops, expiry_relaxed_hops, unverified_db_hops, store_privilege) in messagefoundry/config/settings.py takes no IntegritySettings parameter. So neither [integrity].enabled=false nor fail_closed_on_drift can ever appear in the registry or in GET /security/posture. Its own docstring says the registry covers every [security] switch plus an ENUMERATED set of deviations elsewhere, and [integrity] is not in that enumeration. enabled=false turns the whole tripwire off in one line and nothing reports it. Worth filing.

2. integrity.py's module docstring asserts an adversary the project's threat model never admitted. The docstring opens with an admin holding venv-write plus restart rights. Whether that actor is in the admitted model is a threat-model question, so it is VAULT work and must not be handed to an engine Builder. Flagging the subject only.

3. An install-root ACL preflight, mirroring what auth/trust_anchors.py already does for anchor files. The resolution landed in this PR hands the residual to a deployer-owned filesystem ACL, and nothing in the engine checks that ACL. run_anchor_preflight already implements exactly this shape for operator-supplied trust anchors (group/world-writable refuses at enforce, warns otherwise) and runs in the same lifespan, a few lines after attestation. Reusing it against the install root would turn the assumption into something observed. Worth filing.

One question I could not settle, and it is the owner's: can the install root be made non-writable in the intended deployment shape? The resolution in this PR rests on that ACL. It exists nowhere in these sources. The ADR now records it as the premise rather than answering it.

One place the tree disagreed with the brief: the brief pinned origin/main at 1d69a0efb. At branch time it was c0ae68ca5 — PR 1159 and AC-13 are present either way, so the reading held. No other disagreement; both false D3 claims and the circularity were confirmed in the tree.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Lander review

This removes two false claims from a shipped ADR, which is the highest-value thing a docs PR can do here. I re-derived both from the branch rather than reading them.

Claim 1: "enforced production default" was false

messagefoundry/config/settings.py:3946    fail_closed_on_drift: bool = False

Nothing refuses to start on an editable install under either posture, and a declared-editable install is exempt regardless. So "enforced" was wrong and "recommended" is right. This is the SDS-3.7 shape exactly — a shipped security document asserting an enforcement that does not exist, which a reader would have planned around.

Claim 2: "and on demand" was false, and the near-miss is the interesting part

The call chain is closed at one path:

attest_engine            <- called once, integrity.py:560, inside run_startup_attestation
run_startup_attestation  <- called once, api/app.py:6533, the ASGI lifespan

Everything else the grep returns is the __all__ entry, the import, and docstrings.

No CLI subcommand, and this time with a control that fires:

add_parser("serve")              -> 1   (control: the search works)
add_parser("attest"|"integrity") -> 0   (real absence)

My first pass at this used a regex that returned 0 for a subcommand that does exist, which would have made the zero above meaningless. Recording that because a search proving nothing is the failure mode this repository keeps paying for.

And the route that looks like the exception is not one. POST /status/integrity-check at app.py:5846 reads:

"""Run a database integrity check on demand (PRAGMA quick_check)."""
ok, detail = await engine.store.integrity_check()

That is the store's SQLite check, not engine attestation. Two controls with adjacent names, and the ADR is right to say so rather than let a reader merge them. Filing a real on-demand surface is separate work, as the note says.

The trust-domain resolution is correctly argued

"Any in-process anchor is circular" is sufficient on its own: _loaded_module_files walks messagefoundry.__path__, so integrity.py is inside the set it attests — it attests itself and nothing else attests it. An adversary with venv-write rewrites it in the same single write that re-seals RECORD. Calling that a logical collapse rather than a cost is the right framing, because it means no budget buys past it, and it disposes of the operator-supplied pin, the deferred signed manifest as a runtime check, and Sigstore-as-runtime-anchor in one move.

The new control is scoped honestly

The added warning fires when an operator sets fail_closed_on_drift on a declared-editable install — previously that opt-in looked honoured while the tripwire was disarmed, with zero signal. The test docstring states its own limit without being asked: "This is a MISCONFIGURATION control and nothing more. It closes no hole: an adversary with venv-write plants a direct_url.json or rewrites this module in the same single write."

AC-12 is preserved and the tests assert it — still no refusal, no audit row, no alert on an editable install, so a dev checkout is not bricked. Both arms are covered: the fail-closed opt-in warns, the default posture stays silent.

Stated no larger than it is

I verified the two narrowed claims, the call chain, the absence of a CLI surface with a working control, and what the integrity-check route actually does. I did not re-derive the ADR 0017 relationship or the second ground for the trust-domain decision; the first ground is sufficient on its own and is the one I checked.

Verdict: merge.

@wshallwshall
wshallwshall added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit 1cd9f04 Sep 16, 2026
42 checks passed
@wshallwshall
wshallwshall deleted the claude/builder-ac13-baseline-trust-domain branch September 16, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant