One rule keeps a multi-tenant app safe: every piece of customer data belongs to an **Account**, and
every query has to go through it. Break that rule once and one customer can see another customer's
data. One Shot ships this boundary from day one, even though v1 has exactly one user per account,
because modeling the boundary upfront is what lets teams and shared workspaces ship later without
retrofitting every table and query in the app.

## The rule, in three parts

- **Every model you add gets an `account_id`.** `t.references :account, null: false, foreign_key: true`
  in the migration, `belongs_to :account` in the model. No exceptions for "just this one table."
- **Every query is scoped to the current account.** Write `Current.account.things`, never
  `Thing.all`. `Current.account` is the acting workspace, set from the session cookie the moment a
  request authenticates.
- **Every controller authorizes with Pundit**, and Pundit's default `Scope` filters any relation
  with an `account_id` column down to the acting user's account. See
  [Authorization](/docs/core-concepts/authorization) for how the two layers work together.

`Current.user` and `Current.account` are the two values everything else is built on. Billing
attaches to the **Account** (`account.subscription`), not the `User`, which is what makes a shared
team subscription a natural later addition instead of a rewrite.

## Why one account per user, for now

In v1, signing in for the first time *is* signing up: `User.upsert_by_email!` is the single
chokepoint both the magic-code flow and the OAuth flows route through, and it creates the `User`
and its `Account` together, in one transaction. There's no separate "create a workspace" step, and
no invite flow, because there's nothing yet to invite someone into beyond their own account.

This is a deliberate, cheap-now choice, not a limitation you'll fight later. Every table, every
query, and every policy already scopes to `Current.account`, not to `Current.user`. Adding
multi-user teams later is additive, not a data-model change.

## Extending to teams later

When you're ready for more than one user per workspace, the path is:

1. Add a join model with a role (`Membership`, joining `account`, `user`, and a `role` column), and
   let a `User` belong to many `Account`s through it.
2. Add `owner_id` to `Account` and promote the existing implicit owner (today's sole user) to that
   role explicitly.
3. Add an account switcher in the UI that sets `Current.account` to whichever workspace the signed-in
   user picked.
4. Build the invite flow. Because every existing table and policy already scopes to
   `Current.account`, none of that code has to change; you're adding a new way to select which
   account is current, not rewriting how data is read.

## Next

See how that scoping is enforced at the controller layer:
[Authorization](/docs/core-concepts/authorization).
