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
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.
Add an explicit registry with capability hooks for migrations, routes,
workflows, config, and UI assets. Move FedWiki fully and Stripe's
separable
store, workflow, and webhook pieces under internal/integrations.
Drive startup wiring from declarations, including config validation,
secret
file pairs, CSRF exemptions, UI composition, and workflow startup. Move
integration DB roles and grants into their owning migration streams, and
route outbox writes through a shared enqueue helper.
Squash the pre-production migration history into fresh core, fedwiki,
and stripe baselines and reduce the canonical source list to those
three streams.
Update sqlc configs, generated queries, raw SQL, tests, and docs while
keeping provider tables schema-qualified.
BREAKING: existing local database volumes must be wiped because goose
version history restarts from the new baselines.
Fix HTMX expired-session handling, CSP-blocked form behaviors, reorder
recovery, billing currency display, plan/checkout guards, FedWiki quota
edge cases, and operator/member empty/error states.
Add entitlement uniqueness migrations, canonical migration source
wiring,
and regression coverage for the remediated flows. Update status docs
with
the audit triage and model inventory.
Expose `/operator/integrations` as a registry-driven landing for
provisioning providers, with provider links nested under the new sidebar
entry.
Update the OpenSpec archive and mark milestone 9b done.
Consume wiki-plugin-farmmanager v0.4.1's reversible site states to implement the
force_reduce read-only downgrade and a reversible-delete (archive) model.
Implements the OpenSpec change fedwiki-lifecycle-states.
- Contract: replace the discrete set_readonly/suspend verbs with a parameterized
set_status verb; providers declare their supported lifecycle states
(integration.provider_states). FedWiki declares active/readonly/archived.
- FedWiki state model: fedwiki.sites gains status, storage_bytes, last_modified_at,
force_reduced_at, archived_at; FarmManagerClient.SetSiteStatus (PATCH) +
storageBytes/lastModified; SetSiteStatusWorkflow saga keeps quota = active sites
(quota-gated reactivation).
- Sync now PROJECTS observed status instead of deleting non-active rows, with an
out-of-band usage-drift backstop.
- force_reduce: ReconcileFedWikiQuotaActivity parks excess sites read-only
(keeping the most-recently-modified active) and reactivates on re-upgrade, run
each sync tick. Member "Keep active" swap with a 30-day per-workspace cooldown.
- Archive: member delete routes to the archived state (recoverable) with restore,
delete-permanently, and a 30-day retention purge.
- Operator FedWiki Sites tab surfaces site status. Docs (contract guide,
FARMMANAGER, wishlist) updated; status/issues force_reduce marked resolved.
The operator sidebar's Integration group is registry-driven
(OperatorPageData.IntegrationProviders, loaded from integration.providers).
Every operator MPA page builds its page data via buildOperatorPageData, which
populates that slice — except the landing/overview surface, rendered by the
separate OperatorHandler.renderLanding, which built OperatorPageData inline and
never set IntegrationProviders (OperatorHandler had no DB access at all). So
FedWiki showed in the sidebar on every operator page except the overview.
Extract loadIntegrationProvidersNav as a shared free function, give
OperatorHandler a Database field (wired in server.go), and have renderLanding
load the same nav and set CurrentPath. Latent since the M9
provider-extension-contract change made the Integration nav registry-driven.
Register FedWiki and Stripe providers at boot, persist provider
operations, and stamp owned resource keys.
Rename the FedWiki entitlement key from `sites` to `fedwiki_sites`
and drive the operator integration nav from provisioning providers.
Add GetPersonPage handler and operator_person_detail.html
Retire the legacy /partials/operator/users list and remove the
People tab/pane from operator.html. Update legacyTabRedirects so
tab=people redirects to /operator
Add operator_billing.html wrapper and four GetBilling*Page handlers.
Extract loadBilling*/loadSubscriptions*/loadInvoices*/loadPaymentsData
helpers used by both legacy partial endpoints and the new pages.
Register new /operator/billing/* routes and add legacyTabRedirects
entry.
Add a no-op renderBody stub in fedwiki_partials to satisfy template
parse.
Register GET /operator/org-types, /operator/products,
/operator/entitlement-sets and /operator/plan-ladders
Extract load*PageData helpers and reuse them in GetXPage handlers.
Update operator template nav to use ActiveCapability and direct routes,
adjust legacyTabRedirects, and mark tasks in openspec
Register GET /operator/fedwiki-sites and add GetFedWikiSitesPage.
Reuse the existing operator_sites.html partial and set page
ActiveCapability/IAPosition. Update nav template link and
legacyTabRedirects, and mark the task done in the openspec tasks list.
Strip grant create/revoke UI from operator_grants.html; extract
loadGrantsListData to centralize grants hydration. Add GetGrantsPage
handler and register GET /operator/grants, update legacyTabRedirects,
trim renderGrantsPage, and update the tasks checklist.
Introduce a renderBody template func to dispatch dynamic body partials
from operator.html (real implementation in NewOperatorPartialsHandler).
Add GetOrganizationsPage and GetOrganizationDetailPage to render MPA
pages by setting BodyTemplate/BodyData and ActiveCapability on the
OperatorPageData. Refactor enrollment hydration into
loadOrgEnrollmentData,
update templates to use /operator/organizations links and target