// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial // SPDX-FileCopyrightText: 2025-2026 Christian Galo package integration // ProviderKind discriminates providers in the registry. The operator // "Integrations" surface is exactly the KindProvisioning subset; a KindPayment // provider (Stripe) is registered but never appears there. type ProviderKind string const ( KindPayment ProviderKind = "payment" KindProvisioning ProviderKind = "provisioning" KindNotification ProviderKind = "notification" KindTax ProviderKind = "tax" ) // Operation is a lifecycle verb a provider may support. The mutating verbs // (OpCreate / OpSetStatus / OpDelete) are dispatched provider-side — the // transport is per-provider (Temporal for FedWiki, core.outbox for // Stripe), not mandated by the contract. The read class (OpList/OpDescribe) // lets the platform enumerate a provider's instances to reconcile the observed // status projection. OpSetStatus moves an instance between the provider's // declared States; OpDelete is terminal and distinct from the state machine. type Operation string const ( OpCreate Operation = "create" OpSetStatus Operation = "set_status" OpDelete Operation = "delete" OpList Operation = "list" OpDescribe Operation = "describe" ) // State is a lifecycle state a provider's instance can occupy. `active` is the // implicit baseline every provisioning provider supports; a provider that // declares OpSetStatus also declares the non-active states it supports, and // set_status moves an instance between them. These constants are the known // values, but the supported set is provider-declared (see Manifest.States). type State string const ( StateActive State = "active" StateReadonly State = "readonly" StateArchived State = "archived" ) // Manifest is the capability declaration a provider contributes at boot. It is // the single source of truth for a provider's kind, the lifecycle operations it // supports, and the resource keys it owns. The registry persists it into // core.providers / core.provider_operations and stamps // core.resource_keys.provider for owned keys. // // Operational/commercial state (status, plan-ladder bindings, enablement) is NOT // part of the manifest — that is DB-canonical and operator-editable, and a boot // re-registration must not clobber it. type Manifest struct { Key string // ^[a-z0-9]+$ (no underscores); see validateManifest Kind ProviderKind // one of the ProviderKind constants DisplayName string // human label for the registry / operator surface Operations []Operation // verbs this provider implements States []State // lifecycle states it supports; requires OpSetStatus, `active` implicit ResourceKeys []string // bare keys it owns; each MUST be "_…"-prefixed // OverLimit declares, per owned resource key, what the provider does with // usage above a lowered limit and the one sentence a rule-change preview // renders for it (Decision 147). A key with no declaration denies new use // and nothing else. The registry stamps the declaration together with the // key's provider, because the platform_keys_deny_new CHECK requires a // provider on any key that is not deny_new. OverLimit map[string]OverLimit // OperatorSurfacePath is the operator admin-surface URL for this provider, // rendered in the operator sidebar's Integration group. Empty for providers // with no operator surface (e.g. payment providers). OperatorSurfacePath string // Description is an optional one-sentence lead for the provider's own // page (its admin surface when it declares one, otherwise its settings // page) — operator-panel-navigation: "A provider page leads with the // integration's description". "" renders no lead override. Description string } // ProviderSource is implemented by each provider package (e.g. fedwiki, stripe) // and registered in boot order, parallel to db.MigrationSource. The returned // Manifest is validated and persisted by RegisterProviders at boot. type ProviderSource interface { ProviderManifest() Manifest } // OverLimit is a provider's declaration for one resource key: the behavior // usage above a lowered limit meets under a force_reduce rule, and the // sentence the console renders verbatim wherever it discloses it. type OverLimit struct { Behavior OverLimitBehavior Consequence string } // OverLimitBehavior is what a provider does with usage above a lowered limit // when the governing rule's reduction policy is force_reduce. type OverLimitBehavior string const ( // OverLimitDenyNew refuses new use above the limit and touches nothing // that exists; it is the default and the only value a platform key may // carry. OverLimitDenyNew OverLimitBehavior = "deny_new" // OverLimitPark sets the excess aside, retained and recoverable. OverLimitPark OverLimitBehavior = "park" // OverLimitReclaim takes the excess back. OverLimitReclaim OverLimitBehavior = "reclaim" )