registry: the account pages in the brand shell (BRAND slice 2, part 2) #295

Closed
opened 2026-10-10 00:22:46 +00:00 by orion · 6 comments
Collaborator

Goal

The registry's account pages (/account, sign-in, sign-up, claim, passkey, authenticator-app and step-up pages, rendered by tools/registry/src/account.trb) wear the brand's shell and brand/tokens.css, like the package page of #12, and BRAND.md slice 2 is marked done.

Source

  • BRAND.md section 11 ("packages.torb.dev: Shell") and section 13 slice 2; RELEASE.md section 7.1 (the account page) and 7.11.
  • Split from #12 so that each stays one PR: #12 builds the shell and the static package pages, this issue applies the shell to the pages the write service renders itself.

Design

  • pageOf in account.trb wraps its body in the shell function of #12 (same header with the packages label, top rule, footer, theme toggle); the forms, buttons and tables use the brand's classes (ink primary button; a red button only where BRAND.md section 8 allows it, which is none on these pages).
  • The pages' Content-Security-Policy is relaxed from default-src 'none' only by what the shell needs: style-src 'self', font-src 'self', img-src 'self'. Still no inline style, no inline script, no unsafe-inline; the two passkey pages keep their one script-src 'self' script; form-action and frame-ancestors stay as they are. The shell's theme toggle script is the external file of #12, so no page gains an inline script.
  • Pages stay Cache-Control: no-store, escaped, and CSRF-protected as before; only markup and classes change.

Acceptance criteria

  • Every page of account.trb is produced through the shell of #12; none writes its own <html> skeleton.
  • The policy of each page is the previous one plus exactly style-src 'self'; font-src 'self'; img-src 'self'; the tests that assert the policy are updated and a new one asserts there is still no unsafe-inline and no inline <script> or style= in any account page.
  • The existing account, sign-in, passkey, TOTP and step-up tests pass unchanged apart from the policy strings and markup they match.
  • tools/registry/README.md and RELEASE.md 7.1 describe the new policy; BRAND.md slice 2 is marked done (status paragraph and section 13).

Seed impact

None expected (registry write service and static assets; no syntax, native or driver flag).

Size and dependencies

One PR, one or two Conventional Commits. Depends on #12 (the shell function and its stylesheet). Deploying the registry is outside the loop.

## Goal The registry's account pages (`/account`, sign-in, sign-up, claim, passkey, authenticator-app and step-up pages, rendered by `tools/registry/src/account.trb`) wear the brand's shell and `brand/tokens.css`, like the package page of #12, and BRAND.md slice 2 is marked done. ## Source - BRAND.md section 11 ("packages.torb.dev: Shell") and section 13 slice 2; RELEASE.md section 7.1 (the account page) and 7.11. - Split from #12 so that each stays one PR: #12 builds the shell and the static package pages, this issue applies the shell to the pages the write service renders itself. ## Design - `pageOf` in `account.trb` wraps its body in the shell function of #12 (same header with the `packages` label, top rule, footer, theme toggle); the forms, buttons and tables use the brand's classes (ink primary button; a red button only where BRAND.md section 8 allows it, which is none on these pages). - The pages' Content-Security-Policy is relaxed from `default-src 'none'` only by what the shell needs: `style-src 'self'`, `font-src 'self'`, `img-src 'self'`. Still no inline style, no inline script, no `unsafe-inline`; the two passkey pages keep their one `script-src 'self'` script; `form-action` and `frame-ancestors` stay as they are. The shell's theme toggle script is the external file of #12, so no page gains an inline script. - Pages stay `Cache-Control: no-store`, escaped, and CSRF-protected as before; only markup and classes change. ## Acceptance criteria - [ ] Every page of `account.trb` is produced through the shell of #12; none writes its own `<html>` skeleton. - [ ] The policy of each page is the previous one plus exactly `style-src 'self'; font-src 'self'; img-src 'self'`; the tests that assert the policy are updated and a new one asserts there is still no `unsafe-inline` and no inline `<script>` or `style=` in any account page. - [ ] The existing account, sign-in, passkey, TOTP and step-up tests pass unchanged apart from the policy strings and markup they match. - [ ] `tools/registry/README.md` and RELEASE.md 7.1 describe the new policy; BRAND.md slice 2 is marked done (status paragraph and section 13). ## Seed impact None expected (registry write service and static assets; no syntax, native or driver flag). ## Size and dependencies One PR, one or two Conventional Commits. Depends on #12 (the shell function and its stylesheet). Deploying the registry is outside the loop.
Author
Collaborator

