Files
cgalo5758 9ff516ba95 Introduce the forms library and migrate all forms
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.
2026-09-05 03:16:45 -05:00

7.8 KiB

operator-setup-checklist Specification

Purpose

Give a fresh deployment's first operator a visible, truthful path from nothing to a deliverable plan: a persistent checklist derived entirely from live system state, never from stored progress, so it can never disagree with the surfaces it links.

Requirements

Requirement: Operator surface provides a state-derived setup checklist

The operator panel SHALL provide a setup checklist at /operator/setup that walks a fresh deployment through the minimum path from nothing to a deliverable plan. The checklist SHALL cover, as discrete steps and in this order: configure the integrations the deployment delivers through; create an entitlement set; create a product that uses it (the product step is keyed on a published product, and its copy states that the operator panel publishes a product at creation; the panel's create path has no draft state and no separate publish control, so a standalone "publish" step could never be independently acted on); add an active price and sync it to Stripe; create a plan ladder and attach the product as a tier; choose an org-type default. Each step SHALL link directly to the surface where the operator completes it, and each incomplete step SHALL name what completing it unlocks (the downstream step it feeds).

The Entitlement sets step SHALL NOT be presented as a prerequisite the Products step waits on. Its copy SHALL name the second route to a set, "or create one with your first product", and link to the product create page, because that page's entitlement-set select opens on "New set named after this product" and creates the set with the product (product-management, design D14). The Products step SHALL be actionable while the Entitlement sets step is incomplete, and neither step's copy SHALL tell the operator to complete the other first.

Steps SHALL be equal: the checklist SHALL NOT class steps as required or conditional, SHALL NOT label any step "Required", and SHALL render completion in one tone per state ("Done" in the success tone, "Incomplete" in the neutral tone) for every step (maintainer, 2026-09-02: the two classes encoded one deployment's model and the two-tone badges they produced read as inconsistency). A step whose relevance depends on the deployment's model (Stripe pricing, the org-type default) SHALL say so in its copy rather than through a class. Copy SHALL follow the vocabulary rule that "plan" names a product's role on a ladder, never a kind of product: no step frames products that are not tiers as exceptions.

Every step's completion state SHALL be derived from live system state (existence queries against the same tables the linked surfaces manage). The integrations step derives from the provider-configuration leg product readiness uses: it is incomplete while any resource key referenced by an active entitlement set's rules belongs to a provider whose required configuration is unresolved, or while no integration is configured at all. The checklist SHALL NOT store its own progress flags, so its claims cannot disagree with reality: deleting the last entitlement set un-completes that step.

Scenario: Fresh instance shows every step incomplete

  • WHEN an operator views the setup checklist on a deployment with no configured integrations, entitlement sets, products, prices, ladders, or org-type defaults
  • THEN every step renders as incomplete, integrations first
  • AND each step links to the surface that completes it

Scenario: The entitlement-set step names the product route

  • WHEN an operator views the checklist with no entitlement set yet
  • THEN the Entitlement sets step reads "or create one with your first product" and links to the product create page
  • AND the Products step is actionable, with no copy telling the operator to create a set first

Scenario: Creating a product with its set completes both steps

  • WHEN an operator creates the deployment's first product from the Products step, leaving the entitlement-set select on "New set named after this product", and returns to the checklist
  • THEN both the Entitlement sets step and the Products step derive complete

Scenario: Completion is derived, not recorded

  • WHEN an operator creates an entitlement set through the normal Entitlement Sets surface and returns to the checklist
  • THEN the entitlement-set step renders complete without the operator having interacted with the checklist itself

Scenario: Completion reverses when the underlying state disappears

  • WHEN the only entitlement set is deleted after its step showed complete
  • THEN the step renders incomplete again

Scenario: The integrations step follows the readiness leg

  • WHEN an active entitlement set carries a rule on a resource key owned by a provider whose required keys are unresolved
  • THEN the integrations step renders incomplete and names that provider
  • WHEN every such provider is configured
  • THEN the step renders complete

Scenario: Every step renders alike

  • WHEN an operator views the checklist with some steps complete
  • THEN every complete step carries the same "Done" badge, every incomplete step the same "Incomplete" badge, and no step carries a "Required" label

Requirement: The checklist is persistent and revisitable, not a wizard

The checklist SHALL remain reachable for the lifetime of the deployment. It SHALL NOT gate or sequence access to any other operator surface, SHALL NOT force steps to be completed in order, and SHALL NOT require the operator to pass through it on any navigation path. It is a map, not a corridor.

Scenario: Steps can be completed out of order

  • WHEN an operator creates a plan ladder before any product exists
  • THEN the ladder step derives complete while earlier-listed steps remain incomplete
  • AND no checklist mechanism prevented or warned against the ordering

Scenario: Checklist survives setup

  • WHEN every step is complete and an operator navigates to the checklist surface directly
  • THEN the checklist renders with all steps complete rather than being removed or redirecting away

Requirement: The overview carries a dismissible setup banner

The operator overview SHALL render, above the lookup, the blue Bootstrap info alert reading "Getting started. Finish setting up {deployment name}." with a "Continue setup" link to /operator/setup and a close button, while the banner has not been dismissed and at least one step is incomplete (maintainer, 2026-09-02: the banner should feel welcoming rather than reading almost like an error message; it names no step count; maintainer, 2026-09-03, "I back the blue": the info alert over a plain card, same copy). Once every step derives complete the banner SHALL NOT render, dismissed or not. Dismissal SHALL be deployment-wide, not per browser or per operator: the close button posts to /partials/operator/setup/dismiss, the handler records the instance setting setup_banner_dismissed (the first key of core.instance_settings, with who and when), and the banner swaps out without a page reload. The checklist SHALL stay reachable after dismissal through the System section header's "Setup" action and the setup page's URL.

Scenario: The banner shows until dismissed

  • WHEN an operator views /operator on a deployment with incomplete steps and no dismissal recorded
  • THEN the banner renders above the lookup as the blue info alert with the "Continue setup" link and a close button, naming no step count

Scenario: Dismissal is deployment-wide

  • WHEN an operator closes the banner
  • THEN it disappears without a reload, and no operator sees it again on any browser while the setting stands

Scenario: A finished setup needs no banner

  • WHEN every step derives complete
  • THEN the banner does not render, whether or not it was dismissed