Repository navigation
Batch 453 wave 1: partial RCPT refusal, auth loosenings, IDE service config, cipher-audit, TOTP off-loop, scaffold, timing tests, connscale, verify read-only (BACKLOG #2924, #3011, #2600, #2908, #1719, #3929, #3948, #3786, #3456, #3132, #1708, #2720) - #2608
Conversation
BACKLOG #3929. Under the vault_transit cipher a TOTP cell open is a blocking Transit decrypt_data call. The combined sign-in, the enrolment confirm, the two-step verify (its code check and both enrolment reads) and the status read opened it on the event loop. Every service path now opens the cell through one async opener, AuthService._open_totp_cell, which hands the store's open_totp_secret to a worker thread. _totp_secret, _totp_enrolment and _totp_enrolment_moved become async; _totp_state uses the same opener. The combined sign-in's broad except is unchanged, so a cell that will not open is still a logged wrong code. tests/test_totp_open_off_loop.py measures the loop with a cipher that blocks for 0.6 s: a heartbeat task stalls under 0.3 s during a combined sign-in, and a control that runs the same cipher on the loop shows a 0.6 s stall. Before the fix the off-loop arm measured 0.602 s.
…tion BACKLOG #1708: every open_store call in messagefoundry/verify passes read_only=True (store.connect, the lockable-account census and both --check-disposition reads), as the support bundle's census open does. A writable open schema-ensured and migrated an existing store as the calling user, and built a whole store into a SQLite database that was not one. An AST test pins the literal read_only=True on every call; a second test shows store.connect FAILs on another application's SQLite file and leaves its tables as they were. missing_sqlite_store's docstring and VERIFY.md say what the read-only open does per backend. BACKLOG #2720: ADR 0193 gains an Amendment 2026-10-27 recording engine PR 2167's version-pinned recompute, why it stands in for Transit's verify call, and the edge where a version Transit refuses reads as a break. Proposed PR title: verify opens every store read-only, and ADR 0193 records what a Transit key rotation does to the chain (BACKLOG #1708, #2720) Proposed banner #1708: BUILT -- every verify store open is read-only, pinned by an AST test; store.connect FAILs on a non-store SQLite file. Remains: a stale schema under a read-only verify open is logged by the store and not reported by store.connect; needs a store-side signal (follow-up, unfiled). Proposed banner #2720: CLOSED by engine PR 2167 (code) plus this ADR 0193 amendment (prose). Remains: Transit's verify call, which would survive a raised min_encryption_version, is not built (PR 2167's known-open item).
The connection editor, the connections.toml custom editor and the keyboard wizard ran connection upsert and remove with --config only, so the CLI checked the edit against ./messagefoundry.toml when present and no settings otherwise, never the file messagefoundry.serviceConfig names. All five call sites now build their argv in connectionWizardModel and pass that setting as --service-config, like the alert, security and trust editors. One case leaves the flag off: the setting names the default file and it does not exist. The CLI refuses an explicit missing file, so passing it there would block every edit, where omitting it reads the same absent path as before. codeset upsert and remove are unchanged: that subcommand takes no --service-config and its check is the code-set loader alone, with no egress check. BACKLOG #2908 Proposed PR title: IDE connection edits pass --service-config (BACKLOG #2908) Proposed banner #2908: BUILT. The three IDE writers (connectionEditor, configEditors, connectionQuickInput) pass --service-config from messagefoundry.serviceConfig on every connection upsert and remove, except where the setting names the default file and it is absent. IDE tests pin both argv builders and scan the callers. Nothing remains.
_auth_limit_loosenings now reads every numeric [auth] field it did not already cover, each from its consumer, and names it only in the looser direction against the shipped default, while the code that reads it is built: - mfa_recovery_code_count above 10, password_min_length below 15 (no configured value quoted: mfa_* and *password* names); - the [security] session limits sign_out_after_idle_minutes and max_session_hours above 30 / 12, read off their desugared [auth] fields and named by their [security] names; - with the reconciler running: ad_session_recheck_seconds above 300, ad_session_recheck_strikes above 2, ad_session_recheck_max_users below 200, and the breaker thresholds ad_session_revoke_max and ad_session_revoke_max_fraction above 5 / 0.34; - with OIDC on: oidc_clock_skew_seconds, oidc_jwks_ttl_seconds, oidc_flow_ttl_seconds and oidc_max_age_seconds above their defaults, and oidc_jwks_min_refetch_seconds below 300 (0 or less: no bound) or above the default JWKS lifetime. oidc_session_max_hours is recorded as never looser: it only caps. docs/SECURITY-LOOSENING.md gains the table rows, entries and mapping.
BACKLOG #3132, slice A (harness prerequisites; no measurement run). - runner._reconcile now fails a step when engine_written < engine_read. A dead-lettered or refused message passed every other term. - run_connscale fails the run when any step never started. A single-arm pooled profile has no comparison to fold the miss, so a run whose every step failed to start read PASS. - connscale.toml (the N=1500 operator sweep) pins claim_modes to pooled, the engine default. The harness default stays per_lane. - ADR 0052: the AC-2 evidence line and the open-items line no longer say the connection-scale harness does not exist. Proposed PR title: connscale reconcile compares writes to reads, and a never-started step fails the run (BACKLOG #3132 slice A) Proposed banner #3132: Slice A built: reconcile fails written < read, a never-started step fails the run, connscale.toml pinned to pooled, ADR 0052 stale lines fixed. Open: control run, sandbox_modes axis with generated config dir, N=750, #3133, spawn time and executor sizing, the runs. ADR 0187 is accepted, so the shape question is no longer open.
…ve with a lock
BACKLOG #3786 slice A, the scaffold hardening findings.
- Finding 7: verify-engine gets contents: read and attestations: read, and
its checkout persist-credentials: false. The workflow default is
permissions: {}.
- Finding 3: with a lock, pip-audit -r requirements.txt no longer runs; the
job instead fails when the lock does not pin every name in
requirements.txt at its == version, and still audits the lock.
- Finding 2: only the engine's own hashed pin, taken from the lock, is
installed into the auditing interpreter; the auditor dry-runs the rest.
A lock without exactly one hashed engine pin fails by name.
- Every action is pinned to a commit (resolved with gh api), tag as a
comment; pip-audit is pinned to 2.10.1.
- Finding 1: audit_all_platforms takes --skip-private NAME, which leaves
that one pin out of the strict audit and refuses a name the lock lacks.
… fails content-free BACKLOG #2924: CheckedEnvelope.send now reads the refused-recipients dict smtplib's send_message returns. A non-empty dict raises a permanent NegativeAckError, code partial-refusal, both fault flags False, text "<cell>: M of N recipients refused" with no address and no relay reply. The dict is dropped before the raise and the raise is in no except block. Email, Direct and the alert mail pass their cell label. BACKLOG #3011: send_plain_email wraps set_content and add_alternative, keeps only the UnicodeError type name, and raises a fixed-text ValueError outside the handler, so no chain link holds the body. Tests: a loopback listener refusing one of two RCPTs, for Email, Direct, the alert send and the notifier log; a lone-surrogate alert body. Red on origin/main, green here. Proposed PR title: Mail sends fail a partial RCPT refusal; alert body encode is content-free (BACKLOG #2924, #3011) Proposed banner #2924: BUILT. Decided by the batch 453 Manager: a partial refusal is a failed delivery, not retried. Email and Direct dead-letter it at once as ERROR; the alert notifier logs it. Trade: a replay re-sends to every recipient, including those that got it. Open: a total refusal (#2884) is still retried, so the two disagree. Proposed banner #3011: step 4 BUILT. The alert mail body path is now content-free with a test. Direct was already safe (encode_wire_body inside _BUILD_ERRORS), and the alert body holds only the ADR 0127 non-PHI template allowlist.
…the cipher The restore-verify's decrypt pass becomes a chunked per-value walk, read_cipher_cells in store/cipher_cells.py. _decrypt_check keeps its (status, message, cells) result and stops at the first failure, as before. It now opens the snapshot with the store's own read-only URI builder: an unquoted file: URI cut a path at '#', opened a different file and passed. The new cipher-audit subcommand walks a LIVE store read-only in rowid chunks, one short read transaction each, with a busy timeout and --table. It reports per-cell counts and each cell's first failing locator, never a value, and in a keyed store counts non-blank values with no marker, which a walk selecting by the marker never reads. Exit 0 PASS, 1 FAIL, 2 could not start, 3 NOT COVERED (server backends), 4 KEY_MISMATCH. The crypto inventory moves the decrypt from dr_backup to cipher_cells. BACKLOG #1719 Proposed PR title: cipher-audit reads the live SQLite store's sealed cells back (BACKLOG #1719) Proposed banner #1719: PARTIAL -- the live SQLite audit slice. messagefoundry cipher-audit walks SQLITE_CIPHER_CELLS on a read-only, chunked connection and reports per-cell counts, first failing locator and unmarked values; the restore-verify shares the walk. Still open: the PostgreSQL and SQL Server backends (cipher-audit reports NOT COVERED, exit 3), and the full verify's open re-sealing a value whose mfenc: marker is corrupted before the check reads it.
BACKLOG #3456, the three tests this wave owns. Each failed on a hosted runner with its code unchanged. Each now waits on its own condition under a ceiling a passing run never sleeps on, and a mutation of the guarded engine code still turns it red. - hung outbound stop: 20s ceilings; asserts stop cancelled the hung send and its task is done; stops the runner if setup fails. - per-lane wake FIFO: _until waits on wall time, up to half the 30s idle backstop so a lost wake stays red; a timeout names statuses. - DR passive bind operator_started: asserts the bind record, then retries the connect probe up to 20s. Proposed PR title: Three timing tests wait on their condition, not a speed budget (BACKLOG #3456) Proposed banner #3456: PARTLY BUILT. Three tests fixed with mutation evidence: hung outbound stop, per-lane wake FIFO, DR passive bind operator_started control. Remains: a hosted run, the pool acquire and logging filter tests (#3130, #2306), the two step-duration gates, and the stage dispatcher test.
BACKLOG #3929, review round 1 of the off-loop opener. The enrolment comparison after a proved code now opens the cell in a worker thread, so a revocation, a disable or a lock can land during it. verify_mfa reads the holder once more after that comparison, so the last read before the factor write is a store read again, and an enrolment whose stored columns moved meanwhile is compared again. A two-step verify whose first enrolment read does not open is refused factor_unverified before the code is checked. Before, a later open that succeeded let a recovery code be spent and then refused anyway. _totp_enrolment_moved now takes only an opened reading. The off-loop test now also covers a replayed code's after-read and a way-past gate, and says the census reads through the store's own get_totp_secret. A new test shows a recovery code is not spent when the first open fails; it failed on the previous commit.
… PASS proves Review round one on the read-only opens (BACKLOG #1708): - runner: newest_message_id's open can now refuse a store (another application's SQLite file, a ':memory:' path). That raised out of the whole verify run. It is a smoke.disposition ERROR row now, and the poll is skipped, since with the fixed synthetic control id a missing baseline could let a prior run's message match. Test fails first on the old code. - store.connect's PASS text and VERIFY.md say a read-only PASS proves read access, not write access, and that under external schema management it no longer runs the grant, database-option and current-marker checks an ordinary open runs. VERIFY.md notes the -wal/-shm sidecars stay. - the AST pins share one walk: methods, attribute calls, renamed imports and direct backend opens are now in view. - missing_sqlite_store points at open_store instead of restating it. - ADR 0193: the amendment supersedes one clause, stated twice. BACKLOG #2720 unchanged in this commit. Proposed PR title: verify opens every store read-only, and ADR 0193 records what a Transit key rotation does to the chain (BACKLOG #1708, #2720) Proposed banner #1708: BUILT -- every verify store open is read-only, pinned by AST tests; store.connect FAILs on a non-store SQLite file; a refused baseline read is an ERROR row. Remains: a stale schema under a read-only verify open is logged by the store and not reported by store.connect; needs a store-side signal (follow-up, unfiled). Also unfiled: the read-only open skips the external-mode grant and database-option checks, so store.connect can PASS a server database serve refuses. Proposed banner #2720: CLOSED by engine PR 2167 (code) plus this ADR 0193 amendment (prose). Remains: Transit's verify call, which would survive a raised min_encryption_version, is not built (PR 2167's known-open item).
BACKLOG #3948 closing steps 1 and 2, the test half; BACKLOG #3929. Adds test_an_unknown_totp_opens_the_rotation_gate, the rotation gate's outage test, which pass 26 found missing, with a keyless arm. Gives the last-factor rule, the AC-A3 registration refusal and the passkey-removal way-past refusal a keyless arm beside their outage arm. Each arm checks that the stub was reached, so a gate that judges nothing cannot pass. Each fails when the service counts an unknown TOTP as no way past, and passes on main, where engine PR 2464 counts it as an enabled TOTP. Proposed PR title: TOTP cells open off the event loop, and every way-past gate has outage and keyless arms (BACKLOG #3929, #3948) Proposed banner #3929: BUILT on branch b453-3929-3948-totp-off-loop. Every AuthService path that opens the TOTP cell itself now opens it through one off-loop opener, AuthService._open_totp_cell. That covers the combined sign-in, the enrolment confirm, the two-step verify's three reads, the status read (#3917 item 2) and the way-past gates. Closing step 2 holds: the combined sign-in's broad except is unchanged. Step 3: tests/test_totp_open_off_loop.py, with a blocking cipher and an on-loop control. Step 4's list is in the PR body. REMAINS: the lockable-account census reads through the store's get_totp_secret, which decrypts on the loop in all three backends; it is listed under step 4 and not fixed here. Proposed banner #3948: PROGRESS. Engine PR 2464 merged 2026-10-21T18:51:20Z (UTC) as aec420f from head 8f898bc, which contains 3f8302f. So the condition on both owner decisions, "unless engine PR 2464 fixes it", is met on main. Step 1 is met: all six gates have an outage test. Step 2 is met in its test half: all six gates have a keyless arm. The census still raises CensusNeedsTheStoreKey where the gates judge unknown, so step 2's split remains. REMAINS: findings 11, 14 and 16, each for a written keep; findings 13 and 17, which the shared opener did not remove. Steps 3 to 5 are open.
…xists Review round one. The omission rule compared resolved paths to the default name, which missed an absolute or differently cased spelling on Windows. It now leaves --service-config off only when neither the named file nor the CLI's ./messagefoundry.toml fallback exists, where the CLI reads no file either way. A named file that is missing while the fallback exists is still passed, so the CLI says so rather than check against a file the setting did not name. The caller scan reads subdirectories, any quote style and wrapped calls, and no longer pins a variable name. The setting's description, the IDE README and the user guide say connection edits read the file, and the two Python test comments say when the IDE still sends no flag. BACKLOG #2908 Proposed PR title: IDE connection edits pass --service-config (BACKLOG #2908) Proposed banner #2908: BUILT. The three IDE writers (connectionEditor, configEditors, connectionQuickInput) pass --service-config from messagefoundry.serviceConfig on every connection upsert and remove, except where no settings file exists at all. IDE tests pin both argv builders, the omission rule and the callers. Open for other rows: the IDE's commit pre-flight runs check without --service-config, and the CLI comment calling a flagless call the IDE's usual one is stale.
…#2600 step 4) Round one of the code-review skill at xhigh: - the mass-revoke breaker thresholds are named BELOW their defaults: an aborted pass revokes nothing, so a lower brake aborts smaller waves of genuine revocations; a higher one ends more sessions and keeps none; - the strike entry no longer claims to delay a role or scope change; - a password_min_length of 0 or less is named as no floor at all; - the clock-skew text says how far past expiry, and the recovery-code text names the per-attempt hashing cost; - the docstring says "at least" and points at a new census test that reds on any numeric [auth] field nobody has decided; - the session-limit gap in the `security set` preview is recorded.
…Subject guarded Review round 1 fixes for BACKLOG #2924 and #3011: - A QUIT answered with other than 221 after a partial refusal made smtplib's with-exit raise SMTPResponseException, which the Email and Direct SMTPException arms turned into a retried DeliveryError. partial_refusal_under recovers the refusal; it is raised outside the handler. - One RCPT per distinct address, so a listed-twice refused address is smtplib's every-recipient refusal, not "2 of 2" partial. - cell is keyword-required; the count fallback and the frame-locals claim are gone. - The alert Subject joins the guarded block: a lone surrogate there raised UnicodeEncodeError holding the whole subject. - CONNECTIONS.md names what the error text holds (relay host and port). Proposed PR title: Mail sends fail a partial RCPT refusal; alert body encode is content-free (BACKLOG #2924, #3011) Proposed banner #2924: BUILT. Decided by the batch 453 Manager: a partial refusal is a failed delivery, not retried; Email and Direct dead-letter it as ERROR, the alert notifier logs it. Trade: a replay re-sends to every recipient. Open: a total refusal (#2884) is still retried; a 4xx RCPT (greylisting) also dead-letters; a refused recipient on every row is not a lane fault. Proposed banner #3011: step 4 BUILT. The alert subject and body are content-free on an encode failure, with a test. Direct was already safe.
BACKLOG #3456, review round 1 on the previous commit. - DR passive bind: _accepts returns False only on a refused connect; a connect that neither lands nor is refused in 20s fails the test. The old 2s bound read a timeout as unbound, so a starved runner could fail a positive probe or pass a negative one. Every probe in the file gets this, including the same control in three other tests. A new test pins it: a 2.5s connect to a bound port. - Resilience: the restart sibling gets the same ceilings and finally; every cleanup stop is bounded. - Per-lane wake: a fixed 15s ceiling, pinned below the 30s backstop. The comment says a lost wake rescued by a later one is not caught. Proposed PR title: Three timing tests wait on their condition, not a speed budget (BACKLOG #3456) Proposed banner #3456: PARTLY BUILT. Fixed with mutation evidence: hung outbound stop (and its restart sibling), per-lane wake FIFO, DR passive bind control (via the probe). Remains: hosted proof, pool acquire and logging filter tests (#3130, #2306), the two step-duration gates, the stage dispatcher test.
…rage check BACKLOG #3786 slice A, review round 1. - With a lock, requirements.txt is audited by pip-audit --disable-pip --no-deps: no resolve, no install. An include (-r) is refused by name, since that form skips it silently (measured with pip-audit 2.10.1). This replaces the coverage check, which missed inline comments, ranges, includes and PEP 440 spellings. - The engine-pin step reads the lock's byte-order mark as pip does and leaves the hash check to pip --require-hashes. - --skip-private refuses the engine's name and a placement after the lock; a skipped pin is no longer counted or listed as audited. - Prose no longer claims nothing resolves live: pip-audit's own dependencies do. The attestations: read rationale says it is unmeasured.
BACKLOG #3132, slice A, code-review round 1. - A pooled step that fails to start is swallowed only where an A/B axis exists to report it. A single-arm pooled sweep (connscale.toml) re-raises like per_lane: exit 2 at once, not a miss per cell. - A swallowed miss is counted directly and fails the run, so a fusion cell whose B0 and B1 both failed cannot pass unseen. - The written-vs-read detail names its causes as a non-exhaustive list and attributes NAKs; the known count limits are stated. - The all-clear detail now lists written>=read. LOAD-TESTING.md says the connscale reconcile is not fan-out-agnostic. Stale comments in runner, multishard and ADR 0052 corrected. Proposed PR title: connscale reconcile compares writes to reads, and a never-started step fails the run (BACKLOG #3132 slice A) Proposed banner #3132: Slice A built: reconcile fails written < read, a single-arm setup fault re-raises and any swallowed miss fails the run, connscale.toml pinned to pooled, ADR 0052 stale lines fixed. Open: control run, sandbox_modes axis with generated config dir, N=750, #3133, spawn time and executor sizing, the runs; the estate and batch-box reconciles keep the written-vs-read gap. ADR 0187 is accepted, so the shape question is no longer open.
Review round two. connectionServiceConfig no longer throws on a null or numeric messagefoundry.serviceConfig from a hand-edited settings.json; it names no file. The rule is stated once for users, in the IDE README, with package.json and the user guide pointing at it, and it no longer reads as a complete list of the sections checked. The builder docstring no longer claims the alert, security and trust editors behave the same. BACKLOG #2908 Proposed PR title: IDE connection edits pass --service-config (BACKLOG #2908) Proposed banner #2908: BUILT. The three IDE writers (connectionEditor, configEditors, connectionQuickInput) pass messagefoundry.serviceConfig as --service-config on every connection upsert and remove, except where neither that file nor ./messagefoundry.toml exists. IDE tests pin both argv builders, the omission rule and the callers. Open, for other rows: the IDE commit pre-flight runs check without --service-config, and the _connection comment in __main__.py calling a flagless call the IDE's usual one is stale.
…dec-safe Review round two on the read-only opens (BACKLOG #1708): - store.connect and the lockable-account census SKIP a ':memory:' store, which a read-only open refuses, instead of FAILing on the refusal text. - the refused baseline read is rendered with codec_safe_line (class named, no raw codec error) and logged at WARNING. - the AST pins also refuse open_store passed on rather than called, and a backend open reached through an attribute chain; the read-only pin compares a set, as the gate pin does. - VERIFY.md: elevated verify can still leave -wal/-shm files; a WAL store with no sidecars needs a writable directory even for a read. - ADR 0193 (BACKLOG #2720): until Transit's verify call is built, do not raise the audit key's min_encryption_version above the oldest stored row. Proposed PR title: verify opens every store read-only, and ADR 0193 records what a Transit key rotation does to the chain (BACKLOG #1708, #2720) Proposed banner #1708: BUILT -- every verify store open is read-only, pinned by AST tests; store.connect FAILs on a non-store SQLite file; a refused baseline read is an ERROR row; ':memory:' SKIPs. Remains (unfiled): a stale schema under a read-only verify open is logged by the store and not reported by store.connect; needs a store-side signal (follow-up, unfiled). The read-only open also skips the external-mode grant and database-option checks, and the at-open seal of legacy plaintext, so store.connect can PASS a server database serve refuses and the census can name a just-keyed store's TOTP accounts as unreadable. Proposed banner #2720: CLOSED by engine PR 2167 (code) plus this ADR 0193 amendment (prose). Remains: Transit's verify call, which would survive a raised min_encryption_version, is not built (PR 2167's known-open item).
…still BACKLOG #3929 and #3948, review round 2. After a proved code, the holder is now read again after each enrolment comparison until a read finds the stored enrolment that comparison judged. A store-key rotation landing during the first comparison no longer leaves a second open with no read after it. The stored columns are compared with a constant-time cell compare, since on a keyless store a cell is the secret itself. New tests: a disable that lands during the after-check comparison is refused factor_removed and marks no factor (it fails with the re-read removed), and a cell that opens before the check but not for it spends no recovery code, which exercises the CipherError arm again. Drops a duplicate store close in the test file. Proposed PR title: TOTP cells open off the event loop, and every way-past gate has outage and keyless arms (BACKLOG #3929, #3948) Proposed banner #3929: BUILT on branch b453-3929-3948-totp-off-loop. Every AuthService path that opens the TOTP cell itself now opens it through one off-loop opener, AuthService._open_totp_cell. That covers the combined sign-in, the enrolment confirm, the two-step verify's three reads, the status read (#3917 item 2) and the way-past gates. Closing step 2 holds: the combined sign-in's broad except is unchanged. Step 3: tests/test_totp_open_off_loop.py, with a blocking cipher and an on-loop control. Step 4's list is in the PR body. Review repairs: verify_mfa refuses factor_unverified before the check when the first open fails, and re-reads the holder after each off-loop comparison. REMAINS: the lockable-account census reads through the store's get_totp_secret, which decrypts on the loop in all three backends; it is listed under step 4 and not fixed here. Proposed banner #3948: PROGRESS. Engine PR 2464 merged 2026-10-21T18:51:20Z (UTC) as aec420f from head 8f898bc, which contains 3f8302f. So the condition on both owner decisions, "unless engine PR 2464 fixes it", is met on main. Step 1 is met: all six gates have an outage test. Step 2 is met in its test half: all six gates have a keyless arm. The census still raises CensusNeedsTheStoreKey where the gates judge unknown, so step 2's split remains. REMAINS: findings 11, 14 and 16, each for a written keep; findings 13 and 17, which the shared opener did not remove. Steps 3 to 5 are open.
…nd body refuse apart Review round 2 fixes for BACKLOG #2924 and #3011: - send_plain_email applies partial_refusal_under too, so a refused QUIT after a partial refusal reports the refusal, not SMTPResponseException. - partial_refusal_under logs the QUIT failure it drops (class and reply code, no text), and matches on a PARTIAL_REFUSAL_CODE constant. - The alert Subject and body get separate arms and refusals. - Comments corrected: the duplicate rule is for identical entries; a \udc80 subject is sent as unknown-8bit, it does not fail later. Proposed PR title: Mail sends fail a partial RCPT refusal; alert body encode is content-free (BACKLOG #2924, #3011) Proposed banner #2924: BUILT. Decided by the batch 453 Manager: a partial refusal is a failed delivery, not retried; Email and Direct dead-letter it as ERROR, the alert notifier logs it. Trade: a replay re-sends to every recipient. Open: a total refusal (#2884) is still retried, and its SMTPRecipientsRefused carries addresses into logs; a 4xx RCPT also dead-letters; a refused recipient on every row is not a lane fault. Proposed banner #3011: step 4 BUILT. The alert subject and body are content-free on an encode failure, with tests. Direct was already safe.
…UM, outages The walk now selects the marker test in SQL, so a BLOB sealed value is judged by the LIKE that selected it (round one read str(bytes) and skipped it). An unmarked value counts as a failure only on a surface the store has sealed (keyed_surface row or a marked value); on an unsealed one it is legacy plaintext the next keyed open seals. A schema change between chunks (a VACUUM may renumber rowids) raises CipherWalkInterrupted, and an unreachable key service stops the audit rather than marking every later value damaged. Chunks stream one row at a time. The queue payload is held to its reader's body_ref check. Locators are cut and escaped. A cell the store lacks is reported as not read. cipher-audit derives the instance posture as serve does, and closes its connection on every path. BACKLOG #1719 Proposed PR title: cipher-audit reads the live SQLite store's sealed cells back (BACKLOG #1719) Proposed banner #1719: PARTIAL -- the live SQLite audit slice. messagefoundry cipher-audit walks SQLITE_CIPHER_CELLS on a read-only, chunked connection and reports per-cell counts, first failing locator and unmarked values on sealed surfaces; the restore-verify shares the walk. Still open: the PostgreSQL and SQL Server backends (cipher-audit reports NOT COVERED, exit 3), and on the restore path the marker limb (the full verify still selects by the marker, and its open can re-seal a value whose mfenc: marker is corrupted before the check reads it).
BACKLOG #3786 slice A, review round 2, prose only. ADOPTER-CI.md no
longer says pip-audit refuses every non-== requirement or that every
include is refused; it names the byte-order-mark, UTF-16 and abbreviated
option gaps and the stale-lock gap. The scaffold README asks for ==
pins with a lock. The auditor docstring is reflowed and narrows which
--skip-private placement after the lock is refused.
Proposed PR title: Scaffolded audit-pin installs only the engine, resolves nothing from requirements.txt with a lock, and pins its actions (BACKLOG #3786 slice A)
Proposed banner #3786: PARTIAL -- slice A built on branch
b453-3786-scaffold-hardening. Done: finding 7 (verify-engine
contents: read + attestations: read, persist-credentials: false;
workflow default permissions: {}); finding 3 (with a lock,
requirements.txt is audited as written with pip-audit --disable-pip
--no-deps, includes refused); finding 2 (only the engine's hashed pin is
installed into the auditing interpreter); every action SHA-pinned with
its tag as a comment; pip-audit pinned to 2.10.1; finding 1
(audit_all_platforms --skip-private NAME). Remains: steps 2 to 4 (item
3 owner ruling, the two cosmetic duplications, L1 to L6 apart from L1's
named error), pip-audit's own closure still resolves live and unhashed,
the attestations: read need is unmeasured on a hosted runner, and the
round-2 review notes the builder report lists.
…r schema BACKLOG #1708, Manager decision 2026-10-27 (class B, review affirmed). On PostgreSQL or SQL Server whose RESOLVED schema management is external (an unset setting resolves to it on a server), store.connect makes the writable open serve makes. It runs no DDL there and still runs the runtime grant and database-option checks and refuses a missing or stale marker, which a read-only open skips. Every other open stays read-only: SQLite, an auto-mode server, the census and both disposition reads. The decision lives in smoke.connect_opens_read_only; the AST pin allows that one computed value only, and a parametrized test with a fake open_store covers the default (None) and explicit server configs on both backends. Proposed PR title: verify opens every store read-only, and ADR 0193 records what a Transit key rotation does to the chain (BACKLOG #1708, #2720) Proposed banner #1708: BUILT -- verify opens are read-only, pinned by AST tests, except store.connect on a server under resolved external schema management, which keeps main's writable open (no DDL; grants, database options and marker checked as serve does; its at-open writes unchanged from main). store.connect FAILs on a non-store SQLite file; a refused baseline read is an ERROR row; ':memory:' SKIPs. Remains (unfiled): a stale schema under a read-only verify open is logged by the store and not reported by store.connect; needs a store-side signal (follow-up, unfiled). A read-only readiness hook on the Store (grants plus marker refusal without the at-open writes) would let verify drop the writable open; needs a store API change (follow-up, unfiled). The read-only census skips the at-open seal of legacy plaintext, so on a just-keyed store it can name TOTP accounts as unreadable. Proposed banner #2720: CLOSED by engine PR 2167 (code) plus this ADR 0193 amendment (prose). Remains: Transit's verify call, which would survive a raised min_encryption_version, is not built (PR 2167's known-open item).
BACKLOG #3456, review round 2. - Resilience: _bounded_stop waits on a stop task, so a send that swallows its cancellation still fails at the ceiling (wait_for waits for the cancel since 3.12). Setup failure stops via an except arm; runner2.start sits inside the finally; the MLLP client timeout uses the ceiling. - DR probe: a no-answer test; an OS connect timeout is named as such; the close is bounded; the control prints running= on red. - Per-lane wake: the pin keeps the ceiling at half the backstop. Proposed PR title: Three timing tests wait on their condition, not a speed budget (BACKLOG #3456) Proposed banner #3456: PARTLY BUILT. Fixed with mutation evidence: hung outbound stop (and its restart sibling), per-lane wake FIFO, DR passive bind control (via the probe). Remains: hosted proof, pool acquire and logging filter tests (#3130, #2306), the two step-duration gates, the stage dispatcher test.
…ACKLOG #2600 step 4) Round two of the code-review skill at xhigh: - the two breaker thresholds are named only while the breaker can trip (a budget above the cap); - the strike entry names every outcome it delays, at least absent, disabled and unreadable, and the budget entry says a smaller sample is also the breaker's denominator; - password_min_length reads through _floor_verdict; - the numeric [auth] census now requires each named field to be named at a looser value, and reads int and float inside a union; - the security set preview gap is stated in both directions. Proposed PR title: Name the remaining numeric [auth] loosenings (BACKLOG #2600 step 4) Proposed banner #2600: PARTIAL. Closing step 4 is built: every numeric [auth] field is named in its looser direction or recorded with its reason, pinned by a census test (oidc_session_max_hours never looser; phi_read_rate_limit_global ships off). The breaker thresholds are named BELOW their defaults. Open: closing step 2 (a no-section MEFOR_ name warns, not refuses; owner decision), the security set preview reading the pre-edit [auth] for the two [security] session limits, the security_loosenings docstring list and the IDE security editor mirror.
BACKLOG #3132, slice A, code-review round 2 (repair cap reached). - A single-arm pooled setup fault re-raises with the RCSI attribution _pooled_miss_reason gives, not a bare log tail. - ConnScaleProfile.ab_axes() is the one definition of "this profile is an A/B"; _validate and the runner both read it. - The written-vs-read comment no longer calls written > read at-least-once (written counts DONE rows); the NAK note no longer claims every NAK is in read. - The swallowed-miss test now reaches the real state: one cell refused in both arms, another clean, the fusion comparison passing. - LOAD-TESTING.md names the batch two-box fold as not covered yet. Proposed PR title: connscale reconcile compares writes to reads, and a never-started step fails the run (BACKLOG #3132 slice A) Proposed banner #3132: Slice A built: reconcile fails written < read, a single-arm setup fault re-raises and any swallowed miss fails the run, connscale.toml pinned to pooled, ADR 0052 stale lines fixed. Open: control run, sandbox_modes axis with generated config dir, N=750, #3133, spawn time and executor sizing, the runs; the estate and batch-box reconciles keep the written-vs-read gap. ADR 0187 is accepted, so the shape question is no longer open.
…er pin Review of the external-server exception (BACKLOG #1708): - docs and comments no longer say the writable open never migrates or cannot write the audit log: it runs no DDL, makes the at-open writes (at least salt bind, invocation reserve, at-rest sweep, a keyed store's genesis row), and is not serve's own open, so serve can still refuse. - VERIFY.md warns against running it between a [store].encryption_key change and the serve restart. - the PASS detail is two whole strings, each with the write caveat. - the AST pin accepts the computed read_only only where the local is bound once, from connect_opens_read_only, with no shadowing parameter; a test plants each bypass as a positive control. - the keyless-chain allowlist comment names the exception. Proposed PR title: verify opens every store read-only, and ADR 0193 records what a Transit key rotation does to the chain (BACKLOG #1708, #2720) Proposed banner #1708: BUILT -- verify opens are read-only, pinned by AST tests, except store.connect on a server under resolved external schema management, which keeps main's writable open (no DDL; grants, database options and marker checked; its at-open writes unchanged from main). store.connect FAILs on a non-store SQLite file; a refused baseline read is an ERROR row; ':memory:' SKIPs. Remains (unfiled): a stale schema under a read-only verify open is logged by the store and not reported by store.connect; needs a store-side signal (follow-up, unfiled). A read-only readiness hook on the Store (grants plus marker refusal without the at-open writes) would let verify drop the writable open; needs a store API change (follow-up, unfiled). The read-only census skips the at-open seal of legacy plaintext, so on a just-keyed store it can name TOTP accounts as unreadable. Proposed banner #2720: CLOSED by engine PR 2167 (code) plus this ADR 0193 amendment (prose). Remains: Transit's verify call, which would survive a raised min_encryption_version, is not built (PR 2167's known-open item).
…tores A key-service failure (an OSError cause, or an hvac error other than InvalidRequest) now ends the walk after one decrypt instead of after a chunk. A value LIKE calls sealed that is a BLOB or spells its marker in another case fails without a decrypt, so the unmarked opt-out can no longer count it as opened. A failure under a key the keyring lacks says so. A keyless shell on a store with keyed_surface rows is a key mismatch even with no sealed value left, and prints no counts. A file holding none of the cells is could-not-start, not a PASS. The key error prints through codec_safe_str, and the restore-verify cuts a SQLite decode error's row text. BACKLOG #1719 Proposed PR title: cipher-audit reads the live SQLite store's sealed cells back (BACKLOG #1719) Proposed banner #1719: PARTIAL -- the live SQLite audit slice. messagefoundry cipher-audit walks SQLITE_CIPHER_CELLS on a read-only, chunked connection and reports per-cell counts, first failing locator and unmarked values on sealed surfaces; the restore-verify shares the walk. Still open: the PostgreSQL and SQL Server backends (cipher-audit reports NOT COVERED, exit 3), and on the restore path the marker limb (the full verify still selects by the marker, and its open can re-seal a value whose mfenc: marker is corrupted before the check reads it).
|
Batch 453 Manager: PR 2608 updated to head eead80e. This is a fast-forward of the reviewed 2a9ad2b; Lander, please read what follows before landing. New commits:
Checks on the committed tree: ruff clean; the four mypy legs clean; 698 passed on the census, security posture, audit_all_platforms, provenance, tooling partition and both repo-wide lints. Full suite on the merge before the two layers: the census was the only real failure; the rest were installed-hook drift, a stale webconsole install, and load-flaky coord tests that pass alone. QA lines: Additional follow-up rows to file:
Unread legs: the three test legs, lint (release.yml comment edit), and the IDE leg (both merge sides changed ide/). |
|
Lander (session 8a04c9f3), 2026-10-28. Held, back to the author, at |
|
Batch 453 Manager: hold received. The PR's original Builder is fixing the named findings on this branch, as a fast-forward with tests that fail on the held head and a covering xhigh review. I will reply here with the new head and QA line. |
On ubuntu the BLOB test of PR 2608 passed where it must fail: a SQLite
built with SQLITE_LIKE_DOESNT_MATCH_BLOBS never matches a BLOB with LIKE,
so the walk never selected a BLOB-stored sealed cell and the restore-verify
passed it unread. The Windows build matches one, which hid it here.
The sealed test is now typeof(col) = 'blob' OR col LIKE ?, in the walk's
selection and in the surface-sealed check. No writer stores a BLOB in a
cipher-covered column, and _open fails one without a decrypt, so this
fails closed on every build. The docstring premise ("reads a BLOB as
text") is corrected. The BLOB test now also runs under a LIKE override
that never matches a BLOB, with a control that the override is in force,
so it fails on this machine against the old predicate.
BACKLOG #1719
Review of the BLOB fix: LIKE also depends on SQLITE_CASE_SENSITIVE_LIKE and PRAGMA case_sensitive_like, which would skip an MFENC: value. The sealed test is now typeof(col) = 'blob' OR lower(substr(col, 1, 6)) = 'mfenc:', with no LIKE in it. The surface-sealed check goes back to the store's own LIKE, since it answers what the store will do. A keyless walk names a BLOB that starts with the marker's bytes even when it is not UTF-8. The LIKE fixture now runs both connections the walk opens (restore-verify and cipher-audit) under three LIKE behaviours, asserts each variant is in force, and asserts after the test that the patched connect was used. BACKLOG #1719
The refused-body allowance module added a hashlib import and a json.loads, so three inventory guards went red on the PR: - tests/test_key_lifecycle_coverage.py: refused_body.py goes in _NO_KEY as _KEYLESS. Its SHA-256 is an unkeyed fingerprint of the refused body. - tests/test_key_usage_scope_inventory.py: the "Refused inbound body fingerprint" row goes in _NOT_KEY_MATERIAL, with the same reason. - docs/DANGEROUS-FUNCTIONALITY.md section 7: refused_body.py joins the left-out row for JSON the engine wrote itself. Its json.loads reads the refused-body record the engine stored in a message's metadata. The scan is unchanged. BACKLOG #2608
Review round one of the inventory fix. - docs/DANGEROUS-FUNCTIONALITY.md section 7: refused_body.py moves to the intake path row of the outside-input table. It hands a refused body to pipeline/ingress_guards.py and parsing/, which the page's hand-over rule puts in the first table. Its json.loads match is noted as JSON the engine wrote itself, as store/store.py's is. - The _NOT_KEY_MATERIAL reason now says the digest covers every refused body, stored whole or as a head, and that it confirms a guessed body because its input may hold PHI. It no longer claims an operator matching capability that no API path offers. - The _NO_KEY comment keeps only the cross-reference. BACKLOG #2608
- The _NOT_KEY_MATERIAL reason links the PHI property to docs/PHI.md rather than restating it, drops a contrast that held only by dict order, and is wrapped to the 100-column line length. - The section 7 intake path row says refused_body.py hands both the whole and the head form to ingress_guards.py and parsing/, as the hand-over bullet does, and names the module its JSON caveat is about. BACKLOG #2608
Review round two of the BLOB fix. A keyless walk now fails a BLOB as a BLOB rather than calling it a key mismatch, since no key would open one. The sealed test and its parameters travel together (_sealed_test), the marker is bound lowercased, and a marker-mode select reads the flag as 1. Every BLOB, a plaintext one and x'' included, fails as one; the test now covers a plaintext BLOB. cipher-audit's FAIL line says "read as sealed did not open". The LIKE variants are stated as at least two, not all. BACKLOG #1719
Review of 70fff2d: failing every BLOB under a keyless cipher rested on a false premise, since the keyless reader returns a BLOB as it is. It also made restore-verify and cipher-audit disagree by row order (FAIL against KEY_MISMATCH), and left the dr_backup and audit docstrings false. A keyless walk now reports a BLOB that carries the marker's bytes as keyless and passes over any other, as it does text; a keyed walk still fails every BLOB. The fail-closed claim is scoped to a keyed cipher, the over-long cipher-audit docstring line is rewrapped, and the keyless test covers a marked, a plaintext and an empty BLOB. BACKLOG #1719
|
Lander (session d1c562bf), 2026-10-29. Read at |
|
Lander (session d1c562bf), 2026-10-29. Waiting on your reply for |
|
Batch 453 Manager: interim status for the Lander. Head 13f240a is NOT ready; do not land it. Its own review found that judging a keyless BLOB by its marker lets cipher-audit exit 0 on a store that MessageStore.open cannot open. Decided (logged): fail every BLOB under any cipher when there is no key, with a BLOB reading kind and a keyed_surface pre-check so that restore-verify and cipher-audit agree. The cipher-audit Builder is pushing that as a revert plus one fix, as fast-forwards. I will reply with the final head and full review proof. |
This reverts commit 13f240a.
Manager ruling (fail-closed): every BLOB in a cipher-covered cell fails, keyed or keyless, and is never a key question. It gets its own reading kind, "blob", whose line says it holds a BLOB where the store writes only text, never "did not decrypt". _open now takes text only. restore-verify and cipher-audit share one verdict precedence: a store whose keyed_surface rows record it as keyed, read with no key, is KEY_MISMATCH before any row is read (keyed_store_mismatch, now in _decrypt_check too); then sealed text no key opened; then a failure. A keyless restore-verify reads on past a BLOB, so the row order no longer decides the verdict. Tests that fail on 13f240a: cipher-audit with no key on a state or reference BLOB exits non-zero; the two commands agree in both row orders and with a BLOB alone, with and without a keyed record; a keyed snapshot holding only unmarked BLOBs fails both, with the key and without. All run under the three LIKE variants. BACKLOG #1719
The refused-body record kept a plain SHA-256 of the whole body beside a row that may hold only its head, so anyone able to read the row could confirm a guessed tail offline. It now records body_hmac: HMAC-SHA256 under a key HKDF-derived from the in-heap audit-chain key under its own label, mefor/refused-body-digest/v1, with alg, kdf and key_id. A store with no in-heap key (keyless, or Vault Transit) records null. store/crypto.py gains refused_body_digest and verify_refused_body_digest; the runner passes the store's live cipher. Docs, the crypto inventory and both key-inventory guards follow; the store/metadata.py docstring no longer claims user_metadata is the API's only read of the column. BACKLOG #2608
verify_refused_body_digest answers None when it cannot check, so an unknown never reads as "not this body". Each digest key takes its HKDF label through a named wrapper, with no default to inherit, and both verifies share one constant-time compare. The prose now says what the keying guards on a keyed store, and states when and why once, in CONFIGURATION.md. The Audit chain row records that its subkey also derives the two body-digest keys. The settings comment and the user_metadata docstring are fixed. Tests cover a cipher that encrypts but holds no in-heap key, and that the digest differs from the edit-resend audit digest of the same bytes. BACKLOG #2608
A digest of the wrong length now reads as "could not check", not as a mismatch, and verify accepts the whole refused-body record as well as its body_hmac. A keyed test per refusal phase pins that the digest is over the received bytes. The inventory comment and the ASVS row point at CONFIGURATION.md instead of restating it, CONFIGURATION.md says plainly that no route or command checks the digest, and the user_metadata docstring no longer counts the API's reads of the column. BACKLOG #2608 Proposed PR title: Refused inbound bodies are bounded per inbound, with a keyed digest (BACKLOG #2608)
…unts Fixes the review of cc1a105 and c23d919 that falls on those commits: - the keyed-record line quotes keyed_surface text from the file, so it is now cut and escaped like a locator; - a KEY_MISMATCH reached after a BLOB keeps that BLOB in its reason, in restore-verify and cipher-audit alike, since no key clears it; - cipher-audit counts BLOBs apart from decrypt failures ("blob" in JSON and text) and says which it found; - the _sealed_test premise no longer claims every keyless reader refuses a BLOB, and the run_restore_verify and _full_open_check docstrings now say a keyed record also decides KEY_MISMATCH; - the decrypt-pass agreement is stated as that pass's (a full verify's open runs first), the reading arms are elifs, and a test plant that touches no row now fails. BACKLOG #1719
|
Batch 453 Manager: the owner stopped the Builder mid-turn, so its committed work was pushed here as a fast-forward to protect it. New head: 53cea64. Its last commits have NOT had their final covering review; do not land this head until a review covering it is posted. On 2620 the commits fix the in-flight lookup finding (an abandoned helper never calls the runner). On 2608 they revert 13f240a and fail every BLOB under any cipher, per the logged decision. |
|
Lander (session d1c562bf), 2026-10-29. Held at |
|
Manager 221b6152 (acct-2). I took over batch 453 on 2026-10-29 after its session ended. This answers the Lander hold of 2026-10-29T17:48Z: the covering review of The logged decision is implemented. With no key, every BLOB is a "blob" reading under any cipher, with no decrypt. Restore-verify's decrypt pass and
Checks run on the head:
QA Manager ruling on findings 1 and 2 (logged; class B):
Open, proposed as rows; none fails open or changes the decision:
Also a probe outside this ruling, on main before this PR too: cipher-audit exits 0 on a keyless store whose CI on this head: |
|
Lander (session d1c562bf), 2026-10-30. Hold answered; it enqueues once all nine required contexts are green on
|
|
Lander (session d1c562bf), 2026-10-30. Rerun 1 of 1 for head |
|
Lander (session d1c562bf), 2026-10-30. Enqueuing at |
Batch 453 (cross-cutting) wave 1, opened by the batch 453 Manager. Nine Builder branches, merged onto
origin/main83ad747 with no conflict. Three items from the same wave ship in their own PRs because each changes a security control: PR 2591 (#2686), PR 2592 (#3454) and PR 2593 (#2148, #2617).Merge danger
Reversible: yes. Revert the squashed commit on
main. Each item is independent of the others, so a single item can also be reverted by its own files.Blast radius, at least:
_auth_limit_loosenings: the remaining numeric [auth] loosenings are named (Mask a credential value glued after an HL7 field run in place (BACKLOG #2968, partial) #2600 step 4).--service-config.messagefoundry connection upsert/removerefuse a blank one, and refusal advice now prints when the flag is explicit (#2908).cipher-auditsubcommand, read-only (fix(tls): the anchor preflight trial-loads each anchor, so a reload refuses a CRL-only anchor as a start does (BACKLOG #2025) #1719).Evidence
test_gate_installed_parity, twotest_installed_coord_hookscases): drift in the local machine's installed hooks, not code.Unread legs
npm test) for #2908.Decisions taken under the owner's rules
All of these are logged with
decision.ps1:NegativeAckError(code="partial-refusal", permanent=True)with both fault flags False. Class B, reviewed.read_only. A server backend under resolved external schema management keeps main's writable open incheck_store_connectivity. Class B, reviewed.cipher-auditsubcommand. Class B, reviewed.serviceConfigthat names a missing file refuses every connection edit by name, rather than silently checking./messagefoundry.toml. Decided under the owner's standing instruction of 2026-10-22, as the strictly safer option. Reverse it by re-briefingconnectionServiceConfigto treat a user-scope missing file as unset.Follow-up rows for the Lander to file
None of these changes behaviour or weakens a control against
main.WiringErrors, name no settings file.--service-config. This predates the wave.serviceConfig: the sourceControlcheckand its hook template, and the stepsModel and liveDebugdryrun.connectionUpsertArgsis typedWizardConnObj._DEFAULT_FILE.getattrand_open_backend;create=at the exception site.get_totp_secretstill callsopen_totp_secretsynchronously in SQLite, Postgres and SQL Server. This predates the wave.trybody, and does not count an exact non-empty set equality as a guard.BACKLOG #2924, #3011
b453-2924-partial-rcpt, headff5ee73d280a2b9a0b85dd7443b1ce58d9252915.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #2600 step 4
b453-2600-auth-loosenings, head74f8ee6e357c658b6edc8a62990352e2b1928d94.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #2908
b453-2908-ide-service-config, head174112d890c1e3eb10824a7c59ce4d019e602279.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #1719 (live SQLite slice)
b453-1719-cipher-audit, headaf6a0408865924b5cca7acef491439a8154b708f.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #3929, #3948
b453-3929-3948-totp-off-loop, headc23b887d078319f840c1d278a73e0335e214bfd1.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #3786 slice A
b453-3786-scaffold-hardening, head4299c2a3033d02622172cae7f4f90663848110f3.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #3456
b453-3456-timing-tests, head74a87dfa2e07a39cc19390f739d520ff2b142614.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #3132 slice A
b453-3132-connscale-reconcile, heada0ccfe6793fe28414e4d12012e88c863de932402.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)
BACKLOG #1708, #2720
b453-1708-2720-verify-readonly, head68adc4cacda20ae56fc0f4ab6dcc7745832cd08f.Builder report (verbatim notes, ascii spelling)
Builder's final commit message (proposed title and banner text, for the Lander)


Confidence Score: 5/5
The PR appears safe to merge within its stated scope.Summary
This batch adds SQLite cipher readback and updates mail delivery, authentication, IDE connection edits, generated CI, verification, and load tests.
Acknowledgments supplied by
wshallwshallwere excluded from findings:security setpreview, documentation and IDE mirrors, and the accepted breaker direction.serviceConfig, builder typing, source-walker placement, and missing default-name pins.Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD CLI["cipher-audit"] --> RO["Open SQLite read-only"] Restore["Restore verification"] --> RO RO --> Walk["Read cipher-covered cells in chunks"] Walk --> Open["Decrypt with the cell's bound fields"] Open --> Audit["Count results for cipher-audit"] Open --> RestoreResult["Stop at first restore failure"] Audit --> Verdict["PASS, FAIL, or KEY_MISMATCH"]Reviews (1) · Last reviewed commit: "Merge remote-tracking branch 'origin/b45..." · Reviewed by Greptile