diff --git a/docs/architecture/0002-user-groups-and-bounded-contexts.md b/docs/architecture/0002-user-groups-and-bounded-contexts.md
new file mode 100644
index 0000000..7f93bae
--- /dev/null
+++ b/docs/architecture/0002-user-groups-and-bounded-contexts.md
@@ -0,0 +1,135 @@
+# ADR 0002 — User groups as actors, not bounded contexts
+
+Status: Proposed · Date: 2026-07-01
+
+## Problem
+
+Today the app knows exactly one actor. `auth/domain/session.ts` is a flat
+`Session { bsn, naam }`, authentication is a faked DigiD flow, and the backend has no
+role model at all (only an `X-Admin: true` header seam in `Program.cs` and a stringly-typed
+`Actor` on audit entries). This whole repo *is* the **Zorgverlener** self-service portal (SSP).
+
+We now need a second user group — **Behandelaar** (backoffice: assessing and deciding on
+applications) — and want room for others later (admin, auditor, institution rep). The question
+is a modelling one, not a coding one:
+
+> How do user groups map onto our DDD structure? Is "Zorgverlener" a bounded context? Is
+> "Behandelaar" a folder next to `registratie`/`herregistratie`? Where does "who may do what" live?
+
+Getting this wrong is expensive: split the code by role and every feature smears across
+"folders per persona"; lump everyone into one `users` context and it becomes a god-context.
+
+Confirmed constraints (with the product owner):
+
+- The backoffice is a **separate frontend application**, own audience, own deployment.
+- The groups **authenticate differently**: Zorgverlener via DigiD/BSN; Behandelaar via employee SSO.
+- Both act on the **same underlying aggregate** — the aanvraag/registration — but see different views.
+
+## Options considered
+
+| Option | Ubiquitous language respected? | Coupling | Verdict |
+|---|---|---|---|
+| 1. Split contexts **by role** (`zorgverlener/`, `behandelaar/` folders) | No — role ≠ capability; features smear across personas | High | Reject |
+| 2. One catch-all **`users`/`identity`** context owning everything about people | No — becomes a god-context; mixes identity, authz, and features | High | Reject |
+| 3. **Actors are personas; contexts are capabilities; identity is typed** | Yes | Low | **Adopt** |
+
+## Decision
+
+**A user group is an _actor_, not a bounded context.** Bounded contexts are drawn by
+**ubiquitous language + capability**, never by who logs in. Concretely:
+
+### 1. Two capability contexts, two apps, one shared backend domain
+
+The same real-world thing is described in two different languages:
+
+- **Zelfbediening (SSP)** — the Zorgverlener: *"ik vraag herregistratie aan"* — eligibility, fill in
+ my data, upload documents, submit. **This repo.**
+- **Behandeling (backoffice)** — the Behandelaar: *"ik beoordeel de aanvraag"* — werkvoorraad,
+ beoordeling, besluit, meer-info-opvragen, SLA, audit. **A sibling application**, not a folder here.
+
+Diverging verbs over the same noun is the textbook signal for **two bounded contexts**.
+
+### 2. The aggregate is owned by the backend; the contexts integrate through it
+
+The aanvraag/registration is the **system of record in the backend domain**. Neither frontend owns
+it. They integrate *through the backend* using the **BFF-lite decision DTOs of ADR-0001** — the same
+aggregate projected into two screen-shaped views. The **aanvraag status lifecycle** is the *published
+contract* between the two contexts:
+
+```
+Ingediend → In behandeling → (Meer info gevraagd ⇄) → Goedgekeurd / Afgewezen
+```
+
+The Behandeling context **advances** this lifecycle; the SSP **reads** it. Today the SSP already holds
+the seed of it — `pendingHerregistratie` in `big-profile.store.ts:53` is the first, coarsest read of
+that status ("in behandeling"). As the backoffice appears, that single boolean grows into a real
+status the backend publishes.
+
+```mermaid
+graph TD
+ subgraph FE["Frontend bounded contexts (separate apps)"]
+ SSP["Zelfbediening (SSP)
Zorgverlener · DigiD/BSN
this repo"]
+ BO["Behandeling (backoffice)
Behandelaar · employee SSO
sibling app"]
+ end
+ BE["Backend domain
aanvraag aggregate (system of record)
status lifecycle · authorization"]
+ SSP -- "reads aanvraag status
(decision DTOs, ADR-0001)" --> BE
+ BO -- "advances aanvraag status
(decision DTOs, ADR-0001)" --> BE
+ classDef c fill:#e5f1fb,stroke:#007bc7,color:#00567d;
+ classDef d fill:#fff4e5,stroke:#e8830c,color:#8a4b00;
+ class SSP,BO c;
+ class BE d;
+```
+
+Both FE contexts are **Customer/Conformist** to the backend's published aanvraag model. This is
+deliberately **not** a Shared Kernel between the two apps — coupling two audiences' codebases directly
+would defeat the point of splitting them.
+
+### 3. Separate identity from authorization
+
+These are two concerns people habitually conflate; keeping them apart is the crux of the model.
+
+- **Identity — "who are you, how did you log in"** → the `auth` context. Model the principal as a
+ **discriminated union**, the same "make illegal states unrepresentable" reflex as `RemoteData`:
+
+ ```ts
+ type Principal =
+ | { kind: 'zorgverlener'; bsn: string; naam: string } // DigiD/BSN
+ | { kind: 'medewerker'; medewerkerId: string; naam: string; rollen: Rol[] }; // employee SSO
+ ```
+
+ The union captures that the two actors authenticate differently and carry different identifiers —
+ a Behandelaar has no BSN, a Zorgverlener has no `rollen`. This replaces the flat `Session` the day a
+ second actor arrives.
+
+- **Authorization — "what may you do"** → enforced at the **backend / context boundary**, where the
+ backend is the authority (per ADR-0001). It is *not* a permission matrix living in `auth`. The
+ frontend receives only the decisions it needs to render (e.g. a `canBeoordelen` flag), exactly like
+ every other server-owned rule.
+
+### 4. "Other users" slot in without inventing contexts
+
+Admin, auditor, institution-rep are additional **`Principal` variants** or additional **`rollen` on
+`medewerker`** — never a new folder-per-role. A genuinely new *bounded context* is warranted only when
+an actor brings a new **language and capability** (e.g. an "Toezicht/Handhaving" enforcement context),
+not merely a new login.
+
+## Consequences
+
+- This repo **stays the pure SSP**. No backoffice code leaks in; no role-named folders appear.
+- The backoffice ships as a **separate app** against the same backend and the same OpenAPI contract.
+- The one concrete FE change when actor #2 lands is `Session → Principal` in the `auth` context; the
+ `authGuard`/`SessionStore` seams already localise that (`auth.guard.ts`, `session.store.ts`).
+- The backend becomes the authority for the **aanvraag status lifecycle** and for **authorization**,
+ publishing both as decision DTOs — a natural extension of ADR-0001, not a new pattern.
+- `pendingHerregistratie` is understood as a *temporary stand-in* for a real, backend-owned status.
+
+## Out of scope here (next steps, not built)
+
+- Building the Behandeling backoffice application.
+- Real authentication: DigiD (SSP) and employee SSO / eHerkenning (backoffice).
+- The `auth` `Session → Principal` refactor — deferred until a second actor is actually introduced.
+- The backend aanvraag status lifecycle + authorization endpoints/DTOs.
+
+ponytail: this ADR draws the boundaries so nothing has to be undone later; it does **not** scaffold a
+second app or a role system now. Introduce the `Principal` union and the status lifecycle when the
+backoffice work actually starts — YAGNI until then.