Introduce a commercial license option alongside AGPL-3.0-only, require a
CLA for contributors, and document the terms in COMMERCIAL.md and
NOTICE. Add a script to stamp SPDX headers on Go files and apply it
across the tree.
Every form on both surfaces is now a declared FormSpec in
internal/forms, rendered through the shared form part and parsed
by its handler through the same declaration. Create and edit
share one field list, refusals answer 422 with values carried
back, and layout, buttons and errors come from one part.
Also adds the form registry with its invariant and route-mapping
tests, the raw-form, filler-copy and Go em-dash lint rules,
declared action triggers, and the capture-coverage cross-check.
The forms-library change is archived under
openspec/changes/archive/2026-09-05-forms-library.
Six review rounds on the September walk's 40 findings, executed as the
acceptance-fixes change (design D1 to D31) and archived as
openspec/changes/archive/2026-09-03-acceptance-fixes/ with its 20
deltas synced into openspec/specs.
Shell and conventions: the location trail on every page rooted at the
surface; click-opened help popovers; buttons by role with the pressed
rule retired and tertiary openers with a rotating plus; the code chip
and white card headers; Remove versus Delete on row actions.
Operator surface: three overview tiles, one Integrations card, the
getting-started banner as the first instance setting
(core.instance_settings, migration 00015); record creation on its own
page for products, entitlement sets, and plan ladders; Visibility as
one Public checkbox; the Stripe provider page; the plan ladder
validation page retired and ranks ascending; org-types default change
with dispositions, Discard, and the settle-cloning fix; the rebuilt
composite billing card; hints instead of placeholders; the person page's
identity-provider glyph on its field labels; non-UUID ids answer 404.
Found by review and fixed: a session now ends when its person no longer
exists (the foreign-key failure on a ladder reorder after a snapshot
rebuild); the CSRF cookie lives as long as the session and its toast
says the page is out of date; htmx's settle delay is 0 app-wide.
Verification: unit suites, browser walkthroughs, the screens baseline
(31 screens, accepted), and Lighthouse at 100 on both widths, recorded
in docs/operator-a11y-baseline.md. Three stale issue entries archived.
- Add shared ui_*.html parts (pageHeader, sectionHeader, statusBadge,
emptyState) parsed into every template set
- Add anatomy lint rules with a shrinking allowlist and screen-coverage
check
- Add make screens capture harness with contact sheets and baseline diff
- Compose member and FedWiki regions server-side so pages arrive
complete
- Rebuild Domains and Integrations on the parts as pilots
Replace the entity slugs on organizations, workspaces, resource pools,
and
plan ladders with nullable `key` columns and add keys to products,
prices,
and entitlement sets. Rename `providers.slug` to `provider` and add
partial
unique indexes for system and org role names.
Assign invoice numbers per billing account from a gapless transactional
counter; Stripe's number moves to the invoice mapping as an external
reference.
Seeds, fixtures, and the operator lookup address rows by key, and the
returning-login resync no longer blanks a display name when the IdP
sends
no `name` claim.
Governed operator lists (organizations, grants, people, billing×4) gain
server-side search, status filters, and 50-row pages with true totals
from count(*) OVER(); state is URL-addressable, out-of-range pages
clamp,
and no-match is distinct from true-empty.
People is the eighth flat sidebar entry: /operator/persons lists persons
newest-joined first (excluding the reserved system person), rows linking
to the existing detail.
Billing gains an operator invoice detail at
/operator/billing/invoices/{invoiceID} reusing the member projection;
open invoices past due present as Overdue (derived, filterable, stored
status untouched); all four views lead with the linked organization and
mute object IDs.
Grants filter over the derived Live/Superseded/Inactive state, the SQL
HAVING predicate pinned to the Go derivation by test. Embedded lists
(org composite ledger, Tier changes) adopt the shared controls under
namespaced params with sibling-state-preserving URLs and scoped htmx
swaps that hold the viewport.
Review corrections: blocked ladder Delete renders disabled with tooltip
and mutations fire toasts; collapse triggers paint their open state;
sections use outside headings; plan topology drops the orphan-product
check; domains policy collapses behind a disclosure.
- Restructure operator sidebar into a flat task list with indented
children; fold plan topology into plan ladders
- Expand member catalog non-plan section to all published non-tier
products; require recurring Stripe-mapped prices for purchase
- Add operator domains placements and terminal-claims ledger; redirect
/domains to the FedWiki Sites Domains anchor
- Apply canonical vocabulary and chrome/form conventions; migrate seeded
FedWiki Sites display name
- Add deployment-name branding to titles, mastheads, and OG tags
- Share one grant delivery-state query with lineage across grants
surfaces
- Show pool status/usage, org owners, and config readiness
- Make billing views projection-aware with recency and sync vocabulary
- Guard FedWiki creation without domains and render route-aware 404s