# ADR 034: Authorization Model

- HTML version: https://robbiepalmer.me/projects/recipe-site/adrs/034-authorization-model
- Project: Recipe Site (https://robbiepalmer.me/projects/recipe-site.md)
- Status: Accepted
- Date: 2026-05-27

# 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:

1. **Public content is explicit scope.** Authorization must model public readability as a first
   class visibility state, not only private/shared resources.
2. **Private by default for user-owned mutable state.** User-created state is private unless
   explicitly shared.
3. **Household is the first real sharing boundary.** For MVP, the only multi-user scope that needs
   to exist is the household.
4. **Friend-level sharing is deferred.** It is a real roadmap item, but it should not complicate
   the first authorization model.
5. **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
6. **Membership changes are privileged actions.** Invites, removals, and ownership-sensitive
   changes must always be checked server-side.
7. **Never trust client-side visibility logic alone.** The browser may hide controls, but the
   runtime is the enforcement point.

[ADR 032](/projects/recipe-site/adrs/032-better-auth) 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

---

Markdown index of this site: https://robbiepalmer.me/llms.txt
