98 lines
6.2 KiB
Go
98 lines
6.2 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
package server
|
|
|
|
import "git.coopcloud.tech/wiki-cafe/member-console/internal/forms"
|
|
|
|
// The console's out-of-form mutation triggers (design D7; spec
|
|
// form-library "The registry holds every form and is checked"). Not every
|
|
// mutation is a form: a row's Revoke button, a panel's Sync control, a
|
|
// sortable table's drop and a preview a select fires on change are all
|
|
// single-intent controls with nothing to fill in, and a form around them
|
|
// would be a form with no fields.
|
|
//
|
|
// They are declared here for the same reason forms are declared: so the
|
|
// route test can walk the router and find, for every mutation route,
|
|
// either a registered form's path or one of these. A handler that grows a
|
|
// route nothing renders and no declaration names fails that test, which is
|
|
// the route-level template-versus-handler check no markup lint can do
|
|
// (findings FA-6, FA-7, FA-9).
|
|
//
|
|
// The list is seeded from the 2026-09 forms audit's two "Triggers outside
|
|
// forms" inventories, verified against the routes internal/server
|
|
// registers. Triggers on integration-owned routes are declared by the
|
|
// integration that registers them.
|
|
func init() {
|
|
for _, t := range []forms.ActionTrigger{
|
|
// Shell: the account menu's only session control. A POST so a page
|
|
// on another origin cannot end a person's session by sending the
|
|
// browser to /logout; the handler answers htmx with HX-Redirect to
|
|
// the provider's end-session endpoint.
|
|
{Label: "Sign out", Method: "POST", Path: "/logout"},
|
|
|
|
// Operator: the overview's setup banner.
|
|
{Label: "Dismiss the getting-started banner", Method: "POST", Path: "/partials/operator/setup/dismiss"},
|
|
|
|
// Operator: the organization composite and the domains surface.
|
|
{Label: "Revoke", Method: "POST", Path: "/partials/operator/grants/{grantID}/revoke-and-transition", Modal: true},
|
|
{Label: "Force-release", Method: "POST", Path: "/partials/operator/domains/{claimID}/force-release", Modal: true},
|
|
|
|
// Operator: integrations. Clear is the settings row's own removal of
|
|
// a stored override, and carries no modal: the same override can be
|
|
// set again from the same row (design D21 round 5).
|
|
{Label: "Delete override", Method: "DELETE", Path: "/operator/integrations/config-orphans/{key}", Modal: true},
|
|
{Label: "Clear", Method: "DELETE", Path: "/operator/integrations/{integrationKey}/settings/{key}",
|
|
Note: "fired from an overridden row's Source cell on the integration settings page"},
|
|
|
|
// Operator: the product's prices and its Stripe sync.
|
|
{Label: "Sync to Stripe", Method: "POST", Path: "/partials/operator/products/{productID}/sync-stripe",
|
|
Note: "fired from the price row's Sync, the readiness panel's Sync to Stripe (labelled Create in live or Create in test when the recorded mapping is one the key cannot reach), and its Retry"},
|
|
{Label: "Check now", Method: "POST", Path: "/partials/operator/integrations/stripe/environment-check",
|
|
Note: "the Stripe provider page's Environment check section; starts the read-back boot starts, under the same workflow id"},
|
|
{Label: "Make default", Method: "POST", Path: "/partials/operator/products/{productID}/prices/{priceID}/make-default"},
|
|
{Label: "Deactivate price", Method: "POST", Path: "/partials/operator/products/{productID}/prices/{priceID}/deactivate", Modal: true},
|
|
|
|
// Operator: entitlement set rules. The batch form's commit posts to
|
|
// its own path (FormSpec.CommitAction), which the registry indexes
|
|
// by the form's Path alone, so the commit is declared here beside
|
|
// the triggers rather than left unaccounted for.
|
|
{Label: "Apply changes", Method: "POST", Path: "/partials/operator/entitlement-sets/{setID}/rules/apply",
|
|
Note: "the rules form's commit (operator.entitlement-set.rules, CommitAction); applies the staged batch"},
|
|
{Label: "Retry", Method: "POST", Path: "/partials/operator/entitlement-sets/{setID}/recompute/retry",
|
|
Note: "fired beside the Rules section's failure line; requeues this set's failed obligations and redispatches the drain"},
|
|
|
|
// Operator: plan ladders and their tiers. The two reorder drops and
|
|
// the removal preview are the sortable table and a button, not
|
|
// forms; the preview they produce is the form (spec
|
|
// plan-ladder-management).
|
|
{Label: "Reorder ladders", Method: "POST", Path: "/partials/operator/plan-ladders/reorder",
|
|
Note: "the sortable header row; the drop commits immediately"},
|
|
{Label: "Reorder tiers", Method: "POST", Path: "/partials/operator/plan-ladders/{ladderID}/tiers/reorder/preview",
|
|
Note: "the sortable tbody; the drop opens the preview, which is the guard"},
|
|
{Label: "Preview removal", Method: "POST", Path: "/partials/operator/plan-ladders/{ladderID}/tiers/{productID}/remove/preview"},
|
|
{Label: "Remove tier", Method: "DELETE", Path: "/partials/operator/plan-ladders/{ladderID}/tiers/{productID}", Modal: true},
|
|
{Label: "Delete ladder", Method: "DELETE", Path: "/partials/operator/plan-ladders/{ladderID}", Modal: true},
|
|
|
|
// Operator: the org-type default's live preview, fired by the
|
|
// select and the two disposition radios on change. It reads; the
|
|
// commit is the form's own route.
|
|
{Label: "Preview the default change", Method: "POST", Path: "/partials/operator/org-types/{orgType}/default-change/preview",
|
|
Note: "fired on change from inside the org-type form; renders the preview and writes nothing"},
|
|
|
|
// Member: plans, add-ons and checkout.
|
|
{Label: "Confirm switch", Method: "POST", Path: "/partials/member/plans/switch"},
|
|
{Label: "Cancel plan", Method: "POST", Path: "/partials/member/plans/cancel", Modal: true},
|
|
{Label: "Checkout", Method: "POST", Path: "/billing/checkout",
|
|
Note: "fired from a plan's move control and from an add-on's Add"},
|
|
|
|
// Member: workspaces and domain claims.
|
|
{Label: "Switch workspace", Method: "POST", Path: "/partials/workspaces/{workspaceID}/switch"},
|
|
{Label: "Release", Method: "POST", Path: "/partials/domains/claims/{claimID}/release", Modal: true},
|
|
{Label: "Cancel verification", Method: "POST", Path: "/partials/domains/claims/{claimID}/cancel", Modal: true},
|
|
{Label: "Check now", Method: "POST", Path: "/partials/domains/claims/{claimID}/check"},
|
|
} {
|
|
forms.RegisterTrigger(t)
|
|
}
|
|
}
|