Restructures into apps/ssp + apps/behandelportal (two Angular projects) plus libs/shared + libs/beheer (cross-app libraries), replacing WP-61's separate sibling repo. That split had already produced real drift: a hand-vendored copy of the backend's OpenAPI doc, a shared/ui+layout tree forked and silently diverging (7 files), and beheer + the styles.scss token bridge duplicated byte-for-byte across both repos. - git mv the SSP's src/app/* into apps/ssp/; fold shared/, beheer/, environments/, the Storybook docs/*.mdx, and styles.scss into libs/shared + libs/beheer (all confirmed identical between the two repos before merging). auth stays deliberately duplicated per ADR-0002 (actor-specific, expected to diverge) - amended there. - One generated API client (libs/shared), no more vendored swagger.json. - .dependency-cruiser split into a base factory + one config per app, and Storybook into .storybook-ssp/.storybook-behandelportal - both forced by the @auth/* alias resolving to different directories per app. - SiteHeaderComponent/ShellComponent gained HEADER_NAV_ITEMS/ HEADER_ADMIN_LINKS/DEBUG_PANEL injection tokens so each app supplies its own nav/admin-links/dev-panel instead of one being hardcoded. - CLAUDE.md, ARCHITECTURE.md, dependencies.md, and ADR-0002 updated; WP-67 backlog entry documents the full decision trail. npm run ci green (lint, dep:check x2, 360 tests across ssp/ behandelportal/shared/beheer, both localized builds, backend tests, snippet + api-client drift); both dev servers, both Storybook instances, and docker compose verified working. The old sibling repo (/home/eho/repos/behandelportal) is left untouched, not deleted. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
109 lines
4.5 KiB
TypeScript
109 lines
4.5 KiB
TypeScript
import { Routes } from '@angular/router';
|
|
import { ShellComponent } from '@shared/layout/shell/shell.component';
|
|
import { authGuard, capabilityGuard } from '@auth/auth.guard';
|
|
import { flushPendingGuard } from '@shared/application/pending-saves';
|
|
|
|
export const routes: Routes = [
|
|
{
|
|
path: '',
|
|
component: ShellComponent, // persistent header/footer; only children swap
|
|
children: [
|
|
{ path: '', pathMatch: 'full', redirectTo: 'login' },
|
|
{
|
|
path: 'login',
|
|
loadComponent: () => import('@auth/ui/login.page').then((m) => m.LoginPage),
|
|
},
|
|
{
|
|
path: 'dashboard',
|
|
canActivate: [authGuard],
|
|
loadComponent: () => import('@registratie/ui/dashboard.page').then((m) => m.DashboardPage),
|
|
},
|
|
{
|
|
path: 'registratie',
|
|
canActivate: [authGuard],
|
|
loadComponent: () =>
|
|
import('@registratie/ui/registration-detail.page').then((m) => m.RegistrationDetailPage),
|
|
},
|
|
{
|
|
path: 'aanvraag/:id',
|
|
canActivate: [authGuard],
|
|
loadComponent: () =>
|
|
import('@registratie/ui/aanvraag-detail.page').then((m) => m.AanvraagDetailPage),
|
|
},
|
|
{
|
|
path: 'registreren',
|
|
canActivate: [authGuard],
|
|
// Autosave wizard: flush the pending debounced draft before leaving (pending-saves.ts).
|
|
canDeactivate: [flushPendingGuard],
|
|
loadComponent: () =>
|
|
import('@registratie/ui/registratie.page').then((m) => m.RegistratiePage),
|
|
},
|
|
{
|
|
path: 'herregistratie',
|
|
canActivate: [authGuard],
|
|
canDeactivate: [flushPendingGuard],
|
|
loadComponent: () =>
|
|
import('@herregistratie/ui/herregistratie.page').then((m) => m.HerregistratiePage),
|
|
},
|
|
{
|
|
path: 'intake',
|
|
canActivate: [authGuard],
|
|
canDeactivate: [flushPendingGuard],
|
|
loadComponent: () => import('@herregistratie/ui/intake.page').then((m) => m.IntakePage),
|
|
},
|
|
{
|
|
path: 'brief',
|
|
canActivate: [authGuard],
|
|
canDeactivate: [flushPendingGuard],
|
|
loadComponent: () => import('@brief/ui/brief.page').then((m) => m.BriefPage),
|
|
},
|
|
{
|
|
path: 'brief/huisstijl',
|
|
// Admin-only org-template editor (WP-26): capabilityGuard denies-by-default
|
|
// unless GET /me resolved `orgtemplate:edit` (Admin role). Backend re-enforces
|
|
// via the OrgAdmin gate — the guard just avoids loading a page that would 403.
|
|
canActivate: [capabilityGuard('orgtemplate:edit')],
|
|
canDeactivate: [flushPendingGuard],
|
|
loadComponent: () => import('@brief/ui/org-template.page').then((m) => m.OrgTemplatePage),
|
|
},
|
|
{
|
|
path: 'beheer/stamdata',
|
|
// Admin-only stamdata maintenance editor (ADR-0004): capabilityGuard denies-by-default
|
|
// unless GET /me resolved `stamdata:edit` (Admin role). Backend re-enforces via the
|
|
// StamdataAdmin gate — the guard just avoids loading a page that would 403.
|
|
canActivate: [capabilityGuard('stamdata:edit')],
|
|
loadComponent: () => import('@beheer/ui/stamdata.page').then((m) => m.StamdataPage),
|
|
},
|
|
{
|
|
path: 'beheer/zaken',
|
|
// Admin-only cases overview + delete (WP-36): capabilityGuard denies-by-default
|
|
// unless GET /me resolved `cases:manage` (Admin role). Backend re-enforces via the
|
|
// CasesAdmin gate — the guard just avoids loading a page that would 403. The page
|
|
// lives in registratie/ui (which owns the Aanvraag aggregate); routed under /beheer.
|
|
canActivate: [capabilityGuard('cases:manage')],
|
|
loadComponent: () =>
|
|
import('@registratie/ui/admin-cases.page').then((m) => m.AdminCasesPage),
|
|
},
|
|
{
|
|
path: 'beheer/audit',
|
|
// Admin-only authz/PII-reveal audit trail (WP-41/42). capabilityGuard denies-by-default
|
|
// unless GET /me resolved `cases:manage` (reused for audit read). Backend re-enforces.
|
|
canActivate: [capabilityGuard('cases:manage')],
|
|
loadComponent: () => import('@beheer/ui/audit.page').then((m) => m.AuditPage),
|
|
},
|
|
{
|
|
path: 'beheer/functies',
|
|
// Admin-only feature-flag toggles (WP-47), gated by `flags:manage`.
|
|
canActivate: [capabilityGuard('flags:manage')],
|
|
loadComponent: () =>
|
|
import('@beheer/ui/feature-flags.page').then((m) => m.FeatureFlagsPage),
|
|
},
|
|
{
|
|
path: 'concepts',
|
|
loadComponent: () => import('./showcase/concepts.page').then((m) => m.ConceptsPage),
|
|
},
|
|
{ path: '**', redirectTo: 'login' },
|
|
],
|
|
},
|
|
];
|