# Routes — application page hierarchy

Canonical data: `machine/routes.json`. Next.js App Router.
**Authorization lives in the services** — every service re-checks the caller's rights. Route-group layout guards are display comfort only: a layout wraps neither Server Actions nor route handlers, and is **not** a security boundary.

```
app/
├─ (auth)/
│  ├─ login/                      # no signup — accounts created by Admin (point D provisional)
│  └─ login/help/                 # public, EN/TH: "I cannot log in" — who resets, where to find them
│
├─ (app)/                         # layout: session + tab shell
│  ├─ page.tsx                    # "/" → redirect /tasks
│  ├─ tasks/
│  │  ├─ page.tsx                 # My Tasks — day|week|month, late badges, personal to-dos inline
│  │  ├─ new/page.tsx             # create & assign — same shell as siblings, no remount;
│  │  │                           #   creating is a permission-gated ACTION, enforced in the service
│  │  └─ [id]/page.tsx            # THE task detail — actions depend on my relation to this task
│  ├─ notifications/page.tsx      # list + SSE real time
│  ├─ job-description/page.tsx    # read projection of MY position (source: positions/[id]) — point H
│  └─ settings/page.tsx           # language EN/TH, password, ntfy preferences
│
│  ├─ (manager)/                  # guard: manager_level | admin (display comfort — see above)
│  │  ├─ positions/
│  │  │  ├─ page.tsx              # THE single positions list — manager: own dept; admin: all +
│  │  │  │                        #   structural verbs (create/rename/deactivate/move dept)
│  │  │  │                        #   rendered for admin only. No /admin/positions duplicate.
│  │  │  └─ [id]/page.tsx         # ★ position page = JD editor — the ONLY write surface
│  │  │                           #   duties CRUD/reorder · recurring templates · WI/SOP ·
│  │  │                           #   time-to-do · copy from position · move tasks
│  │  ├─ team/page.tsx            # team overview — layout waits for point B example
│  │  ├─ team/recurring/page.tsx  # read projection, dept-wide; edits deep-link to positions/[id]
│  │  ├─ review/page.tsx          # queue: tasks waiting for MY check / MY verification
│  │  └─ kpi/page.tsx             # my department's KPI (Q9); admin sees all
│  │
│  └─ (admin)/admin/              # guard: admin
│     ├─ departments/page.tsx     # create/rename/deactivate, never delete
│     ├─ people/
│     │  ├─ page.tsx              # ~400 people: held position + account, search
│     │  ├─ [id]/page.tsx         # routine & reversible ONLY: assignment · temp cover · pwd reset
│     │  └─ [id]/offboard/        # ★ the irreversible journey, its own page:
│     │                           #   target → preview impact → type-to-confirm → 1 transaction
│     └─ holidays/page.tsx        # annual holiday calendar (feeds date-shifting)
│
└─ api/v1/…                       # REST facade (not pages) — architecture.md §5
```

## Design rationale

- **URL never encodes the role — applied for real this time.** One positions list, one position page; structural verbs appear only for admin, exactly the `/tasks/[id]` pattern. The former `/admin/positions` was the same list twice with different buttons — deleted.
- **`/tasks/[id]` is the only task page.** Assignee, checker, verifier, one-time creator, dept manager, admin: same page, relation-driven actions.
- **`/tasks/new` lives with its siblings.** Creating is a permission-gated action (like check/verify), not a role area; nav shows it to the manager tier, the service enforces it for everyone. Same layout → no shell remount between `/tasks/*` URLs.
- **`/review` is data-driven, not role-routed.** Absorbs the point-A matrix for free.
- **One write surface for position data.** `/positions/[id]` edits; `/team/recurring` and `/job-description` are read projections that deep-link to it. If a projection shows something different, the projection is the bug.
- **Offboarding is a journey, not a button.** `/admin/people/[id]` keeps only routine, reversible actions; the irreversible transaction gets its own page with impact preview and type-to-confirm (spec §9).
- **"I cannot log in" has a path.** `/login/help` (public, EN/TH) says who resets and where to find them — otherwise point D's Admin/HR-only policy turns Roma & Narin into a 400-person helpdesk.
- **Staff visibility of other positions is now an explicit decision** — open point **H** (conservative default: own position only), no longer a side effect of the layout.
- **Line Leader editing JDs** → parked for the point-A matrix (spec default: all four levels equal).

## Open-point references (semantics owned by `machine/open-points.tsv`)

- **C, E** → recurring-instance content of `/tasks` waits for the engine. Pages themselves buildable.
- **B** → `/team` layout deliberately built last; its data is ready.
- **D** → `/login` built on the provisional; usernames are a mutable attribute (bulk UPDATE later, never account recreation).
- **H** → `/job-description` scope; conservative default in use.

Scaffold mapping — the six historic screens land in: `/tasks`, `/tasks/[id]`, `/team`, `/tasks/new`, `/review`, `/admin/people`. Total ≈20 pages.
