oficina / home Public

Fold the approving review: the tree diagram, the CSP test, the mailer

Approved by Fable at round seven. Three follow-ups folded in rather
than left for the executor to trip over.

The File Structure still put rpid_test.go under internal/guardstest
while Task 7 puts it in internal/home, with the reason — it reads the
app's own config through a helper over the unexported App, which a
guards-package test cannot reach.

The CSP test would not have compiled: defaultCSP is unexported in
serve.go. It asserts Options.CSP stays empty and the served header
carries no unsafe-inline, which is the same property from the outside —
and notes that rastrillo's default already delivers §11's script-src
self through default-src self, so there is nothing to override.

And mail.Sender and signin.Mailer have identical method sets, so the
capturing test sender plugs into Flow.Mailer with no adapter.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 3fd6a054e01e5159662cabe3dc8baab7f3a49c46 parent 4aca0f9
1 file changed, +14 −2
  • docs/superpowers/plans/2026-09-03-home-signin.md +14 −2

CI passed — run details

diff --git a/docs/superpowers/plans/2026-09-03-home-signin.md b/docs/superpowers/plans/2026-09-03-home-signin.md
index aca9eb0..3cc10c1 100644
--- a/docs/superpowers/plans/2026-09-03-home-signin.md
+++ b/docs/superpowers/plans/2026-09-03-home-signin.md
@@ -204,10 +204,13 @@ internal/home/
templates/ Scriptless screens, attribute spelling
(ruling 20; the seven utilities keep class).
logtest/ Gate 9. Already on main (9162ee5).
+ rpid_test.go Rulings 13/16: the RP ID is the full host.
+ Package home, not guardstest: it reads
+ the app's own passkey.Config.
+ noscript_test.go §11 + ruling 21's allowlist.
internal/guardstest/
logsinks_test.go Already landed. Forbids non-slog sinks.
noaddress_test.go Gate 2's schema half.
- rpid_test.go Rulings 13/16: the RP ID is the full host.
```
---
@@ -869,7 +872,9 @@ lost or would have had to write:
Configuration: `Origin: "https://id.oficina.works"`, `LinkPath:
"/signin/verify"`, a non-zero `Key` from config (it seals the pending blob
and **must not** come from an instance data key — sign-in runs before any
-session exists), `Mailer`, `Classifier`, and `Keymail` **with
+session exists), `Mailer` (rastrillo's `mail.Sender` and `signin.Mailer` have identical
+method sets, so the capturing test sender plugs straight in with no
+adapter), `Classifier`, and `Keymail` **with
`RedirectPath: "/signin/callback"`** — its default is `/auth/callback`, so
mounting the route without setting this leaves the two disagreeing.
@@ -1334,6 +1339,13 @@ func TestNoScriptTagOutsideTheAllowlist(t *testing.T) {
}
// The carve-out must not widen into unsafe-inline behind our backs.
+//
+// Do NOT reference rastrillo's defaultCSP — it is an unexported const in
+// serve.go. Assert that the app leaves Options.CSP empty and that the
+// SERVED header's default-src and script-src carry no 'unsafe-inline'.
+// (§11 says the credential origin moves to script-src 'self'; rastrillo's
+// default already delivers that via default-src 'self', so there is
+// nothing to override — which is the point of asserting it stays empty.)
func TestServedCSPIsRastrillosDefault(t *testing.T)
// And the one screen that carries script must still work without it: