d5885d1d97
New scoped API-key role granting read + products:write + policies:write + licenses:write — the least-privilege credential for end-to-end catalog setup and license issuance (create product, define policies/tiers, issue licenses against them) without holding the master key. The catalog write scopes already existed and were enforced on the endpoints; only the role->scope expansion was missing. So this is a new Role variant, not a scope-model change. grants() matches scope strings explicitly (never by :write suffix) so the role can't widen into settings / payment / merchant-profile / webhook writes, and every master-only operation stays behind require_admin and so is structurally unreachable. Existing tier caps still bound it (Creator: 5 products / 5 policies per product). Migration 0023 rebuilds scoped_api_keys to widen the role CHECK (SQLite can't alter a CHECK in place); the table has no FKs, so it's a plain copy/drop/rename. Test covers the full onboard chain under the key's own credential plus denial of master-only gates and support-only writes.