Skip to main content

Context

Permissions were a flat list, and nothing checked that an action’s permission made sense for what the action does. The owner’s intent-map item P2 and the IAM answer A10 (mem L627) set a curated catalogue per module, with labels and risk, and policy providers that decide per request. The owner confirmed the key form on 2026-10-20 (mem L930): a permission key is <module>.<resource>.<action>, and each module’s permissions are one definePermissions() value.

Decision

  1. Each module declares its permissions as one definePermissions() value. That value is the module’s catalogue. It replaces the @Permissions class of P2, because the owner’s define* rule makes definePermissions() the value form (0145).
  2. Keys are <module>.<resource>.<action>, for example billing.invoice.refund, as A10 sets. The module key (0131) is the first segment. Each catalogue entry carries a label, a description, a risk and a verb (A10).
  3. The catalogue is curated per module. Gen warns, and does not fail, when an action reuses a permission whose verb differs from the action’s verb (mem L401).
  4. A @Policy provider method returns allow, deny or abstain. Any deny wins.
  5. Wildcard permissions are allowed only in system roles (A10).
  6. A rename of a permission goes through deprecation (0131).

Consequences

  • Permission review becomes a catalogue review, per module.
  • A verb mismatch is a warning, so an existing action is not broken on the day the check lands.
  • A key names its module, so the registry can check uniqueness by prefix.

Enforcement

planned — gen emits the catalogue from each module’s definePermissions() value and warns on a verb mismatch. Wildcard use outside system roles is planned as a gen error. The uniqueness check on keys is planned.

Alternatives

  • resource:verb keys: not chosen; the owner confirmed <module>.<resource>.<action>.
  • A @Permissions class: replaced by the definePermissions() value (decision 1).

Supersedes and sources

Supersedes: none. Sources: owner intent-map item P2 (accepted; mem L401), IAM answer A10 (mem L627), the owner’s confirmed naming of 2026-10-20 (mem L930: billing.invoice.refund, one definePermissions() per module), and the define rule (mem L546).