diff --git a/docs/adr/0006-demo-user-three-layer-policy.md b/docs/adr/0006-demo-user-three-layer-policy.md new file mode 100644 index 0000000..cbcbc85 --- /dev/null +++ b/docs/adr/0006-demo-user-three-layer-policy.md @@ -0,0 +1,30 @@ +# ADR-0006: Demo-user write protection enforced in three layers + +## Status + +accepted + +## Context + +Scrum4Me has a demo account that allows prospective users to explore the app without signing up. The demo user must never be able to create, update, or delete any data. A single guard at one layer is insufficient: a bug or a missing check in any one layer would expose a write path. See `docs/architecture/auth-and-sessions.md` and `docs/plans/ST-1110-demo-readonly.md` for implementation details. + +## Decision + +Write protection for the demo user is enforced at **three independent layers**: + +1. **Network — `proxy.ts`:** The Next.js proxy middleware rejects all non-GET requests from demo sessions before they reach any route handler or server action. +2. **Server — every Server Action and Route Handler:** Each write endpoint checks `session.isDemo` and returns `403` immediately if true. +3. **UI — disabled buttons + ``:** Write controls (create, edit, delete, reorder) are rendered as `disabled` with a tooltip explaining the demo restriction. No write request is ever sent. + +## Consequences + +### Positive + +- Defense-in-depth: any single layer can fail independently without exposing a write path. +- Clear user feedback at the UI layer without relying on error responses. +- Straightforward to audit: search for `isDemo` to find all enforcement points. + +### Negative + +- Three enforcement sites for every new write operation — easy to miss one when adding a new feature. +- Mitigation: the `DemoTooltip` pattern is documented in `docs/patterns/` and enforced in code review.