Replace the entity slugs on organizations, workspaces, resource pools, and plan ladders with nullable `key` columns and add keys to products, prices, and entitlement sets. Rename `providers.slug` to `provider` and add partial unique indexes for system and org role names. Assign invoice numbers per billing account from a gapless transactional counter; Stripe's number moves to the invoice mapping as an external reference. Seeds, fixtures, and the operator lookup address rows by key, and the returning-login resync no longer blanks a display name when the IdP sends no `name` claim.
30 lines
1.2 KiB
Go
30 lines
1.2 KiB
Go
package integration
|
|
|
|
import "fmt"
|
|
|
|
// AssertKeyMatch enforces design D7 (schema-hardening): every integration
|
|
// declares its key twice — once from its own Key() method, once in the
|
|
// Key field of the manifest its Provider() returns — and nothing but this
|
|
// check enforces the two agree. A mismatch previously registered the
|
|
// provider under one key while mounting its UI and settings under the
|
|
// other, silently splitting the operator Integrations page into a
|
|
// half-row (registry data, no settings) and a phantom row (settings, no
|
|
// registry data).
|
|
//
|
|
// codeKey is the integration's Key() value; manifest is the Manifest
|
|
// returned by that same integration's Provider().ProviderManifest(). Called
|
|
// from cmd/start.go's registry loop, before provider registration, so a
|
|
// mismatch fails boot instead of surfacing later as a UI defect.
|
|
func AssertKeyMatch(codeKey string, manifest Manifest) error {
|
|
if codeKey == manifest.Key {
|
|
return nil
|
|
}
|
|
name := manifest.DisplayName
|
|
if name == "" {
|
|
name = codeKey
|
|
}
|
|
return fmt.Errorf(
|
|
"integration %q: Key() returns %q but its provider manifest declares key %q; the two must match",
|
|
name, codeKey, manifest.Key)
|
|
}
|