Summary
Authentication chooses identity; authorization chooses visibility and mutation rights.
This ADR defines the lean authorization baseline needed before implementing shared user-state features.
Context
The recipe-site roadmap is not just "users can log in." It includes:
- public recipe content
- private user-owned state
- shared household state
- eventual friend-sharing features
Those features need a clear answer to:
- who can see a record
- who can change it
- which sharing boundary is first-class
Without an authorization model, authentication only tells us who a user is, not what they are allowed to do.
Decision
Adopt the following authorization baseline:
- Public content is explicit scope. Authorization must model public readability as a first class visibility state, not only private/shared resources.
- Private by default for user-owned mutable state. User-created state is private unless explicitly shared.
- Household is the first real sharing boundary. For MVP, the only multi-user scope that needs to exist is the household.
- Friend-level sharing is deferred. It is a real roadmap item, but it should not complicate the first authorization model.
- Keep roles small. For MVP, support only:
- Owner: can read, edit, delete, and manage sharing for their own resources
- Household member: can access only resources explicitly shared with the household
- Membership changes are privileged actions. Invites, removals, and ownership-sensitive changes must always be checked server-side.
- Never trust client-side visibility logic alone. The browser may hide controls, but the runtime is the enforcement point.
ADR 032 accepts Better Auth. Its organization/household primitive should be treated as a membership building block, not as a complete authorization system by itself.
MVP Policy Matrix
| Resource / action | Public visitor | Owner | Household member |
|---|---|---|---|
| Read public recipe | Yes | Yes | Yes |
| Read private recipe or user state | No | Yes | No |
| Read household-shared recipe / state | No | Yes | Yes |
| Create recipe draft | No | Yes | Yes |
| Edit own recipe draft | No | Yes | No |
| Edit another user's shared recipe | No | No | No |
| Delete own resource | No | Yes | No |
| Manage household membership | No | Yes | No |
The key intentional constraint is that household sharing grants read access first. Collaborative editing, shared ownership, and household-admin roles are deferred until real use shows they are needed. In this matrix, Owner means the resource owner except for household membership actions, where it means the household owner.
The practical MVP scope becomes:
| Capability | MVP? | Notes |
|---|---|---|
| Public recipe visibility | Yes | Public recipe content remains readable without login. |
| Private user-owned state | Yes | Core per-user state remains private unless explicitly shared. |
| Household membership | Yes | First shared boundary. |
| Share to household | Yes | Explicit, server-checked sharing. |
| Separate editor/admin roles | Deferred | Only needed if recipe authoring/publishing expands beyond today. |
| Friend-to-friend sharing | Deferred | Adds a second social graph too early. |
| Fine-grained RBAC / ABAC matrices | No | Overkill until real collaboration pain appears. |
| Public API scopes | Deferred | Only relevant once machine-facing APIs exist. |
Consequences
Positive
- The product gets a visibility model for public, private, and shared content without inventing enterprise-style RBAC.
- Authorization stays aligned with the actual roadmap: public recipes, self state, household sharing, friends later.
- The runtime and database work have a concrete policy model to implement.
Negative
- Household sharing still requires careful modeling of invitations, acceptance, and revocation.
- Some future features may need a richer policy model than owner/member.
When To Revisit
Revisit when any of the following become true:
- recipe publishing or editing needs privileged non-owner roles
- friend-to-friend sharing becomes a near-term feature
- multiple household roles become necessary in practice
- API keys, agents, or third-party integrations need non-human authorization scopes