Skip to main content

Why Generalized Permissions

  • By Alan James

The Problem with Dedicated Relationship Tables​

  • One FK-constrained join table per relationship type (CompanyUser, TeamUser, CollectionTeam, ...)
  • Real DB integrity, but:
    • schema proliferation - every new relationship = new table/migration/API/service/tests
    • repeated APIs doing the same conceptual thing ("relate A to B with these scopes")
    • risk of authorization logic drifting between relationship implementations over time
  • Nothing stops a future contributor from bypassing a central service and querying/adding a raw table directly - the "one abstraction" is a convention, not a constraint

What the Generalized Grants Model Actually Does​

  • One permission_grant table: subject, resource, one scope per row, soft-deleted (real audit trail - see below)
  • Governed by a typed relationship model (which subject/resource pairs are legal, which scopes are valid) - not an untyped bag of IDs
  • GrantService is the only thing that ever touches the table - two narrow methods (canPerform, getAccessQuery) are the entire surface every other service gets
  • This is a hard line, not a soft one - there's no raw table left to reach for if someone wants to bypass it

Why This Matters for a Small Team That Doesn't Know How It'll Grow​

  • Yew is young - the actual shape of future relationships isn't known today
  • Committing to N dedicated tables optimizes for a stable domain model this project doesn't have yet
  • One centralized, validated path is a stronger constraint than N typed tables + good intentions - same "platform enforces it, not team discipline" principle as Postgres/cookies/hash-routing, applied to the schema itself

The Tradeoff (named honestly, not hidden)​

  • No database-enforced foreign keys on either side of a relationship
  • No automatic cascade deletes - has to be built by hand
  • The plan: every resource-owning service's delete path explicitly calls into GrantService to purge anything referencing it - six known, enumerable call sites, not an open-ended risk
  • More validation work moves into the application layer, concentrated in one service instead of duplicated across many

The Broader Pattern​

  • Same shape as Postgres over MongoDB, cookies over JWT, hash routing over History API: give up some flexibility/elegance in exchange for the platform enforcing correctness instead of relying on people remembering to do the right thing
  • One scope per grant row + soft delete also means every grant and revocation is independently auditable - a side effect that happens to set up V4's audit-log requirement for free

Conclusion​