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.
Move sub-surfaces into their sections: billing views get a pill row,
org types a header button. Replace inline IdP handoff copy with an SVG
icon and tooltip, add help icons to dense form rows, and delete the
registry-driven sidebar nav plumbing. Update specs and tests.
- 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
Implement the ux-first-run change: a state-derived setup checklist on
/operator/setup with a landing region that recedes once required steps
are done, and empty states that distinguish blocked from empty across
operator and member surfaces. Also add production deployment and
environment reference docs, plus a config-key completeness test.
- 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
Records the M10 10g first-contact walk: process doc and rubric, five
naive mission logs, three outside-model reads, three heuristic reviews,
and 21 synthesized findings with maintainer triage.
Enforce 10j's verified gaps (schema-hardening change):
- Migration 00010: partial unique indexes for one default pool and one
primary assignment per workspace, plus CHECKs pinning
pool/provider/subscription vocabularies and provider lifecycle
timestamps.
- Workspace creation shares a transactional provisioning function;
extension validates its target pool; last-tier deletion of a defaulted
ladder is guarded; signup completes plan-less on a broken ladder.
- Boot asserts integration slug parity and validates declared config
enums; Stripe invoice amounts are range-checked; domain cancellation
runs a final evidence probe; rule authoring is additive-only.
Add lifecycle_status = 'published' to the public-catalog queries
(plans and add-ons listings) and reject checkout before any Stripe
call unless the product behind the price clears the shared member
gate (published + active + public). The currently-enrolled ladder
rung stays renderable even if its product is later drafted or
retired, fetched directly so members keep seeing what they are on.
Introduce a single evaluateMemberGate definition shared by the
catalog paths and the operator readiness panel so the surfaces
cannot disagree about what is publishable for members.
Write the eight domain-model cards under `docs/models/`, mark M10 10i
Done, and update the design docs to v16. Also records Doc 44, which
ratifies Decisions 129-133 as amended, and the Doc-39 conformance
check that satisfied its gate.
Introduce `docs/models/` with the catalog index and its first card
(product-catalog), recording invariants, dimensions, and drift traps
per the Decision 141 documentation division. Add the model-cards
openspec change (proposal, design, spec, tasks) and sync the design
docs to v15: product kind taxonomy dissolved (Decisions 134–139),
Decisions 140–141 ratified, and product/pricing helpers updated. The
catalog is the single descriptive home for as-built models.
Configure the personal org-type default ladder and floor vacant pools so
the seeded dataset survives grant revocation. Let the modal mechanics
test
fall back to plan-ladder action triggers in full-suite order.
Put the fedwiki chain (init, render, farm, caddy) behind a fedwiki
compose profile symmetric with discourse's; the default composition is
neither, selected via COMPOSE_PROFILES in test/.env, so a default stack
no longer binds host 443.
Guard every script and walkthrough on service presence: shared
skipUnlessIntegrationEndpointReachable helper, seed-stack presence
checks (also repairing its unsourced .env and container-native render
invocation), generic root-owned testdata reclaim in teardown, discourse
coverage in verify-stack-isolation, and fedwiki's 8090 base in the port
probe.
Update stack docs and finalize status bookkeeping for all three
changes; archives the test-stack-integration-profiles change.
Register bool and duration ConfigSpec keys from the Default's type, move
fedwiki's four sync knobs and discourse's two into their integrations'
ConfigSpecs, and replace core's read of fedwiki-custom-domain-target
with a core domains-connect-target key resolved once and threaded
through server and worker config.
Generate init's optional-integration scaffold sections from each
registered ConfigSpec instead of the hand-maintained list, and reword
the Temporal boot warning generically.
Archives the integration-config-parity change; status bookkeeping and
the verify-skill doc follow with the test-stack commit.
Run Docker runtime stage as non-root user app (UID 65532).
Add styled full-page 404/500 error rendering for navigation requests
while preserving plain-text responses for HTMX partials.
Reuse recent unconsumed OIDC login state to avoid state mismatch on
parallel login hits, and merge resource_access in role extraction.
Re-level template headings, add autocomplete tokens, and resolve
catalog resource display names.
Self-label test-stack secrets and document CSRF secret rotation.
Replace domain claims with open invoices, show monthly recurring
revenue,
count team organizations, and add more informative trend captions.
Use standard bordered cards and add a README screenshot with reversible
sample-data tooling.
Registry.ClaimExternal now enforces the plan gate itself via an injected
domains.ExternalClaimGate (pre-lock, typed refusals), so every entry
point — and any future consumer — inherits it from the allocation API.
One constructor in internal/server builds the gate from the entitlements
querier and connect target; it is injected into the member-facing
registry constructions in server.go and fedwiki.go and drives affordance
rendering on both surfaces. The duplicated helpers and resource-key
constants in fedwiki web and member_domains are gone; fedwiki no longer
reads entitlement tables for this gate at all.
Archives the change with the domains-registry spec delta (enforcement
location is now requirement-level: registry-inherited, surfaces derive).
Closes the entitlement-gate placement debt in issues.md; files the
separately-discovered operator force-release dead-end affordance bug
that a placed claim exposed in the domains walkthrough.
Domains leaves the member nav everywhere; GET /domains 302s to the
dashboard and domains.html is deleted. Claims are managed where they are
used: the fedwiki sites card embeds the core claims partial, a
server-conditional dashboard notice carries pending verifications (the
durable re-entry now that the page is gone), and the member_domains
partials retarget to 'closest .domains-surface' so multiple hosts coexist
on one page. Adding an external domain starts only from the create form;
the fedwiki banner slims to verified-unplaced one-click creates, since
the notice and embedded section own the pending state.
Verified at the surface end-to-end (stack + Chrome): nav absence,
redirect, notice lifecycle through claim-cancel, and cross-host swap
isolation with two claim views open. Archives the change with spec
deltas synced (domains-registry point-of-use rewrite, fedwiki-sites and
member-dashboard additions); files the entitlement-gate placement debt
in issues.md; adds the repo verify skill.
Move member domain management affordances to point-of-use within site
flows and retire the standalone member `/domains` page. Document
integration interdependence exploration.
Documents the merged 10f operator overview (56a743f, 4cec386) as a
spec-driven change: delta merged into operator-panel-navigation (at-a-glance
region with per-source em-dash degradation and provisions-backed delivering
count, registry-driven system rail with dead-letter-only alarm, brand-neutral
shell, no-skip heading outline). Milestones: 10f code-shipped; 10a screenshot
deferred pending the overview polish follow-up.
Include profiled services during teardown and recover stale Compose
projects
when the generated environment file is missing.
Record claim lifecycle safeguards and mark custom domain code complete
with
only the production adoption cutover remaining.
Sweep stranded pending claims at boot and on a Temporal schedule while
preserving evidence-based abandonment semantics.
Apply occupancy and name-policy checks to carves by operator-root owners
without affecting direct operator placements.
Domain names become an allocatable resource with one authority. A new
core module (schema `domains`, own migration stream between core and the
integrations) owns claims — a DNS node plus its whole subtree, mutually
disjoint: operator shared-domain roots, member claims carved from them,
and bring-your-own names proven by TXT verification — and placements,
which bind a name inside a claim to a provider slug and resource ref.
Verification moves to the claim and decouples from creation. A member
proves control of a domain once; afterwards every name inside it places
instantly, wildcard-CNAME friendly, with no further DNS work. The claim
workflow activates the claim and stops — it no longer creates a site —
so the sites list offers a one-click create once a domain verifies.
/domains/ask answers from placements and is registered by core rather
than the FedWiki adapter; its HTTP contract is unchanged. A configured
`domains-ask-fallback-url` forwards names the registry does not know to
a legacy answerer, the strangler seam wiki.cafe's migration needs; a
name the registry knows but has archived is refused locally.
FedWiki's create saga reserves the name before the farm call, carrying a
workflow-minted site id so retries are idempotent, and compensates on
failure. Sync places only names it owns, never stealing a member's;
lifecycle transitions and the retention purge maintain servability. An
unconditional boot pass seeds operator roots, releases orphaned
placements, and adopts pre-existing sites — grandfathering member-owned
external domains shortest-name-first, and skipping name policy, so a
live single-letter site cannot lose its certificate.
Members manage domains at /domains: claims with verification status, DNS
records including an optional wildcard row, check-now, cancel, release.
Name policy (reserved, blocked, premium, plus a single-letter guard) is
operator data; refusals collapse to a plain "unavailable" so the console
never becomes an oracle for who holds what.
BREAKING (pre-release): `fedwiki.custom_domain_verifications` and
`sites.is_custom_domain` are dropped, the flag now derived from the
placement's claim kind; resource key `fedwiki_custom_domains` migrates
to the platform-owned `external_domain_claims`; running
verify-custom-domain workflows must be terminated before deploy.
Each poll now probes both required DNS records (TXT challenge + connect)
and records per-record state with observed values, so the pending view
shows found/missing/mismatch diagnostics per record with copy-on-click.
Check now signals the workflow to probe immediately and reset backoff;
Cancel frees the domain instantly via a new canceled status. The pending
banner reopens the instructions view. Hardening from adversarial review:
poll timer clamped to the deadline with a final probe before expiry,
ContinueAsNew on suggestion, per-workspace pending cap, clipboard
failure feedback. Archives OpenSpec change custom-domain-verification-ux;
records the 10d domain exploration and wiki.cafe census in status/.
Resume only app-paused schedules so operator pauses survive restarts.
Apply dormancy handling to Discourse and FedWiki.
Remove the unused pool-scoped grant route, hide internal transition
errors, and update specs and tests to use the canonical grant endpoint.
Render grant extension controls only for active grant-backed provisions.
Scan for valid walkthrough subjects and skip when Discourse is
unreachable.
Add a fresh-stack target and document the supported e2e workflow.
Report malformed sequences on the validation page and topology health
strip. Normalize fulfillment and Stripe webhook fixtures to preserve
contiguous, zero-based ranks.
List every provider kind with direct settings and admin links, move
FedWiki
under the integrations route, and add in-shell operator 404s.
Report sync health from Temporal schedule executions and clear one-shot
settings feedback parameters after display.
Persist non-secret ConfigSpec overrides in core and apply them at boot
ahead of environment values and defaults. Validate typed and enum
values,
show pending restart state, and remove Stripe's unused provider config
table.
Re-resolve members absent after batch adds by forum user ID. Update
renamed
usernames and quarantine deleted users so they cannot block healthy
group
delivery. Align the fake with Discourse's partial-batch semantics.
Run group sync every minute with immediate triggering, and disable
first-post
typing heuristics that silence test users. Document how stale usernames
can
poison batch group convergence.
Classify resource keys as boolean or numeric, adapt the operator form to
the selected key, and derive rule types server-side to prevent
wrong-shape rules.
Render generic HTMX card shells from integration declarations. Move the
FedWiki UI into its partial, add Discourse forum status, and label
member
entitlements with provider attribution.
Stripe's webhook deduplication used ON CONFLICT on a partitioned table
where the unique key included received_at, which only collapsed
same-instant duplicates. Switch to WHERE NOT EXISTS to deduplicate
across time.
FedWiki's operator page failed to render because html/template's
escape analysis requires all referenced templates in the set, even on
untaken branches. Include partials/operator_lookup_result.html in the
parsed template set.
Move resolved issues to archive.
Deliver forum posting entitlements through managed group membership with
identity linkage, periodic reconciliation, webhook handling, and an
operator mapping surface.
Include fake and live test environments, setup documentation,
migrations,
and end-to-end coverage.
Persist pool-scoped grants using OR semantics across active provisions,
retaining lapsed rows for transition visibility. Add consumer queries,
DB-backed coverage, and plans for the dependent Discourse integration.
Preview affected orgs by position source and require keep or migrate for
default-sourced positions. Commit deletion, renumbering, and holder
reconciliation atomically while preserving other-source delivery.
Classify rank-zero changes for default ladders and require operators to
grandfather or migrate affected organizations before applying ranks.
Fix operator attribution during tier induction backfills and make the
grant
extension walkthrough's optional-form check panic-safe.
Only create schedules after Temporal NotFound and update after
concurrent
creation. Resolve the system workspace on every workflow run so
persisted
schedule arguments cannot retain stale IDs after database resets.
Replace product-kind branching and direct position writes with enclosed
database functions driven by structural product shape.
Migrate grant and provision data, unify operator issuance, update
subscription and expiry flows, and add migration and integration proofs.
Clarify provider vs integration terminology and document the in-tree
distribution model. Refresh M9 status, issue tracking, and lint/doc
links to
use the new language.