You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(backlog): close two rows whose work is on main, and un-stale a third
Read the subject-exists screen's candidate list (BACKLOG #1426, open in PR
806, not yet on main) and verified candidates against the code rather than
against the screen.
CLOSED, both verified by driving rather than reading:
#1392 the PR-609-after-ADR-0172 ordering constraint. 6e0a950 (ADR 0172,
07:29:46Z) and 671d575 (PR 609's edit, 08:31:45Z) are both
ancestors of origin/main under merge-base --is-ancestor, in the
required order. ADR file plus index row present. Both corrected
files carry the excluded-topology caveat. A grep for "always serves
TLS" in CLAUDE.md returns nothing and that negative is FALSE: the
phrase wraps a line break.
#1389 the CI guard that bound the wrong step. Fixed on main in e9fa3b4
(PR #733). _engine_step_invocations() returns exactly one hit, the
engine step at ci.yml:852, not the tooling line at :1162. Two
mutation controls fire and the unmutated file stays green.
STILL OPEN, remainder sharpened:
#1276 part A shipped in 6e0a950; the row still said origin/main carries
NONE of it. That is the shape that costs a Builder. Corrected in
place, with the one real remainder named: nothing re-mints an
expired generated pair, which api/tls.py:114-117 states itself.
Two findings about the screen, recorded in the report rather than here: its
path-added-after signal is unsound under a shallow clone, and its verdict
counts move with clone depth.
Gates run in this worktree: backlog_status_check (OK, 657 items each with
exactly one status), link_check (OK), backlog_citation_check (OK),
banner_sha_check (10 findings, all pre-existing rows this diff does not
touch), dangling_citation_check, citation_line_check, verdict_divergence
(advisory, exit 0). pytest cannot run here: no dependencies installed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/BACKLOG.md
+56-5Lines changed: 56 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13940,7 +13940,21 @@ measurement from this row's subject and it is named here rather than performed.*
13940
13940
> **FIVE WRITTEN "DEV ONLY" PROHIBITIONS MUST BE REWRITTEN IN THE SAME CHANGE, or the tree ships a control its own docstring forbids.** `pki.py:141-143` records that the returned key is unencrypted PKCS#8 and that a self-signed certificate *"has no chain of trust and must never front production PHI"*; `__main__.py:578`, `:3642`, `:3677` and `:3689` repeat the restriction in the CLI help, the docstring, the JSON note and the console note. **The owner has authorised the override (2026-08-16).** The honest replacement text is that an untrusted certificate is strictly better than cleartext and strictly worse than an operator-supplied chain, so the generated pair is a **placeholder to be replaced**, not an endorsed production terminator.
13941
13941
> **WHAT AN OPERATOR NOTICES, and half of it is unpleasant.** A browser reaching the console gets a full-page trust interstitial until the certificate is imported into Local Computer / Trusted Root ([`docs/TRAY.md:133`](TRAY.md) already documents that import). More importantly, **the first-party clients infer the scheme from CONFIGURATION, not from the socket**: the tray reads `[api].tls_cert_file` out of the service TOML to choose `http` or `https` ([`messagefoundry/tray/config.py:207-219`](../messagefoundry/tray/config.py)). A generated certificate that does not surface through that key would leave the tray, the harness, `apiclient` and the IDE dialling `http` at an `https` listener.
13942
13942
> **SCOPE, AND THE PART DELIBERATELY OUTSIDE IT.** [ADR 0143](adr/0143-web-console-on-by-default-disableable-with-loopback-secure-context-browser-hardening.md) sec. *"Deferred (considered, not built): auto-TLS on loopback"* sized the whole move as **XL**, precisely because it forces a lockstep client migration across the harness, `apiclient`, the tray and the IDE. **This item is the mint-and-serve half plus whatever minimum makes those four agree on the scheme.** If the client work turns out to be the bulk, split it rather than letting this item quietly become ADR 0143's XL.
13943
-
> **BUILD STATE, MEASURED ON THE BRANCH AND NOT ON `main` -- so a lane does not rebuild what exists.** *All of it on `claude/builder-1-1245-1276a` at `17c16128` (PR 534), by the builder holding the lane, with controls. `origin/main` carries NONE of it.* **ALREADY BUILT THERE: (a) the superseding ADR.** `docs/adr/0172-the-engine-always-serves-tls-minting-a-self-signed-certificate-on-first-run.md` exists on that head and is **x0 on `origin/main`** -- so it is allocated and written. ***NOBODY ALLOCATES A SECOND NUMBER FOR THIS***; two separate dispatch messages told a lane to allocate one, and both were wrong. **(b) Part A**, `api/tls.py:133` mints on first run, and `make_self_signed` has **3 call sites there against `main`'s 2**. **STILL ABSENT: the audited re-mint.** `cert_expiry.py` carries **0** re-mint references against a control of **9** definitions, and `api/tls.py:106-109` is a docstring *admitting* nothing re-mints an expired pair, so day 366 serves a certificate every client rejects. **AND ONE CITATION IN THIS ROW IS OFF BY SIX LINES:** part B's prose is at **`pki.py:227`**, not the cited `221-222`; `:221` is the DEV ONLY line. *Locate by phrase.* **NOT A TARGET, stated so nobody widens the sweep into a breakage:** the XML namespace constants in `wsdl.py` and `soap.py` are `http://` by specification. **Changing them breaks SOAP.**
13943
+
> **SUPERSEDED 2026-09-03 -- THE PARAGRAPH BELOW WAS MEASURED ON A BRANCH AND IS NOW FALSE ABOUT
13944
+
> `main`. READ THIS FIRST.** It says `origin/main` carries NONE of part A. It carries **all** of it,
13945
+
> as of `6e0a950b6` (PR 575), verified at `46ea10a78`: `docs/adr/0172-the-engine-always-serves-tls-minting-a-self-signed-certificate-on-first-run.md`
13946
+
> is on main with its index row at `docs/adr/README.md:197`, `messagefoundry/api/tls.py` is on main,
13947
+
> and `ensure_api_tls_material` has call sites in `api/tls.py`, `api/app.py` and `__main__.py`.
13948
+
> **THE REMAINDER IS ONE LIMB AND THE SHIPPED CODE NAMES IT ITSELF: nothing re-mints an EXPIRED
13949
+
> generated pair.** `messagefoundry/api/tls.py:114-117` says so in terms -- `build_api_ssl_context`
13950
+
> performs no expiry check, so a site past day 365 would serve a certificate every client rejects,
13951
+
> with `CertExpiryRunner` alarming meanwhile. **Do not rebuild part A.** Left uncorrected, the
13952
+
> paragraph below is the exact shape that costs a whole Builder: a branch-scoped measurement read
13953
+
> later as a statement about main. Found by `scripts/docs/subject_exists_screen.py`, the subject-exists
13954
+
> screen filed as BACKLOG #1426 -- allocated and open in PR 806, **not yet on `main`**, so that number
13955
+
> resolves to nothing in this file until it lands.
13956
+
>
13957
+
> **BUILD STATE, MEASURED ON THE BRANCH AND NOT ON `main` -- so a lane does not rebuild what exists. STALE, see above.** *All of it on `claude/builder-1-1245-1276a` at `17c16128` (PR 534), by the builder holding the lane, with controls. `origin/main` carried NONE of it WHEN THIS WAS WRITTEN; it now carries part A.* **ALREADY BUILT THERE: (a) the superseding ADR.** `docs/adr/0172-the-engine-always-serves-tls-minting-a-self-signed-certificate-on-first-run.md` exists on that head and is **x0 on `origin/main`** -- so it is allocated and written. ***NOBODY ALLOCATES A SECOND NUMBER FOR THIS***; two separate dispatch messages told a lane to allocate one, and both were wrong. **(b) Part A**, `api/tls.py:133` mints on first run, and `make_self_signed` has **3 call sites there against `main`'s 2**. **STILL ABSENT: the audited re-mint.** `cert_expiry.py` carries **0** re-mint references against a control of **9** definitions, and `api/tls.py:106-109` is a docstring *admitting* nothing re-mints an expired pair, so day 366 serves a certificate every client rejects. **AND ONE CITATION IN THIS ROW IS OFF BY SIX LINES:** part B's prose is at **`pki.py:227`**, not the cited `221-222`; `:221` is the DEV ONLY line. *Locate by phrase.* **NOT A TARGET, stated so nobody widens the sweep into a breakage:** the XML namespace constants in `wsdl.py` and `soap.py` are `http://` by specification. **Changing them breaks SOAP.**
13944
13958
> **THE CLIENT-SIDE SCHEME DEFAULTS ARE AT LEAST 14, AND THE FIGURE TRAVELLING IN SESSION MAIL WAS 8.** *Measured 2026-08-23 by the builder holding the lane, on `claude/builder-1-1245-1276a` at `17c16128`, and written here because a count that lives only in mail is re-derived at full cost by the next reader.* A strict `= "http://` predicate over engine-URL defaults -- non-test, XML namespaces excluded with a working control that correctly dropped 13 namespace lines -- returns **11 sites**. **That predicate provably misses at least three more**: list comprehensions at `harness/load/shardcert.py:3383` and `:4453`, and a positional argument at `harness/load/connscale/batchbox.py:200`. **So the number is AT LEAST 14, stated as a floor rather than a total, because the predicate is known to under-count and no exhaustive form of it has been run.** `apiclient/client.py:237` is confirmed as the public constructor default. *Nothing in this row previously carried a count; the 8 was never in the ledger, which is how it stayed unchecked while being quoted.*
13945
13959
> Verdict: build
13946
13960
> Closing-act: code
@@ -18118,9 +18132,31 @@ silent expiry are the defect.
18118
18132
18119
18133
## 1389. a REQUIRED CI guard is green while asserting against the wrong step: its locator binds the tooling pytest line, not the engine one it names
18120
18134
18121
-
> 🔢 **FILED 2026-08-29 (builder 2).** `tests/test_ci_engine_step_excludes_webconsole.py` exists to
18135
+
> ✅ **CLOSED 2026-09-03 -- fixed on `origin/main` in `e9fa3b440` (PR #733), verified by DRIVING the
18136
+
> guard rather than reading it.** `e9fa3b440` is an ancestor of `origin/main`. The locator now binds
18137
+
> the step by NAME (`_ENGINE_STEP = "Tests (pytest)"`) and joins backslash continuations before
18138
+
> matching, and calling `_engine_step_invocations()` against HEAD returns **exactly one** hit: job
18139
+
> `test`, the wrapped `retry-native-crash.sh pytest ... -m 'not tooling'` command at
18140
+
> `.github/workflows/ci.yml:852` -- the engine step, **not** the tooling line at `:1162` this row was
18141
+
> filed about. **Two mutation controls fired, and the first attempt at them did not**, which is why
18142
+
> they are recorded: replacing the glob on the engine step with the broken plain
18143
+
> `--ignore=packaging/messagefoundry-webconsole/tests` turns both assertions red, and deleting the
18144
+
> subtraction turns the subtraction assertion red, while the unmutated file stays green. An earlier
18145
+
> pass of those same mutations changed no bytes -- the replacement string did not match the raw
18146
+
> spelling in `ci.yml` -- and reported PASS, which is indistinguishable from a guard that cannot
18147
+
> fail. **A mutation control must assert that it mutated something.** Screened by
18148
+
> `scripts/docs/subject_exists_screen.py`, the subject-exists screen filed as BACKLOG #1426 --
18149
+
> allocated and open in PR 806, **not yet on `main`**.
18150
+
>
18151
+
> **NOTE ON WHAT WAS NOT RUN HERE.** `pytest` cannot execute in this worktree -- no dependencies are
18152
+
> installed, and importing the suite dies at `ModuleNotFoundError: No module named 'pydantic'`. The
18153
+
> three assertions were driven by loading the test module directly and calling them, which exercises
18154
+
> the same code without the conftest. The full suite legs are unread from here.
18155
+
>
18156
+
> **FILED 2026-08-29 (builder 2).** `tests/test_ci_engine_step_excludes_webconsole.py` exists to
18122
18157
> stop the engine pytest step double-running the ~356 web-console tests that `testpaths` includes
18123
-
> (BACKLOG #1027). ***IT PASSES. IT IS A REQUIRED CHECK. AND IT IS NOT LOOKING AT THE ENGINE STEP.***
18158
+
> (BACKLOG #1027). ***IT PASSED. IT WAS A REQUIRED CHECK. AND IT WAS NOT LOOKING AT THE ENGINE
18159
+
> STEP.*** That is fixed; the text below is the record of the defect, not of current state.
18124
18160
>
18125
18161
> **Scored 2026-09-03 -> P3.** Value **1/10** · Difficulty **1/10** · _fill-in_. Verified shipped by DRIVING the guard, not reading it: the locator now binds the step structurally by name at tests/test_ci_engine_step_excludes_webconsole.py:40 and joins backslash continuations first at tests/test_ci_engine_step_excludes_webconsole.py:43, and calling _engine_step_invocations() against HEAD returns exactly one hit, job "test", the wrapped retry-native-crash.sh command at .github/workflows/ci.yml:852 -- not the tooling line at ci.yml:1162 this row names. A five-case mutation battery over patched copies of ci.yml confirmed the assertions point the right way: a plain --ignore on the engine step goes red, the same flag hidden on a continuation line goes red, a dropped --ignore-glob goes red, renaming the step fails loudly at tests/test_ci_engine_step_excludes_webconsole.py:126, and a harmless reformat preserving the glob stays green. It is registered and collected, not orphaned: tests/tooling_manifest.txt:45 lists the file, so pytest -m tooling collects all 3 tests, and pytest on the file passes 3 of 3. The fix is on origin/main (e9fa3b440, PR 733), confirmed with git merge-base --is-ancestor. The only residual is bookkeeping -- the row still reads as open with stale present-tense text and drifted coordinates at docs/BACKLOG.md:17883 -- which is a banner flip and a doc edit, so value 1 and difficulty 1 stand.
18126
18162
@@ -18264,10 +18300,25 @@ an affected seat is alive, working, and unreachable by the channel that leaves a
18264
18300
18265
18301
## 1392. PR 609 must land WITH OR AFTER ADR 0172: it replaces a stale understatement of the TLS posture with an overstatement that is false on main, and links an ADR file main does not have
18266
18302
18267
-
> 🔢 **FILED 2026-08-29 (builder 2).** PR 609 deletes two strings saying remote TLS exposure is
18303
+
> ✅ **CLOSED 2026-09-03 -- the ordering held, verified against origin/main at its 2026-09-03 head.**
18304
+
> This row asked for one thing: that PR 609's doc edit never land before ADR 0172. It did not. `6e0a950b6`
18305
+
> (ADR 0172, 2026-09-02T07:29:46Z) and `671d57501` (PR 609's edit, 08:31:45Z) are **both ancestors of
18306
+
> `origin/main`** under `git merge-base --is-ancestor`, an hour apart and in the required order --
18307
+
> checked here against a negative control, an invented sha, which the same probe correctly refused.
18308
+
> The ADR file is on main with its index row at `docs/adr/README.md:197`, and both corrected files
18309
+
> carry the excluded-topology caveat this row demanded: `messagefoundry/api/app.py:19-25` and
18310
+
> `CLAUDE.md:119-127`. **A grep for the phrase "always serves TLS" in `CLAUDE.md` returns nothing,
18311
+
> and that negative is FALSE** -- the phrase wraps a line break as `**always\n serves TLS**`. Read
18312
+
> the paragraph, not the grep; a confident negative from a line-oriented tool is the reading to
18313
+
> distrust. Nothing runnable remained, only this banner. Screened by
18314
+
> `scripts/docs/subject_exists_screen.py` -- the subject-exists screen filed as BACKLOG #1426,
18315
+
> allocated and open in PR 806, **not yet on `main`** -- and then verified against the code.
18316
+
>
18317
+
> **FILED 2026-08-29 (builder 2).** PR 609 deletes two strings saying remote TLS exposure is
18268
18318
> still to come -- `CLAUDE.md:120` and `messagefoundry/api/app.py:19` -- and replaces them with text
18269
18319
> asserting the engine **always serves TLS**, minting a self-signed certificate on first run, citing
18270
-
> **ADR 0172**. ***BOTH THE OLD TEXT AND THE NEW TEXT ARE WRONG ABOUT MAIN, IN OPPOSITE DIRECTIONS.***
18320
+
> **ADR 0172**. ***BOTH THE OLD TEXT AND THE NEW TEXT WERE WRONG ABOUT MAIN, IN OPPOSITE
18321
+
> DIRECTIONS*** -- both are now corrected on main, which is why this row closes.
18271
18322
>
18272
18323
> **Scored 2026-09-03 -> P3.** Value **1/10** · Difficulty **1/10** · _fill-in_. All three limbs of the ordering constraint hold at HEAD, verified by running rather than reading. ADR 0172 landed first (commit 6e0a950b6, 2026-09-02 07:29 UTC) and PR 609's doc edit landed after it (commit 671d57501, 08:31 UTC), and git merge-base --is-ancestor confirms the ancestry, so the hold this row exists to enforce was honored. The ADR file and its index row both exist (docs/adr/README.md:197), and every live relative 0172 link resolves -- the single unresolvable path is the placeholder inside this row's own table, not a shipped link. The replacement text is now true of main: calling ensure_api_tls_material with default ApiSettings minted api-generated-cert.pem plus api-generated-key.pem, returned the identical pair on a second call, and returned None only under tls_terminated_upstream (messagefoundry/api/tls.py:87), while the serve path calls it unconditionally and not behind --allow-insecure-bind (messagefoundry/__main__.py:2885), and both corrected files carry the excluded-topology caveat (CLAUDE.md:120, messagefoundry/api/app.py:19). Nothing runnable remains; the only residue is closing the row, which parse_items still reports open at docs/BACKLOG.md:18023.
0 commit comments