ADR-0080: Traceability Workspace — Hub, Sub-Pages, and Role-Gated Views¶
- Status: accepted (Nicolas 2026-07-18 — decisions confirmed at the foot of this ADR).
- Date: 2026-07-18
- Deciders: Nicolas Burri, design by Claude.
- Origin: Nicolas's play-test feedback (#5/#6): "the traceability view becomes overwhelming — I'd prefer sub-pages with an overview page linking to the detail views"; and "the QMB training overview should not be under My training but in the traceability section — do we need access control for who sees what within the traceability section, not only access to the whole page?"
- Relates to: the traceability model (traceability-model.md — the views this organizes), ADR-0049 (document-relation matrix), ADR-0077 (requirement coverage), ADR-0079 (risk traceability), ADR-0071 (training compliance), the opinionated-by-default principle (conventions.md), ADR-0027 (RLS).
- Refined by: ADR-0093 (the per-view scope selectors this workspace introduced are removed — the toolbar switcher becomes the one scope context, and required views show a neutral picker that writes the shared state)
Context¶
Traceability has grown into a family of distinct views — document-relation matrix, requirement coverage, risk traceability, and (Stage C) validation + GSPR — crammed onto one page that has become overwhelming. Two structural problems, confirmed in the code:
- No per-view access control. The
/traceabilityroute and its nav link carry no permission guard (unlike/admin,/scope-config) — every authenticated user reaches every view; only RLS filters the data. And the QMB training-compliance roll-up lives inside "My training" (my-training.ts) — a sensitive oversight surface (who is overdue) sitting on every user's personal page. "Who may see which oversight view" is currently unmodeled. - One flat page mixes personal-irrelevant oversight with everyday coverage, with no home that summarizes QMS health at a glance.
Decisions (each marked with the recommendation for review)¶
D-A — Traceability becomes a WORKSPACE: an overview hub + focused sub-pages [recommend]¶
/traceability becomes an overview hub whose tiles each show a headline metric + status
(e.g. "Requirement coverage 36/77 · 5 gaps", "Risk 2 gaps", "Training 3 overdue") and link to a
focused sub-page:
| Sub-page | Route | Content (existing) |
|---|---|---|
| Requirement coverage | /traceability/coverage |
ADR-0077 coverage view |
| Risk traceability | /traceability/risk |
ADR-0079 risk view |
| Document relations | /traceability/relations |
ADR-0049 relation matrix + coverage rules |
| Training compliance | /traceability/training |
ADR-0071 QMB roll-up (moved — D-B) |
| (Validation / GSPR) | reserved | Stage C — tiles appear when built |
The hub doubles as a QMS-health dashboard; the sub-pages are each a focused surface (a refactor that extracts today's panels into routed components — no data changes).
D-B — The QMB training-compliance oversight MOVES out of "My training" [recommend]¶
The scope compliance roll-up + aging (my-training.ts:237+) moves to /traceability/training.
"My training" keeps only the personal view (my obligations, my completions, my certifications).
Oversight and self-service are different audiences and different sensitivities.
D-C — Per-view authorization: server-enforced, UI-reflected, route-guarded [recommend 2-tier]¶
Each sub-view is gated by a permission in the existing per-scope permission model (the same
mechanism behind canConfigureScope() / canAdmin()), enforced server-side at the view's data
endpoint and reflected in the UI (the hub shows only permitted tiles; routes are guarded). It is
scope-aware: you see a sub-view for the scopes where you hold its permission.
Recommended granularity — two tiers, matching the natural cleavage:
VIEW_TRACEABILITY— the engineering-trace views (coverage, risk, relations, later validation/GSPR). Whoever does design control sees them together.VIEW_TRAINING_COMPLIANCE— the training oversight (personal-data-sensitive: who is overdue). A separate, more restricted gate.
This closes today's gap in both directions: the trace views stop being wide-open, and training compliance stops appearing on everyone's page.
D-D — Routing & guards¶
/traceability (hub) + /traceability/{coverage,risk,relations,training}, each route guarded by
its permission; the hub renders only the permitted tiles and, if the user holds none in any scope,
the Traceability nav entry hides entirely (like admin/scope-config). Server endpoints enforce
regardless of the UI.
Migration / seed¶
Add the two permissions to the vocabulary. Backfill so nothing silently breaks: grant
VIEW_TRACEABILITY to preserve current reach (Q-2), and VIEW_TRAINING_COMPLIANCE to the
QMB / quality-manager role only (Q-3) — deliberately tightening the currently-open training view.
Non-goals¶
Not adding trace content (validation/GSPR are Stage C — the hub only reserves their tiles); not changing the underlying data or RLS (this is a presentation + view-authorization layer over already-RLS-scoped data); not per-user ACLs (role/permission-based, per the opinionated model); the "My training" personal view is otherwise unchanged.
Consequences¶
- The hub is the reusable home for Stage C's validation + GSPR views (drop-in tiles).
- Per-view permissions become the pattern for any future oversight surface.
- A contained frontend refactor (panels → routed sub-components) + two new permissions + guards + endpoint checks + a seed/migration. No data-model change.
Decisions confirmed (Nicolas, 2026-07-18)¶
- Q-1 permission granularity → two tiers —
VIEW_TRACEABILITY(coverage / risk / relations, later validation / GSPR) +VIEW_TRAINING_COMPLIANCE(training oversight). - Q-2
VIEW_TRACEABILITYbackfill → granted to all scope members, preserving today's reach; RLS continues to scope the data. - Q-3
VIEW_TRAINING_COMPLIANCEholders → QMB / quality-manager role only — deliberately tightening the currently-open training view. - Q-4 hub scope model → one hub aggregating across the user's permitted scopes, with per-scope rows / metrics.
- Q-5 → "My training" keeps the personal view; only the QMB oversight roll-up moves.