oficina / home Public

Re-review: the fix introduced a false reason of the class it removes

The branch's own thesis is that a false reason in a binding file is
worse than no reason. The fourth commit then gave one.

It blamed the v0.22.0 pin bump for falsifying the "zero bare `rst-*`
attribute selectors" claim. Counted across every cached version: the
twins arrive at v0.21.0 (0 bare selectors before it, 130 at it), and
this repo's FIRST go.mod pinned v0.21.0. The bump to v0.22.0 took 130
to 130 and falsified nothing. What happened is that the claim was
verified on 2026-08-30 against a rastrillo with 528 class occurrences
and no twins — true when written, and already false by the time the
skeleton existed. The rule to write classes survives either way; the
story about how we found out did not.

One line below it, "adopt `rastrillo doctor` the day it lands" was a
trigger that had already fired: doctor shipped in v0.21.0, the same
version. The same commit that re-checked one dependency claim left the
one beneath it unchecked. There is also no vendored `static/` in the
tree — page.go links no stylesheet — so "re-copy static/tokens.css"
was an instruction with no object.

Carries the RP ID rule, which this file never had. Spec §4 and rulings
2 and 13 make it a permanent, test-backed constraint, and it is
exactly the kind of thing that reads like an improvement: WebAuthn
ACCEPTS a suffix RP ID, so widening to `oficina.works` looks harmless
and silently collapses the origin split. `passkey.Config.LegacyRPID`
is a second door to the same place — it passes straight through to
webauthn.Config as another accepted RP ID — so both halves are named.

The gate-9 sentence was a status line ("is not there yet") in a file
that governs belief. Restated as the rule: gate 9 needs no database,
so it is not sequenced behind one.

§11's own numbers are corrected on spec/springboard-and-corrections
rather than here — the spec is the file that was wrong, and this one
now agrees with it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev f9f1d24ca6fcf8e9d3ee23102258a53321e225e8 parent 4d054bd
1 file changed, +33 −7
  • AGENTS.md +33 −7

CI passed — run details

diff --git a/AGENTS.md b/AGENTS.md
index fa21a69..9313d5d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -35,8 +35,14 @@ grep** over the raw SQLite file and WAL **plus this app's store objects**,
against a seeded corpus of known addresses; a **no-address-at-rest** test
asserting the schema has no address column and that a full sign-in plus
directory upsert **plus rekey** leaves no readable address anywhere, **WAL
-included**; and **no-content-in-logs** (gate 9). Gates 1 and 2 need a
-database and the skeleton has none; gate 9 does not, and is not there yet.
+included**; and **no-content-in-logs** (gate 9). **Gates 1 and 2 need a
+database and the skeleton has none. Gate 9 needs no database** — it scans
+strings, and `cmd/home/main.go` already emits log lines — **so it is not
+sequenced behind one**, which is why §13 step 1 puts it beside the
+skeleton. A guard written after the code it guards is a guard written to
+pass. (Stated as the rule rather than as a status: which gates exist today
+is a question for `git log`, and a status line in a binding file is a
+sentence that goes stale without anyone noticing.)
---
@@ -106,6 +112,16 @@ quietly ignored).
minting, and **never renders an account-authored string**. It is the
relying party. This is a permanent constraint with its own test, not a
naming choice.
+- **The RP ID is the full host — `id.oficina.works` — asserted by a test.**
+ Never widen it to a registrable suffix. WebAuthn *permits* an RP ID that
+ is a suffix of the origin's hostname, so `oficina.works` would be
+ accepted; it is also valid at every host in the zone, the directory and
+ every team instance included, which collapses the very split the two
+ origins exist to make (§4, rulings 2 and 13). The widening has a second
+ door: `passkey.Config.LegacyRPID` is passed straight through to
+ `webauthn.Config` as a second accepted RP ID, so it must stay empty
+ unless a rename drill (§5.7) is actually running, and then hold a full
+ host. Both halves need the test, because both are accepted silently.
- Assertions carry **identity and display preferences, never
authorization**. The boundary test (§5.4) is **two-sided**: a claim may
ride the assertion only if **(a)** the instance makes no trust decision
@@ -172,11 +188,21 @@ quietly ignored).
writes today." So the rule stands and the justification does not: write
classes because that is what the partials we render alongside write, not
because the attribute grammar is unreleased. **Re-check this when the pin
- moves** — it is a claim about a dependency, and bumping the dependency is
- what falsified the last one.
-- **Re-copy `static/tokens.css` on every rastrillo upgrade.** It is frozen
- at scaffold time while partials upgrade with the module. Adopt
- `rastrillo doctor` the day it lands and delete this step.
+ moves, and name the version you checked.** Note what actually falsified
+ the old claim, because this file got that wrong too: the twins arrived in
+ **v0.21.0**, which is the version this repo's *first* `go.mod` pinned. The
+ claim was verified on 2026-08-30 against a rastrillo that had 0 bare
+ selectors and 528 class occurrences — true then, and already false by the
+ time the skeleton existed. The later bump to v0.22.0 changed 130 to 130
+ and falsified nothing.
+- **`rastrillo doctor` has landed** — in v0.21.0, the first version this
+ repo pinned. "Adopt it the day it lands" was a trigger that had already
+ fired when it was written. When this app vendors `static/`, run
+ `rastrillo doctor --fix` on each upgrade rather than re-copying by hand,
+ and keep the `TestVendoredAssetsMatchTheLibrary` that `rastrillo new`
+ scaffolds as the standing gate. There is no vendored `static/` in the
+ tree today — `internal/home/page.go` links no stylesheet, deliberately —
+ so this is an instruction with no object until the first asset arrives.
- Zero JS. **No surface here has any reason to require script**, and the day
one does is the day the spec is wrong.