[loop:torbscript] claim refine by session:loop-torbscript-20261010 until 2026-10-10T12:44Z (#12 is merged, the dependency is gone)

[loop:torbscript] claim refine by session:loop-torbscript-20261010 until 2026-10-10T12:44Z (#12 is merged, the dependency is gone)
Author
Collaborator

[loop:torbscript] decided by the loop: the account pages also get script-src 'self'. Why: the shell of #12 (registryPageHtml in compiler/src/documentation/site-registry.trb) puts <script src="/assets/registry.js"> in every head (stored theme, theme toggle), and default-src 'none' would block it, so the toggle would stay hidden and the stored theme would not apply. The script is the same external file of the same origin (nginx serves /assets/ on packages.torb.dev, Traefik routes /account there too), so no inline script appears and the two passkey pages (which already carry script-src 'self') lose nothing. The acceptance criterion on the policy is amended below. Rejected: a shell parameter that leaves the script out on account pages (a second shell variant for a toggle, and the account pages would flash the wrong theme).

[loop:torbscript] decided by the loop: the account pages also get `script-src 'self'`. Why: the shell of #12 (`registryPageHtml` in `compiler/src/documentation/site-registry.trb`) puts `<script src="/assets/registry.js">` in every head (stored theme, theme toggle), and `default-src 'none'` would block it, so the toggle would stay hidden and the stored theme would not apply. The script is the same external file of the same origin (nginx serves `/assets/` on packages.torb.dev, Traefik routes `/account` there too), so no inline script appears and the two passkey pages (which already carry `script-src 'self'`) lose nothing. The acceptance criterion on the policy is amended below. Rejected: a shell parameter that leaves the script out on account pages (a second shell variant for a toggle, and the account pages would flash the wrong theme).
Author
Collaborator

[loop:torbscript] decided by the loop: the form styles go into assets/registry.css, in the same PR. Why: site-style.trb and registryStylesheet style the search field only; there are no classes for a labelled field, a text input, a form row or the list of identities/passkeys, so "the brand's classes" for the forms do not exist yet. They are added in site-registry.trb next to the package-page rules, from the tokens only (no new colour, no red, ink primary button = button button-primary, tables = the existing table/.table-wrap, notices = .callout), so the account pages need no inline style.

[loop:torbscript] decided by the loop: the form styles go into `assets/registry.css`, in the same PR. Why: `site-style.trb` and `registryStylesheet` style the search field only; there are no classes for a labelled field, a text input, a form row or the list of identities/passkeys, so "the brand's classes" for the forms do not exist yet. They are added in `site-registry.trb` next to the package-page rules, from the tokens only (no new colour, no red, ink primary button = `button button-primary`, tables = the existing `table`/`.table-wrap`, notices = `.callout`), so the account pages need no inline style.
Author
Collaborator

[loop:torbscript] refine: amended contract, ready for implementation.

Goal. Every page account.trb renders (account, sign-up, sign-in, claim, passkey registration and sign-in, authenticator app, step-up, refusal pages) goes through the registry shell of #12 and wears brand/tokens.css; BRAND.md slice 2 is done.

Design point. BRAND.md section 11 "packages.torb.dev" (Shell: same header with the packages label; ink primary button, never red) and section 13 slice 2; RELEASE.md 7.1 (account page) and 7.11 (hosting, CSP).

Acceptance criteria (replaces the list in the description where it differs):

  • pageOf in tools/registry/src/account.trb calls registryPageHtml (title and body only, no searchAction, as the package pages); no page of account.trb writes its own <html> skeleton, and no page has an inline <script> body, style= attribute or event handler.
  • contentSecurityPolicy becomes the previous value plus exactly script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' (default-src 'none', form-action, frame-ancestors, base-uri unchanged); ceremonyPolicy becomes the previous value plus style-src 'self'; font-src 'self'; img-src 'self' (its script-src 'self' is already there); policyOf (provider origins in form-action) still derives from the constant and keeps its test.
  • A new test asserts, for the rendered page of every route of account.trb that answers HTML, that the policy has no unsafe-inline/unsafe-eval, that every <script carries src="/ (none inline) and that the body has no style= and no on<event>= attribute.
  • The existing account, claim, sign-in, passkey, TOTP and step-up tests pass unchanged apart from policy strings and markup they match (most compare against the exported constant and need no edit); Cache-Control: no-store, escaping and CSRF checks are untouched.
  • assets/registry.css (from registryStylesheet) gains the rules the account pages need (labelled field, text input, form row, list of identities/passkeys/tokens, tokens table in .table-wrap), tokens only, with a test in compiler/tests/site-registry.test.trb that the stylesheet has them and no # literal outside what it has today.
  • tools/registry/README.md (the policy sentence at line 73) and RELEASE.md 7.1/7.11 describe the new policy and that the account pages use the shell; BRAND.md slice 2 reads done (section 13 item 2 and the status paragraph at the top, "the account pages are #295" removed); docs/tooling/torb-docs-site.md mentions the form rules; skills/ regenerated if a doc it is built from changed.

Seed impact. None: markup, CSS and a policy string in .trb source; no syntax change, no new native, no driver flag, no std name looked up by string; the two-commit rule does not apply.

Size. One PR, two Conventional Commits: feat(docs): the registry stylesheet's form rules (site-registry.trb + its test + torb-docs-site.md) and feat(registry): the account pages in the brand shell (account.trb, tests, README, RELEASE.md, BRAND.md, skills). Closes #295. Deploying the registry stays outside the loop.

next: ready

[loop:torbscript] refine: amended contract, ready for implementation. **Goal.** Every page `account.trb` renders (account, sign-up, sign-in, claim, passkey registration and sign-in, authenticator app, step-up, refusal pages) goes through the registry shell of #12 and wears `brand/tokens.css`; BRAND.md slice 2 is done. **Design point.** BRAND.md section 11 "packages.torb.dev" (Shell: same header with the `packages` label; ink primary button, never red) and section 13 slice 2; RELEASE.md 7.1 (account page) and 7.11 (hosting, CSP). **Acceptance criteria** (replaces the list in the description where it differs): - [ ] `pageOf` in `tools/registry/src/account.trb` calls `registryPageHtml` (title and body only, no `searchAction`, as the package pages); no page of `account.trb` writes its own `<html>` skeleton, and no page has an inline `<script>` body, `style=` attribute or event handler. - [ ] `contentSecurityPolicy` becomes the previous value plus exactly `script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'` (`default-src 'none'`, `form-action`, `frame-ancestors`, `base-uri` unchanged); `ceremonyPolicy` becomes the previous value plus `style-src 'self'; font-src 'self'; img-src 'self'` (its `script-src 'self'` is already there); `policyOf` (provider origins in `form-action`) still derives from the constant and keeps its test. - [ ] A new test asserts, for the rendered page of every route of `account.trb` that answers HTML, that the policy has no `unsafe-inline`/`unsafe-eval`, that every `<script` carries `src="/` (none inline) and that the body has no `style=` and no ` on<event>=` attribute. - [ ] The existing account, claim, sign-in, passkey, TOTP and step-up tests pass unchanged apart from policy strings and markup they match (most compare against the exported constant and need no edit); `Cache-Control: no-store`, escaping and CSRF checks are untouched. - [ ] `assets/registry.css` (from `registryStylesheet`) gains the rules the account pages need (labelled field, text input, form row, list of identities/passkeys/tokens, tokens table in `.table-wrap`), tokens only, with a test in `compiler/tests/site-registry.test.trb` that the stylesheet has them and no `#` literal outside what it has today. - [ ] `tools/registry/README.md` (the policy sentence at line 73) and RELEASE.md 7.1/7.11 describe the new policy and that the account pages use the shell; BRAND.md slice 2 reads done (section 13 item 2 and the status paragraph at the top, "the account pages are #295" removed); `docs/tooling/torb-docs-site.md` mentions the form rules; `skills/` regenerated if a doc it is built from changed. **Seed impact.** None: markup, CSS and a policy string in `.trb` source; no syntax change, no new native, no driver flag, no std name looked up by string; the two-commit rule does not apply. **Size.** One PR, two Conventional Commits: `feat(docs): the registry stylesheet's form rules` (site-registry.trb + its test + torb-docs-site.md) and `feat(registry): the account pages in the brand shell` (account.trb, tests, README, RELEASE.md, BRAND.md, skills). Closes #295. Deploying the registry stays outside the loop. next: ready
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T16:52Z

[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T16:52Z
Author
Collaborator

[loop:torbscript] implement: PR #307 (head c6d20d09, CI success, argus requested), est. tokens 120000, next: waiting (review by argus)

[loop:torbscript] implement: PR https://git.torb.dev/torbscript/language/pulls/307 (head c6d20d09, CI success, argus requested), est. tokens 120000, next: waiting (review by argus)
argus closed this issue 2026-10-10 13:31:04 +00:00
Sign in to join this conversation.
No labels
loop
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#295
No description provided.