diff --git a/SoW/.mermaid.json b/SoW/.mermaid.json
new file mode 100644
index 0000000..1bcd778
--- /dev/null
+++ b/SoW/.mermaid.json
@@ -0,0 +1,18 @@
+{
+ "theme": "base",
+ "themeVariables": {
+ "fontFamily": "Segoe UI, system-ui, -apple-system, Roboto, sans-serif",
+ "fontSize": "15px",
+ "primaryColor": "#e9eef8",
+ "primaryBorderColor": "#2a4c8f",
+ "primaryTextColor": "#18202e",
+ "lineColor": "#5a6478",
+ "secondaryColor": "#f2f4f8",
+ "tertiaryColor": "#ffffff",
+ "clusterBkg": "#fbfcfd",
+ "clusterBorder": "#c9d6ee",
+ "edgeLabelBackground": "#ffffff"
+ },
+ "flowchart": { "curve": "basis", "htmlLabels": true, "padding": 16, "nodeSpacing": 45, "rankSpacing": 55 },
+ "sequence": { "actorMargin": 40, "mirrorActors": false }
+}
diff --git a/SoW/.puppeteer.json b/SoW/.puppeteer.json
new file mode 100644
index 0000000..b911f25
--- /dev/null
+++ b/SoW/.puppeteer.json
@@ -0,0 +1 @@
+{ "executablePath": "/opt/pw-browsers/chromium", "args": ["--no-sandbox", "--disable-setuid-sandbox"] }
diff --git a/SoW/README.md b/SoW/README.md
new file mode 100644
index 0000000..a82534a
--- /dev/null
+++ b/SoW/README.md
@@ -0,0 +1,35 @@
+# SoW — Atlas PPM
+
+Statement-of-Work deliverables for the Atlas PPM engagement.
+
+## Contents
+
+| File | What |
+|---|---|
+| `STATEMENT-OF-WORK.md` / `.html` | **Canonical SoW** in the Birgma house format (17 sections; mirrors `GovernancePortal_Latest/docs/STATEMENT-OF-WORK.md`) |
+| `SoW-Atlas-PPM-Product-Build.md` | Detailed build SoW (Markdown, Confluence-ready) |
+| `SoW-Atlas-PPM-Remediation.md` | SoW for the code-review remediation engagement (Epic #106) |
+| `sow-atlas-ppm-product-build.html` | Product-build SoW as a styled, printable HTML page |
+| `flows.md` | Index of all flow diagrams (live Mermaid + image links) |
+| `flows-gallery.html` | Self-contained HTML gallery of every rendered flow |
+| `flows/*.mmd` | Mermaid source (20 system + 8 user + 9 dev = 37 flows) |
+| `images/*.png` | Static rendered images of each flow |
+
+## Three views of the flows
+
+- **System & data flows** (`NN-*.mmd`) — how the platform moves data and enforces rules.
+- **User journeys** (`user-*.mmd`) — persona → goal, step by step.
+- **Software-development interaction** (`dev-*.mmd`) — SDLC + how the pieces interact at build/run/deploy.
+
+## Regenerating the images
+
+Rendered with `@mermaid-js/mermaid-cli` against the repo's Chromium (not an app dependency — install on demand):
+
+```bash
+for f in flows/*.mmd; do
+ b=$(basename "$f" .mmd)
+ npx @mermaid-js/mermaid-cli -i "$f" -o "images/$b.png" -p .puppeteer.json -c .mermaid.json -b white -s 2
+done
+```
+
+`.mermaid.json` carries the Atlas theme; `.puppeteer.json` points at the pre-installed Chromium with `--no-sandbox`.
diff --git a/SoW/STATEMENT-OF-WORK.html b/SoW/STATEMENT-OF-WORK.html
new file mode 100644
index 0000000..c2eab46
--- /dev/null
+++ b/SoW/STATEMENT-OF-WORK.html
@@ -0,0 +1,350 @@
+
+
+
+
+
Statement of Work
+
Atlas PPM
+
Portfolio & Project Management platform — Birgma / Biltema Group
+
How to use this document. The scope, deliverables, acceptance criteria and security/compliance commitments below are grounded in the delivered system. Fields in [brackets] — parties, dates, effort and commercials — are for the contracting parties to complete; they are intentionally not pre-filled.
This Statement of Work defines the scope, deliverables, approach, acceptance criteria and responsibilities for the design, build and hand-over of Atlas — a Portfolio & Project Management web application that runs the Biltema Group portfolio end to end: demand intake and scoring, projects with stage-gate governance, programs and products, OKRs, timeline/Gantt planning, resource and financial management, delivery reporting, and a security/compliance module — with identity federated to Microsoft Entra ID and authorization enforced server-side. The frontend is reproduced pixel-faithful to the approved prototype (design/Atlas PPM.dc.html) and wired to the .NET 10 minimal API.
+
+
+
+
2 Background
+
Portfolio governance today is spread across spreadsheets and disconnected trackers, so demand, delivery, resourcing and financials cannot be seen or governed in one place, and stage-gate/architecture decisions are not auditable. Atlas replaces that with a single, role-aware platform: a controlled object model (demands → projects → programs/products/OKRs), server-authoritative RBAC, real-time collaboration, connector-fed work-item sync, and an ISO 27001 / GDPR-aware governance module — deployable on-premise and air-gapped.
+
+
+
+
3 Objectives
+
+
Federated single sign-on and least-privilege authorisation (Entra ID; 6 canonical roles enforced server-side via a capability matrix).
+
A faithful reproduction of every approved screen, data-driven with first-class loading / empty / error states (empty by default — no seed data).
+
A controlled demand → project → gate lifecycle with stage gates (G0–G5) and architecture/security gate reviews.
+
Planning & resourcing: timeline/Gantt with cross-entity dependencies; time-phased resource utilisation; financials (budget vs actual, FaC, ROI).
+
Integration: idempotent work-item sync from Jira and Azure DevOps behind one connector abstraction; Teams notifications.
+
Real-time collaboration: presence, cursors and live change-sync; PI board, task board, demand funnel and a freeform whiteboard.
+
Governance & compliance by design: decision log (ADR), TOGAF ADM, ISO 27001 Statement of Applicability, and GDPR handling of personnel data.
+
Portability & assurance: container-first, same-origin behind nginx, an air-gapped build, observability, backups and a continuously green CI gate.
Organisation-side security controls (MFA / Conditional Access, at-rest encryption, SIEM ingestion) — supported by the app; enabling them is an operator action.
+
Data migration from legacy PPM tools (unless added by change request).
+
Editing the design reference (design/) — regenerated by the design team.
All in-scope screens demonstrable against requirements.md (FR-*) and user-stories.md; real data with loading/empty/error; integration tests green
+
M2 Security acceptance
Threat model reviewed; server-authoritative RBAC verified by tests; no High findings in npm audit --omit=dev / Trivy; Semgrep + secrets clean; nginx CSP/TLS hardening
Per-project ISO 27001 SoA populated; GDPR / personnel-data pack reviewed by [DPO]; DPIA + MBL §11 sign-off; audit trail verified
+
M5 Documentation & hand-over
D4–D9 delivered; knowledge-transfer session held
+
M6 Live sign-off
A real Entra interactive sign-in verified in [staging/production]; go-live approved by [sponsor]
+
+
+
Definition of Done (per work package): code merged to main behind green CI (one issue → one PR); tests for the behaviour; docs/ADR updated; no High/Critical security findings; module-boundary ratchet and API type-contract drift both green.
+
+
+
+
8 Roles & responsibilities (RACI)
+
+
Activity
Delivery team
Client / IT
Sponsor
DPO
+
+
Build & test the application
R/A
C
I
I
+
Entra tenant + app registrations, MFA/CA
C
R/A
I
I
+
Host / network / TLS certificates
C
R/A
I
—
+
Connector setup + consent (Jira/ADO/Teams/Graph)
C
R/A
I
—
+
Security & compliance artefacts
R/A
C
I
C
+
Personnel-data sign-off (DPIA / MBL §11)
C
C
I
R/A
+
Acceptance & go-live approval
C
C
R/A
C
+
+
+
R = Responsible · A = Accountable · C = Consulted · I = Informed. Names: [to complete].
+
+
+
+
9 Assumptions & dependencies
+
+
An Entra ID tenant is available with rights to create app registrations and grant admin consent; MFA / Conditional Access is enabled organisation-side.
+
A Windows / VMware host is provisioned with the runtime; TLS certificates supplied; served same-origin behind nginx.
+
PostgreSQL 16 is provisioned; off-host, access-controlled backup storage is available.
+
Directory data via Entra; the client nominates admins, approvers and connector credentials (Jira / Azure DevOps / Teams / Graph).
+
The environment is air-gapped at runtime — all assets self-hosted; build tooling runs in CI, not on the target.
+
+
+
+
+
10 Constraints
+
+
Single-instance, same-origin on-premise deployment; the value is auditability and durability of portfolio evidence, not high availability.
+
No runtime internet egress — no CDNs; fonts/assets bundled (ADR-0078).
+
Deployment is by downloading built artefacts to a Windows server (no git on target); artefacts must be self-contained.
+
Authorization is server-authoritative; the client is never a security boundary.
+
Stack: React 18 / TypeScript / Vite · .NET 10 minimal API / EF Core 10 · PostgreSQL 16 · modern evergreen browsers.
+
+
+
+
+
11 Environment & technical requirements
+
Technical requirements are specified in requirements.md (TR-*): platform, frontend, identity, API/data, storage, messaging, security, observability, i18n, CI and compatibility. Setup steps are in SETUP.md / DOCKER.md; identity in sso-setup.md; connectors in jira-setup.md, azure-devops-setup.md, teams-setup.md, email-graph-setup.md.
+
+
+
+
12 Security & compliance obligations
+
The supplier will deliver and maintain: a threat model (threat-model.md) and hardening record (security-hardening.md); server-authoritative RBAC (capability matrix, ADR-0004); a per-project ISO 27001:2022 Statement of Applicability (ADR-0066); a compliance module mapping controls across GDPR / PCI-DSS / ISO 27001 / EU AI Act / SOC 2 / NIS2; and a GDPR / personnel-data pack (dpia-personnel-data.md, compliance-sweden.md, retention.md) — DSAR export, evidence-preserving erasure and retention purge. CI enforces SAST (Semgrep), Trivy, an axe sweep, coverage floors, an API type-contract drift check and the ADR-0072 module-boundary ratchet; GitHub Actions are pinned to commit SHAs. Personnel-data features stay gated off until DPIA + MBL §11 sign-off (ADR-0063).
+
+
+
+
13 Change control & governance
+
Changes to scope, deliverables or acceptance criteria are handled by written change request: description, rationale, impact on schedule/effort, and sign-off by [sponsor] and [delivery lead]. Day-to-day delivery is tracked on main with green-CI gating, one issue → one PR, and an ADR for every significant decision (architecture/adr/, ALL-ADRS.md). Product-owner-approved deviations from the frozen prototype are recorded in CLAUDE.md §2 and an ADR.
+
+
+
+
14 Risks
+
Key delivery/operational risks and mitigations are catalogued in threat-model.md and the ADRs. Highest residual items are organisation-side: enabling MFA / Conditional Access, at-rest encryption and SIEM forwarding. Delivery-side watch items: prototype-fidelity acceptance (mitigated by side-by-side review), the air-gapped no-CDN constraint (self-hosted assets, offline build verified), and the staged migration of legacy display-string date columns (ADR-0082, per-module).
+
+
+
+
15 Commercials
+
[To be completed by the parties — pricing model (fixed-price / capped T&M / T&M), total or not-to-exceed, rate card, effort estimate, payment schedule (tied to the milestones in §7), expenses, warranty and any support/maintenance terms. Not pre-filled.]
+
+
+
+
16 Acceptance & sign-off
+
Acceptance is granted per milestone (§7). Final acceptance follows M6 (live sign-off). This Statement of Work is agreed and authorised by:
Companion SoWs: SoW-Atlas-PPM-Product-Build.md (detailed build, self-contained with the 39 embedded flow diagrams) and SoW-Atlas-PPM-Remediation.md (Epic #106 remediation). Format follows the Birgma house Statement-of-Work template.
+
+
+
A Appendix — Functional flows
+
The complete flow library (39 diagrams), also maintained as editable Mermaid in SoW/flows/ and indexed in SoW/flows.md.
+
A.1 System & data flows
+
Application map & navigation
Authentication & RBAC gate
Dashboard layouts & data
Demand funnel
Portfolio → Project
Stage gates G0–G5
Task board (realtime)
Gantt & dependencies
Resource utilisation
Financials roll-up
Program detail
Products → Releases
OKRs linkage
Delivery status
News wall
Connector sync (Jira/ADO)
Whiteboard co-editing
Reports & export
Administration
Governance & compliance
+
A.2 User journeys (per role)
+
Executive — portfolio review
PMO — approve a demand
PM — create a project (wizard)
PM — manage tasks & Jira sync
PM — stage-gate review
Team member — update my work
Stakeholder — check my status
Manager — My Team
Platform Admin — administration
Chief Architect — governance
+
A.3 Software-development interaction flows
+
Change lifecycle
CI pipeline
API type contract + drift
Module-boundary ratchet
Test strategy
Local dev loop
Build & air-gapped deploy
Runtime topology
Extending a connector
+
+
+
\ No newline at end of file
diff --git a/SoW/STATEMENT-OF-WORK.md b/SoW/STATEMENT-OF-WORK.md
new file mode 100644
index 0000000..e54b9a9
--- /dev/null
+++ b/SoW/STATEMENT-OF-WORK.md
@@ -0,0 +1,419 @@
+# Statement of Work — Atlas PPM
+
+> **How to use this document.** The scope, deliverables, acceptance criteria and
+> security/compliance commitments below are grounded in the delivered system.
+> Fields in **[brackets]** — parties, dates, effort and commercials — are for the
+> contracting parties to complete; they are intentionally not pre-filled.
+
+| | |
+|---|---|
+| **Project** | Atlas — Portfolio & Project Management (PPM) platform |
+| **Client / Sponsor** | [Birgma / Biltema — sponsor name] |
+| **Supplier / Delivery** | [Delivery team / vendor] |
+| **SoW version** | 1.0 · [date] |
+| **Effective period** | [start] – [end] |
+| **Document owner** | [name, role] |
+
+---
+
+## 1. Purpose
+
+This Statement of Work defines the scope, deliverables, approach, acceptance
+criteria and responsibilities for the design, build and hand-over of **Atlas** —
+a Portfolio & Project Management web application that runs the Biltema Group
+portfolio end to end: demand intake and scoring, projects with stage-gate
+governance, programs and products, OKRs, timeline/Gantt planning, resource and
+financial management, delivery reporting, and a security/compliance module —
+with identity federated to **Microsoft Entra ID** and authorization enforced
+server-side. The frontend is reproduced **pixel-faithful to the approved
+prototype** (`design/Atlas PPM.dc.html`) and wired to the **.NET 10 minimal API**.
+
+## 2. Background
+
+Portfolio governance today is spread across spreadsheets and disconnected
+trackers, so demand, delivery, resourcing and financials cannot be seen or
+governed in one place, and stage-gate/architecture decisions are not auditable.
+Atlas replaces that with a single, role-aware platform: a controlled object
+model (demands → projects → programs/products/OKRs), server-authoritative RBAC,
+real-time collaboration, connector-fed work-item sync, and an ISO 27001 /
+GDPR-aware governance module — deployable **on-premise and air-gapped**.
+
+## 3. Objectives
+
+1. Federated single sign-on and least-privilege authorisation (Entra ID; 6
+ canonical roles enforced server-side via a capability matrix).
+2. A faithful reproduction of every approved screen, **data-driven** with
+ first-class loading / empty / error states (empty by default — no seed data).
+3. A controlled **demand → project → gate** lifecycle with stage gates (G0–G5)
+ and architecture/security gate reviews.
+4. **Planning & resourcing**: timeline/Gantt with cross-entity dependencies;
+ time-phased resource utilisation; financials (budget vs actual, FaC, ROI).
+5. **Integration**: idempotent work-item sync from Jira and Azure DevOps behind
+ one connector abstraction; Teams notifications.
+6. **Real-time collaboration**: presence, cursors and live change-sync; PI board,
+ task board, demand funnel and a freeform whiteboard.
+7. **Governance & compliance by design**: decision log (ADR), TOGAF ADM, ISO
+ 27001 Statement of Applicability, and GDPR handling of personnel data.
+8. **Portability & assurance**: container-first, same-origin behind nginx, an
+ air-gapped build, observability, backups and a continuously green CI gate.
+
+## 4. Scope of work
+
+### 4.1 In scope (work packages)
+
+| WP | Work package | Summary |
+|----|--------------|---------|
+| WP1 | Identity & access | Entra SSO (MSAL); RS256 token validation (issuer/audience/tenant); server-authoritative RBAC capability matrix (6 canonical roles; 9 cosmetic header identities); idle logout; anonymous-in-production boot fuses |
+| WP2 | Portfolio & demand intake | Portfolio (projects + blockers); Demand Pipeline value-vs-effort scored funnel; Programs (stakeholder power/interest matrix); Products; OKRs linked to projects/programs/products |
+| WP3 | Project delivery | Project Detail — Overview, Tasks (board + list, drag), Epics, RAID, Artifacts (+versions), Costs (labor/license/PaaS/IaaS/SaaS), Gates (G0–G5), Security (ISO 27001 SoA); People & roles incl. delivery roles (Tech Lead / Scrum Master) |
+| WP4 | Planning & timeline | Timeline / Gantt (project & program scope); phases, bars, milestones; cross-entity dependency arrows (`manual` / `jira` / `project`) |
+| WP5 | Resources & financials | Resource roster (Entra-synced); period-windowed utilisation with a shared time-phased engine + date-range filter; Financials — budget vs actual, CapEx/OpEx, forecast-at-completion, savings/benefit, portfolio ROI |
+| WP6 | Reporting & assurance | Dashboard (Executive / Operational / Compact / drag-and-drop Custom); Delivery status by period; Releases calendar; Weekly Updates (news wall); branded Reports with PDF / Excel / PPTX export; audit log |
+| WP7 | Integrations | Jira & Azure DevOps work-item sync behind one `IWorkItemConnector` (shared background queue/worker, 202 + poll, delta watermark); Microsoft Teams notifications; connector catalogue (ServiceNow, ManageEngine SDP, GitHub, Confluence, Slack, Power BI) |
+| WP8 | Real-time collaboration | Single SignalR "room" hub — presence, shared cursors, live change-sync, off-screen peer indicators; PI Program Board, demand funnel, task board; Freeform Whiteboard with granular authorized co-editing |
+| WP9 | Governance & compliance | Stage gates + gate reviews (architecture/security); decision log (ADR); TOGAF ADM phases, architecture domains/waivers/ARB; ISO 27001 SoA; security/compliance module (GDPR, PCI-DSS, ISO 27001, EU AI Act, SOC 2, NIS2) with control mappings |
+| WP10 | People, teams & methodology | My Team — members & skills matrix, Team SWOT, individual development plans (manager-scoped, governance-gated); Methodologies library + create-project wizard |
+| WP11 | Platform quality & CI | Generated API type contract (OpenAPI → TypeScript) with drift check; module-boundary ratchet (ADR-0072); tests (xUnit · Vitest · Playwright + axe · k6) with coverage floors; SAST (Semgrep) + Trivy; SHA-pinned GitHub Actions |
+| WP12 | Air-gapped operations & docs | Self-hosted fonts/assets; nginx same-origin (`/api/v1`, `/hubs`); OpenTelemetry observability; backups/restore; audit trail; secret rotation; architecture (HLD/LLD/ADRs/ABB-SBB), requirements, install/integration guides |
+
+### 4.2 Out of scope
+
+- Hosting, network and identity-tenant administration beyond configuration
+ guidance (Entra tenant, Windows/VMware host, corporate network, firewalls, TLS).
+- Organisation-side security controls (MFA / Conditional Access enablement,
+ at-rest disk encryption, SIEM ingestion) — the application supports them;
+ enabling them is an operator/IT action.
+- Data migration from legacy PPM tools (unless added by change request).
+- Editing the design reference (`design/`) — regenerated by the design team.
+- **Jira bidirectional write-back** (Proposed, ADR-0080 — pending sign-off).
+- **Full screen-body internationalisation** — the product is English content with
+ localised chrome (ADR-0084) until a product decision widens it.
+- Personnel-data features (Team SWOT / development plans) remain **gated off**
+ until DPIA + MBL §11 sign-off (ADR-0063).
+
+## 5. Deliverables
+
+| # | Deliverable | Form | Acceptance evidence |
+|---|-------------|------|---------------------|
+| D1 | Web application (SPA + API + database) | Running same-origin stack | Builds & serves behind nginx; frontend `npm run build` green; API `/health`·`/readyz` healthy |
+| D2 | Source code + CI pipelines | Git repository | CI green: frontend (lint/test/build + coverage floor), API (build/test + coverage floor), API type-contract drift, accessibility (axe), SAST (Semgrep) + Trivy |
+| D3 | Automated test suite | Code | Backend xUnit (incl. fixtures + architecture-boundary tests) + frontend Vitest + Playwright/axe + k6; coverage floors gated in CI (backend line ≥ 65 %, frontend line ≥ 6 %, raised as screens gain tests) |
+| D4 | Architecture & design docs | Markdown | `architecture/hld.md`, `architecture/lld.md`, `architecture/adr/` (+ `ALL-ADRS.md`), `architecture/building-blocks.md` (ABB/SBB) |
+| D5 | Requirements & user stories | Markdown | `requirements.md` (FR/NFR/TR), `user-stories.md` |
+| D6 | Security & compliance pack | Markdown + code | `threat-model.md`, `security-hardening.md`, `pentest-scope.md`, per-project ISO 27001 SoA (ADR-0066), control mappings |
+| D7 | GDPR / personnel-data pack | Markdown | `dpia-personnel-data.md`, `compliance-sweden.md`, `retention.md` (DSAR export, evidence-preserving erasure, retention purge) |
+| D8 | Operations runbooks | Markdown | `SETUP.md`, `DOCKER.md`, `sso-setup.md`, `secrets.md`, `observability.md`, `postgres-cert-auth.md`, connector setup guides |
+| D9 | User & functional documentation | Markdown + HTML | `user-stories.md`, `accessibility.md`, and the flow package — `SoW/flows.md` + gallery (39 diagrams: system · per-role journeys · development) |
+
+## 6. Approach & delivery phases
+
+Iterative delivery; each phase is independently shippable and CI-gated. (Phases
+reflect the documented delivery state and forward plan; see the ADRs.)
+
+| Phase | Focus | Status |
+|-------|-------|--------|
+| P0 — Shell & SSO | App shell, routing, theme tokens, Entra SSO, RBAC capability matrix | Delivered |
+| P1 — Core objects | Dashboard, Portfolio (+ Blockers), Project Detail, Demands funnel | Delivered |
+| P2 — Planning & portfolio breadth | Gantt/timeline, Programs, Products, OKRs, Resources, Financials | Delivered |
+| P3 — Reporting | Delivery status, Releases, Weekly Updates (news), branded Reports | Delivered |
+| P4 — Integrations & real-time | Jira/ADO connector abstraction, Teams notifications, SignalR rooms | Delivered |
+| P5 — Governance & compliance | Stage gates, gate reviews, ADR log, TOGAF ADM, ISO 27001 SoA, compliance module | Delivered |
+| P6 — Approved extensions | Whiteboard, Team SWOT & dev plans, timeline dependencies, brand themes, quality/Jira ingest | Delivered (CLAUDE.md §2 + ADRs) |
+| P7 — Engineering-quality remediation | Security hardening, generated API types, connector abstraction, comment/god-object cleanup (Epic #106; ADRs 0080–0084) | Delivered |
+| P8 — Azure-native / production migration | Managed identity, Key Vault, managed Postgres (PITR), private networking, WAF | Planned (separate SoW) |
+
+## 7. Milestones & acceptance criteria
+
+| Milestone | Acceptance criteria |
+|-----------|---------------------|
+| M1 Functional acceptance | All in-scope screens demonstrable against `requirements.md` (FR-*) and `user-stories.md`; each view shows real data with loading/empty/error; integration tests green |
+| M2 Security acceptance | Threat model reviewed; server-authoritative RBAC verified by tests; no High findings in `npm audit --omit=dev` / Trivy; Semgrep + secrets scan clean; nginx CSP/TLS hardening in place |
+| M3 Operational acceptance | Same-origin deployment per `SETUP.md` / `DOCKER.md`; `/health`·`/readyz` pass; **backup + restore rehearsed**; air-gapped build verified (no runtime egress) |
+| M4 Compliance acceptance | Per-project ISO 27001 SoA populated; GDPR / personnel-data pack reviewed by [DPO]; DPIA + MBL §11 sign-off for personnel features; audit trail verified |
+| M5 Documentation & hand-over | D4–D9 delivered; knowledge-transfer session held |
+| M6 Live sign-off | A real Entra interactive sign-in verified in [staging/production]; go-live approved by [sponsor] |
+
+**Definition of Done (per work package):** code merged to `main` behind green CI
+(one issue → one PR); tests for the behaviour; docs/ADR updated; no High/Critical
+security findings; module-boundary ratchet and API type-contract drift both green.
+
+## 8. Roles & responsibilities (RACI)
+
+| Activity | Delivery team | Client / IT | Sponsor | DPO |
+|---|---|---|---|---|
+| Build & test the application | R/A | C | I | I |
+| Entra tenant + app registrations, MFA/CA | C | R/A | I | I |
+| Host / network / TLS certificates | C | R/A | I | — |
+| Connector setup + consent (Jira/ADO/Teams/Graph) | C | R/A | I | — |
+| Security & compliance artefacts | R/A | C | I | C |
+| Personnel-data sign-off (DPIA / MBL §11) | C | C | I | R/A |
+| Acceptance & go-live approval | C | C | R/A | C |
+
+_R = Responsible · A = Accountable · C = Consulted · I = Informed. Names: [to complete]._
+
+## 9. Assumptions & dependencies
+
+- An **Entra ID tenant** is available with rights to create app registrations and
+ grant admin consent; **MFA / Conditional Access** is enabled organisation-side.
+- A **Windows / VMware host** (or the agreed target) is provisioned with the
+ runtime; **TLS certificates** are supplied; the site is served same-origin
+ behind nginx.
+- **PostgreSQL 16** is provisioned; off-host, access-controlled **backup storage**
+ is available.
+- Directory data is provided via **Entra**; the client nominates admins, approvers
+ and connector credentials (Jira / Azure DevOps / Teams / Graph).
+- The environment is **air-gapped** at runtime — all assets are self-hosted; build
+ tooling runs in CI, not on the target.
+
+## 10. Constraints
+
+- Single-instance, same-origin on-premise deployment; the value is auditability
+ and durability of portfolio evidence, not high availability.
+- **No runtime internet egress** — no CDNs; fonts/assets bundled (ADR-0078).
+- Deployment is by **downloading built artefacts to a Windows server** (no git on
+ the target); artefacts must be self-contained.
+- Authorization is **server-authoritative**; the client is never a security
+ boundary. UI role checks are cosmetic.
+- Stack: React 18 / TypeScript / Vite · .NET 10 minimal API / EF Core 10 ·
+ PostgreSQL 16 · modern evergreen browsers.
+
+## 11. Environment & technical requirements
+
+Technical requirements are specified in `requirements.md` (TR-*): platform,
+frontend, identity, API/data, storage, messaging, security, observability, i18n,
+CI and compatibility. Setup steps are in `SETUP.md` / `DOCKER.md`; identity in
+`sso-setup.md`; connectors in `jira-setup.md`, `azure-devops-setup.md`,
+`teams-setup.md`, `email-graph-setup.md`.
+
+## 12. Security & compliance obligations
+
+The supplier will deliver and maintain: a **threat model** (`threat-model.md`) and
+security-hardening record (`security-hardening.md`); **server-authoritative RBAC**
+(capability matrix, ADR-0004); a per-project **ISO 27001:2022 Statement of
+Applicability** (ADR-0066); a security/compliance module mapping controls across
+GDPR / PCI-DSS / ISO 27001 / EU AI Act / SOC 2 / NIS2; and a **GDPR / personnel-data
+pack** (`dpia-personnel-data.md`, `compliance-sweden.md`, `retention.md`) — DSAR
+export, evidence-preserving erasure and retention purge. CI enforces SAST
+(Semgrep), dependency/secret/IaC scanning (Trivy), an accessibility (axe) sweep,
+coverage floors, an API type-contract drift check and the ADR-0072 module-boundary
+ratchet; GitHub Actions are pinned to commit SHAs. Personnel-data features stay
+gated off until DPIA + MBL §11 sign-off (ADR-0063).
+
+## 13. Change control & governance
+
+Changes to scope, deliverables or acceptance criteria are handled by written
+**change request**: description, rationale, impact on schedule/effort, and sign-off
+by [sponsor] and [delivery lead]. Day-to-day delivery is tracked on `main` with
+green-CI gating, **one issue → one PR**, and an ADR for every significant
+decision (see `architecture/adr/` and `ALL-ADRS.md`). Product-owner-approved
+deviations from the frozen prototype are recorded in `CLAUDE.md §2` and an ADR.
+
+## 14. Risks
+
+Key delivery/operational risks and mitigations are catalogued in `threat-model.md`
+and the ADRs. Highest residual items are organisation-side: enabling MFA /
+Conditional Access, at-rest encryption and SIEM forwarding. Delivery-side watch
+items: prototype-fidelity acceptance (mitigated by side-by-side review), the
+air-gapped no-CDN constraint (self-hosted assets, offline build verified), and the
+staged migration of legacy display-string date columns (ADR-0082, per-module).
+
+## 15. Commercials
+
+[To be completed by the parties — pricing model (fixed-price / capped T&M / T&M),
+total or not-to-exceed, rate card, effort estimate, payment schedule (tied to the
+milestones in §7), expenses, warranty and any support/maintenance terms. Not
+pre-filled.]
+
+## 16. Acceptance & sign-off
+
+Acceptance is granted per milestone (§7). Final acceptance follows M6 (live
+sign-off). This Statement of Work is agreed and authorised by:
+
+| Party | Name | Signature | Date |
+|---|---|---|---|
+| Client / Sponsor | [ ] | | |
+| Delivery lead | [ ] | | |
+| DPO (compliance) | [ ] | | |
+
+_Effective date: [on last signature] · SoW version: 1.0 · Supersedes: [none / prior]._
+
+## 17. References
+
+`requirements.md` · `user-stories.md` · `architecture/hld.md` ·
+`architecture/lld.md` · `architecture/adr/` (+ `ALL-ADRS.md`) ·
+`architecture/building-blocks.md` · `threat-model.md` · `security-hardening.md` ·
+`pentest-scope.md` · `compliance-sweden.md` · `dpia-personnel-data.md` ·
+`retention.md` · `accessibility.md` · `observability.md` · `SETUP.md` ·
+`DOCKER.md` · `sso-setup.md` · `secrets.md` · connector guides (`jira-setup.md`,
+`azure-devops-setup.md`, `teams-setup.md`, `email-graph-setup.md`) ·
+`SoW/flows.md` (functional flows). Companion SoWs: `SoW-Atlas-PPM-Product-Build.md`
+(detailed build) and `SoW-Atlas-PPM-Remediation.md` (Epic #106 remediation).
+
+---
+
+## Appendix A — Functional flows
+
+The complete flow library (39 diagrams); editable Mermaid in `flows/`, indexed in `flows.md`. The HTML edition embeds these inline.
+
+### A.1 System & data flows
+
+**Application map & navigation**
+
+
+
+**Authentication & RBAC gate**
+
+
+
+**Dashboard layouts & data**
+
+
+
+**Demand funnel**
+
+
+
+**Portfolio → Project**
+
+
+
+**Stage gates G0–G5**
+
+
+
+**Task board (realtime)**
+
+
+
+**Gantt & dependencies**
+
+
+
+**Resource utilisation**
+
+
+
+**Financials roll-up**
+
+
+
+**Program detail**
+
+
+
+**Products → Releases**
+
+
+
+**OKRs linkage**
+
+
+
+**Delivery status**
+
+
+
+**News wall**
+
+
+
+**Connector sync (Jira/ADO)**
+
+
+
+**Whiteboard co-editing**
+
+
+
+**Reports & export**
+
+
+
+**Administration**
+
+
+
+**Governance & compliance**
+
+
+
+### A.2 User journeys (per role)
+
+**Executive — portfolio review**
+
+
+
+**PMO — approve a demand**
+
+
+
+**PM — create a project (wizard)**
+
+
+
+**PM — manage tasks & Jira sync**
+
+
+
+**PM — stage-gate review**
+
+
+
+**Team member — update my work**
+
+
+
+**Stakeholder — check my status**
+
+
+
+**Manager — My Team**
+
+
+
+**Platform Admin — administration**
+
+
+
+**Chief Architect — governance**
+
+
+
+### A.3 Software-development interaction flows
+
+**Change lifecycle**
+
+
+
+**CI pipeline**
+
+
+
+**API type contract + drift**
+
+
+
+**Module-boundary ratchet**
+
+
+
+**Test strategy**
+
+
+
+**Local dev loop**
+
+
+
+**Build & air-gapped deploy**
+
+
+
+**Runtime topology**
+
+
+
+**Extending a connector**
+
+
+
diff --git a/SoW/SoW-Atlas-PPM-Product-Build.md b/SoW/SoW-Atlas-PPM-Product-Build.md
new file mode 100644
index 0000000..8d45202
--- /dev/null
+++ b/SoW/SoW-Atlas-PPM-Product-Build.md
@@ -0,0 +1,340 @@
+# Statement of Work — Atlas PPM Product Build
+
+| Field | Value |
+|---|---|
+| **Project** | Atlas — Portfolio & Project Management platform |
+| **Client** | Birgma / Biltema Group (Nordic retail) |
+| **Repository** | `nicpozent/ATLASPPM_AdditionalFeatures` |
+| **Prepared for** | nicolas.pozza@birgma.com |
+| **Date** | 2026-08-07 |
+| **Document type** | Statement of Work — for signature (v1.0 draft) |
+
+---
+
+## 1. Background & objectives
+
+Atlas is a Portfolio & Project Management web application for Birgma / Biltema
+Group. This engagement delivers the **full application** — every screen and all
+functionality — **pixel-faithful to the approved prototype**
+(`design/Atlas PPM.dc.html`), wired to the **.NET 10 minimal API** backend, and
+hardened for an **on-premise, air-gapped** deployment.
+
+Primary objectives:
+
+1. Reproduce every prototype screen 1:1 (layout, typography, colour, components,
+ states, copy) with no redesign or additions beyond approved extensions.
+2. Data-drive every screen from the `/api/v1/*` API via TanStack Query, with
+ first-class **loading / empty / error** states (empty by default — no
+ fabricated seed data).
+3. Enforce **server-authoritative** role-based access control; the client is
+ never a security boundary.
+4. Meet the non-functional bar: accessibility (WCAG AA), localised chrome,
+ security/compliance modules, and a continuously green automated build.
+
+---
+
+## 2. Scope of work
+
+### 2.1 Workspace screens
+- **Dashboard** — four layouts via a segmented control: Executive
+ (portfolio-health donut, budget-burn, KPI cards w/ sparklines,
+ active-projects table, needs-attention, demand pipeline, recent activity),
+ Operational, Compact, and a drag-and-drop **Custom** builder.
+- **Portfolio** — Projects (filter chips + cards/table) and Blockers (list +
+ side panel); drill-through to Project Detail.
+- **Programs** — list + detail (stakeholder power/interest matrix, linked
+ projects, status); create-program modal.
+- **Products** — product portfolio; Jira/ADO tasks mapped to releases.
+- **OKRs** — objectives with key results linked to projects/programs/products.
+- **Demands** — value-vs-effort scored intake **funnel**; drag across stages;
+ create/approve modals.
+- **Timeline / Gantt** — Project / Program scope; phases, bars, milestones,
+ dependency arrows, month grid, export.
+- **Project Detail** — tabs: Overview, Tasks (board + list, drag), Epics, RAID,
+ Artifacts (+ versions), Costs (labor/license/PaaS/IaaS/SaaS), Gates (G0–G5),
+ Security (ISO 27001 SoA), plus people, linked products, change requests.
+- **Resources** — people synced from Entra ID; allocation vs availability;
+ period-windowed utilisation with a date-range filter.
+- **Financials** — budget vs actual, CapEx/OpEx, forecast-at-completion,
+ savings/benefit, portfolio ROI, source toggle.
+- **Delivery Status** — stakeholder report by period; velocity, on-time %,
+ blockers, budget burn.
+- **Releases** — release calendar & deployment tracking.
+- **Weekly Updates (News)** — editable news wall (masonry, themes, edit mode).
+
+### 2.2 Configuration screens
+- **My Team** — members & skills, per-team SWOT, individual development plans
+ (manager-scoped; governance-gated).
+- **Methodologies** — methodology library + create-project wizard.
+- **Integrations** — connectors (Jira, Azure DevOps, ServiceNow, ManageEngine
+ SDP, GitHub, Confluence, Teams, Slack, Power BI), SSO, email, directory sync.
+- **Reports** — branded portfolio/demand/blocker/audit reports; export formats.
+- **Administration** — roles & permissions matrix, backups/restore, audit log,
+ AD sync, install/integration guides, deletion requests.
+- **Help** — role-based guides, articles, contact.
+
+### 2.3 Stakeholder experience
+- Reduced navigation: **My Projects**, **My Demands** + Delivery, Releases,
+ News, Help.
+
+### 2.4 Governance modules
+- Stage gates G0–G5, gate reviews (architecture/security), decision log (ADR),
+ TOGAF ADM phases, architecture domains/waivers/ARB, and a security/compliance
+ module (GDPR, PCI-DSS, ISO 27001, EU AI Act, SOC 2, NIS2) with control
+ mappings, reproduced where the prototype places them.
+
+### 2.5 Approved extensions (beyond the frozen prototype)
+Built in the existing design language and recorded per `CLAUDE.md §2` + an ADR:
+Microsoft Teams notifications; real-time collaboration (SignalR rooms — PI
+Program Board, demand funnel, task board, live presence/cursors/off-screen
+peers); Freeform Whiteboard (co-editing, templates, export); Team SWOT and
+individual development plans; ISO 27001 Statement of Applicability; cross-entity
+timeline dependencies; period-windowed resource utilisation; quality test tasks
++ Jira board ingest; project delivery roles (Tech Lead / Scrum Master); and the
+three Atlas brand themes (Command / Daylight / Carbon).
+
+### 2.6 Platform & cross-cutting
+- Entra ID (MSAL) SSO with route guards; server-authoritative RBAC (6 canonical
+ roles; 9 cosmetic header identities).
+- Generated API type contract (OpenAPI → TypeScript) with CI drift protection.
+- Self-hosted fonts/assets for air-gapped operation; nginx same-origin serving.
+- Observability (OpenTelemetry), backups/restore, audit trail, secret rotation.
+
+### 2.7 Out of scope
+- Any redesign, restyling, or screens/sections not in the prototype (except the
+ §2.5 approved extensions).
+- New CSS frameworks or global stylesheets (inline theme tokens only).
+- Client-side authorization as a security control.
+- Full screen-body internationalisation (chrome-only per ADR-0084 until a
+ product decision widens it).
+- Jira bidirectional write-back (Proposed, ADR-0080 — pending sign-off).
+- Editing the design reference (`design/`) — regenerated by the design team.
+
+### 2.8 User roles & journeys
+
+Authorization is enforced server-side on **6 canonical roles**; the header's
+**9 identities** are cosmetic (they change the visible nav, not access). Each
+role's primary journey is captured as a flow diagram in the flow package
+(`SoW/flows/user-*`, rendered in `SoW/images/` and the gallery).
+
+| Role (enforced) | Header identity(ies) | Primary journeys | Flow |
+|---|---|---|---|
+| **Platform Admin** | Platform Admin | Administration — RBAC matrix, backups/restore, audit log, AD sync, deletion requests | `user-09` |
+| **PMO** | PMO | Triage & approve demands; portfolio oversight | `user-02` (+ `user-01`) |
+| **Project Manager** | PM (· PM Lead / delivery leads) | Create project (wizard); manage tasks & Jira sync; request a stage-gate review | `user-03`, `user-04`, `user-05` |
+| **Team Member** | Engineering / Service / Dev / Infra Manager (& members) | Update my work; My Team — skills, SWOT, development plans | `user-06`, `user-08` |
+| **Executive** | (leadership) | Portfolio review | `user-01` |
+| **Stakeholder** | Stakeholder | Check my projects / demands / delivery (reduced nav) | `user-07` |
+| **Architecture** | Chief Architect | Governance — ADR log, architecture gate reviews, TOGAF ADM, ISO 27001 SoA | `user-10` |
+
+The four **Manager** identities (Engineering / Service / Dev / Infra) differ only
+cosmetically and share the Team Member / *My Team* journeys. Beyond these
+role journeys, the flow package also documents **system & data flows** (20) and
+**software-development interaction flows** (9) — see `SoW/flows.md` and the
+gallery.
+
+---
+
+## 3. Deliverables
+
+1. The complete, prototype-faithful Atlas PPM **frontend** (React 18 + TS +
+ Vite), one screen component per route, split into local sub-components.
+2. The supporting **.NET 10 minimal API** endpoints each screen consumes
+ (extended where a screen needs an endpoint not yet present), EF Core 10 /
+ PostgreSQL 16.
+3. **Entra SSO** wiring (login/redirect handling, route guards) and the RBAC
+ capability matrix.
+4. **Generated API types** + `api.ts` client; TanStack Query hooks with
+ loading/empty/error states.
+5. **Automated test suites** — backend (xUnit, incl. fixtures + architecture
+ boundary tests), frontend (Vitest), accessibility (Playwright + axe),
+ performance (k6) — all gated in CI with coverage floors.
+6. **Flow diagrams** (`SoW/flows`) — 39 diagrams in three views: system & data
+ flows (20), per-role user journeys (10), and software-development interaction
+ flows (9), with rendered images and an index/gallery.
+7. **Architecture Decision Records** for every architectural choice, plus a
+ consolidated `ALL-ADRS.md`.
+8. **Deployment artefacts** for the air-gapped Windows on-prem target
+ (self-contained build output, nginx config, setup/integration guides).
+
+---
+
+## 4. Approach & methodology
+
+- **Prototype is the source of truth.** Inline styles lifted from the prototype;
+ `theme.ts` tokens and the three fonts only; computed visuals (charts, donuts,
+ sparklines, gantt geometry) ported faithfully.
+- **Empty by default.** Real layout with tasteful empty states until the API
+ returns data; never fabricated seed data.
+- **Server-authoritative security.** The API is the authority for authorization;
+ UI role checks are cosmetic affordances only.
+- **Typed, tested, accessible.** TypeScript strict; generated API types;
+ ≥44px hit targets, real controls, focus styles, `aria-*`; every data view has
+ loading/empty/error.
+- **Build one screen fully** (visually faithful + data-wired + empty state)
+ before the next; compare side-by-side with the prototype.
+- **ADR-driven + one-change-one-PR**, each verified green in CI before merge.
+
+---
+
+## 5. Technical architecture
+
+| Layer | Technology |
+|---|---|
+| Frontend | React 18, TypeScript (strict), Vite, react-router v6, TanStack Query, @azure/msal-browser, SignalR client |
+| Styling | Inline styles + `theme.ts` tokens (CSS-variable themes; 5 palettes); self-hosted fonts |
+| Backend | .NET 10 minimal API, modular monolith (per-domain `Atlas.Api.`), EF Core 10 |
+| Data | PostgreSQL 16 (`date`/`timestamptz` typed dates per ADR-0082) |
+| Realtime | SignalR "room" hub (presence, cursors, live sync) |
+| Serving | nginx, same-origin, `/api/v1/*`; on-prem air-gapped |
+| Quality gates | Module-boundary ratchet (NetArchTest), coverage floors, OpenAPI type-contract drift, axe a11y, Semgrep/Trivy |
+
+---
+
+## 6. Milestones (build order)
+
+| # | Phase | Contents |
+|---|---|---|
+| M1 | Dashboard | Executive layout first (tokens, cards, charts, tables), then Operational/Compact/Custom |
+| M2 | Core object | Portfolio (+ Blockers) and Project Detail drill-in |
+| M3 | Flow & time | Demands funnel, Gantt timeline |
+| M4 | Portfolio breadth | Programs, Products, OKRs, Resources, Financials |
+| M5 | Reporting | Delivery Status, Releases, News |
+| M6 | Configuration | Methodologies (+ wizard), Integrations, Reports, Admin, Help |
+| M7 | Stakeholder | My Projects / My Demands + role-based nav & affordances |
+| M8 | Governance | Gates, decisions, TOGAF ADM, security/compliance |
+| M9 | Platform hardening | Entra SSO, real API wiring, loading/empty/error finalisation, air-gapped packaging |
+
+*Milestones are delivery groupings, not a fixed calendar; sequencing may be
+reprioritised with the product owner.*
+
+---
+
+## 7. Acceptance criteria
+
+- **Visual fidelity**: each screen matches the prototype 1:1 on side-by-side
+ review (layout, spacing, type, colour, components, states, copy).
+- **Data-wired**: every view reads real data via TanStack Query with
+ loading/empty/error states; empty by default.
+- **Security**: authorization enforced server-side; verified by backend tests.
+- **Accessibility**: axe sweep passes (structural); WCAG AA colour contrast on
+ all themes.
+- **Quality gates green**: frontend + backend suites, coverage floors, OpenAPI
+ contract-drift, module-boundary ratchet, SAST/Trivy.
+- **Deployable**: a clean build runs on the air-gapped Windows target from the
+ provided artefacts.
+
+---
+
+## 8. Assumptions & constraints
+
+- **On-prem, air-gapped**: no runtime internet egress; all fonts/assets
+ self-hosted (ADR-0078); dev-only tooling runs in CI, never ships.
+- **Deployment**: client downloads built files to a Windows server; no git on
+ target — artefacts must be self-contained.
+- **Identity**: Entra ID (Azure AD) tenant available for SSO; directory sync for
+ Resources.
+- **Prototype freeze**: `design/Atlas PPM.dc.html` is authoritative and not
+ edited; approved deviations recorded in `CLAUDE.md §2` + an ADR, and flagged
+ for the design team to regenerate `design/`.
+- **Roles**: six canonical backend roles enforce access; the nine-identity
+ header switcher is cosmetic.
+
+---
+
+## 9. Roles & responsibilities
+
+| Party | Responsibility |
+|---|---|
+| Engineering (delivery) | Frontend + API implementation, tests, ADRs, CI, deployment artefacts |
+| Product Owner (Birgma) | Prototype sign-off, approval of extensions & Proposed ADRs, milestone prioritisation |
+| Design team | Own `design/`; regenerate to reflect approved extensions |
+| Platform / IT (Birgma) | Entra tenant, on-prem/nginx environment, DB provisioning, deploy windows |
+| Security / Compliance | DPIA / MBL §11 sign-off for personnel-data features; governance module review |
+
+---
+
+## 10. Non-functional requirements
+
+- **Accessibility** — WCAG AA; keyboard + AT support; axe-gated in CI.
+- **Internationalisation** — six-locale chrome catalogue (en/sv/fi/da/no/fr) +
+ completeness test; English screen content (ADR-0084).
+- **Security & compliance** — RBAC capability matrix; GDPR/ISO 27001/PCI-DSS/EU
+ AI Act/SOC 2/NIS2 modules; audit trail; secret rotation; CSP + TLS hardening.
+- **Performance** — k6 performance budget; time-phased resource engine shared
+ across roster/report/export to prevent drift.
+- **Observability** — OpenTelemetry traces/metrics/logs (OTLP, opt-in).
+- **Data integrity** — typed dates (`date`/`timestamptz`); no display-string
+ date columns (ADR-0082).
+
+---
+
+## 11. Risks & dependencies
+
+| Risk / dependency | Mitigation |
+|---|---|
+| Prototype fidelity disputes | Side-by-side review as an explicit acceptance gate |
+| Air-gapped runtime (no CDNs) | Self-host all assets; verify offline build |
+| Entra tenant / directory access | Confirm tenant + app registration early (M9 depends on it) |
+| Personnel-data features (SWOT / dev plans) | Gated off until DPIA + MBL §11 sign-off (ADR-0063) |
+| External connector availability (Jira/ADO/etc.) | Empty/degraded states; connectors dormant until configured |
+| Compliance-module accuracy | Review with Security/Compliance before acceptance |
+
+---
+
+## 12. Commercials & timeline
+
+> **To be completed by the parties.** The Atlas engineering scope, milestones and
+> acceptance are fixed by this document; pricing, rates and calendar dates are
+> commercial terms to be agreed and filled in before signature.
+
+| Term | Value |
+|---|---|
+| Pricing model | ‹fixed-price / capped T&M / T&M — to be agreed› |
+| Total price / not-to-exceed | ‹to be agreed› |
+| Rate card (if T&M) | ‹to be agreed› |
+| Estimated effort | ‹to be agreed› |
+| Payment schedule | On acceptance of each milestone (M1–M9, §6) · ‹split % to be agreed› |
+| Expenses & travel | ‹to be agreed› |
+| Start date | ‹TBD› |
+| Target completion | ‹TBD› (milestone dates per §6) |
+| Warranty / support | ‹to be agreed› |
+| Governing agreement | This SoW is issued under ‹MSA / framework agreement ref — TBD› |
+
+Change control: any change to the fixed scope (§2) is handled by a written
+change request priced against the agreed model before work proceeds.
+
+## 13. Acceptance & sign-off
+
+Work is accepted milestone-by-milestone against the criteria in §7. This
+Statement of Work is agreed and authorised by the undersigned.
+
+**For Birgma / Biltema Group (Client)**
+
+| | |
+|---|---|
+| Name | ______________________________ |
+| Title | ______________________________ |
+| Signature | ______________________________ |
+| Date | ______________________________ |
+
+**For the Supplier** — ‹supplier legal name — TBD›
+
+| | |
+|---|---|
+| Name | ______________________________ |
+| Title | ______________________________ |
+| Signature | ______________________________ |
+| Date | ______________________________ |
+
+Effective date: ‹on last signature› · SoW version: v1.0 (draft) · Supersedes: ‹none / prior version›
+
+---
+
+*Companion document: a separate SoW covers the **code-review remediation
+engagement** (Epic #106) — security hardening, structural refactors, and the
+ADRs 0080–0084 — with per-item delivery status.*
+
+*The 39 flow diagrams (system · user journeys · development) are embedded in the
+HTML edition and indexed in `flows.md`; the HTML edition is the self-contained,
+signable version.*
diff --git a/SoW/SoW-Atlas-PPM-Remediation.md b/SoW/SoW-Atlas-PPM-Remediation.md
new file mode 100644
index 0000000..ddf28e4
--- /dev/null
+++ b/SoW/SoW-Atlas-PPM-Remediation.md
@@ -0,0 +1,198 @@
+# Statement of Work — Atlas PPM Code-Review Remediation
+
+| Field | Value |
+|---|---|
+| **Project** | Atlas PPM — Code-Review Remediation (Epic #106) |
+| **System** | Atlas — Portfolio & Project Management web app (React/TS + .NET 10 minimal API, PostgreSQL 16) |
+| **Client** | Birgma / Biltema Group |
+| **Repository** | `nicpozent/ATLASPPM_AdditionalFeatures` |
+| **Prepared for** | nicolas.pozza@birgma.com |
+| **Date** | 2026-08-07 |
+| **Status** | In progress — the majority of scope delivered; remainder tracked below |
+
+---
+
+## 1. Background & objectives
+
+A structured code review of the Atlas PPM codebase produced a remediation
+backlog (findings **R1–R19**, organised into six waves in Epic #106). The
+objective of this engagement is to resolve those findings — closing security
+gaps, removing structural drift, and recording the architectural decisions —
+**without changing product behaviour or the approved visual prototype**, and
+while keeping the build continuously green.
+
+Guiding principles applied throughout:
+
+- **One finding → one pull request**, each rebased to a single clean commit.
+- **Server-authoritative decisions recorded as ADRs** (Architecture Decision
+ Records) before or alongside the code.
+- **Test-gated**: every change verified by the full automated suite before merge.
+- **No behaviour or visual regression**; inline-styled theme tokens only.
+
+---
+
+## 2. Scope of work
+
+### 2.1 In scope — by wave
+
+| Wave | Findings | Theme |
+|---|---|---|
+| 1 | R1–R5 | Security gate hoist & connector logging; frontend error-surface hardening; docs/config accuracy |
+| 2–3 | R6–R10 | Coverage measurement + floors; ESLint ratchets; server module-folder materialisation; single `Auth:Enabled` reader; entity-hue palette unification |
+| 4 | R11–R13 | Generated API type contract; whiteboard shape registry; tab/layout registries |
+| 5 | R14–R16 | Dates-as-real-types ADR; one connector abstraction; i18n-scope ADR |
+| 6 | R17–R18 | Comment cleanup (why-not-what); god-object file splits |
+| — | R19 | Watch-only (no action) |
+
+### 2.2 Out of scope
+
+- New product features or screens beyond the approved prototype (except
+ product-owner-approved extensions already recorded in `CLAUDE.md §2`).
+- Redesign or restyling of any existing screen.
+- Jira **bidirectional write-back** — captured as a *Proposed* decision
+ (ADR-0080) awaiting product-owner sign-off; **not** implemented.
+- Full screen-body internationalisation (deliberately deferred — see ADR-0084).
+- Data migrations for legacy display-string date columns — planned per-module
+ under ADR-0082 but not executed in this engagement.
+- Any change to the client as a security control (authorization stays
+ server-authoritative).
+
+---
+
+## 3. Deliverables & status
+
+### 3.1 Security hardening
+| Deliverable | Status |
+|---|---|
+| Authorization gaps closed (H1/H2/M1/M2/M3 + follow-up sweep of ~10 further read/write endpoints) | ✅ Delivered |
+| CSP (M4) + all LOW findings + by-id ownership authorization | ✅ Delivered |
+| nginx CSP + cipher hardening; Jira attachment SSRF guard; backup-webhook validation | ✅ Delivered |
+| GitHub Actions pinned to commit SHAs; Dependabot for actions | ✅ Delivered |
+
+### 3.2 Engineering quality & CI gates
+| Deliverable | Status |
+|---|---|
+| Backend coverage measurement (coverlet) + CI floor (65% line) | ✅ Delivered |
+| Frontend coverage measurement (v8) + CI floor (6% line) | ✅ Delivered |
+| ESLint ratchets: `max-lines`, `max-lines-per-function`, literal-hex-colour ban | ✅ Delivered |
+| Module-boundary ratchet (ADR-0072, NetArchTest) enforced in CI | ✅ Delivered (pre-existing, respected) |
+| **Generated API type contract** (OpenAPI → `src/api/generated.ts`) + CI drift job (R11) | ✅ Delivered — ADR-0081 |
+
+### 3.3 Structural refactors
+| Deliverable | Status |
+|---|---|
+| Whiteboard shape registry + client/server drift guard (R12) | ✅ Delivered (metadata half; render unification tracked in #98) |
+| Server module-folder layout + `Auth:Enabled` single reader (R8/R9) | ✅ Delivered |
+| Entity-hue palette unification (R10 stage A) | ✅ Delivered |
+| Project/Dashboard tab & layout registries (R13) | ✅ Delivered |
+| **One work-item connector abstraction** (Jira + Azure DevOps → `IWorkItemConnector` + generic queue/worker) (R15) | ✅ Delivered — ADR-0083 |
+| Comment cleanup — delete restatement, keep rationale (R17) | ✅ Delivered |
+| God-object split: `WriteEndpoints.cs` (805 → 83-line composer + 7 files) (R18 pt 1) | ✅ Delivered |
+
+### 3.4 Architecture Decision Records
+| ADR | Subject | Status |
+|---|---|---|
+| ADR-0080 | Jira bidirectional write-back | **Proposed** (awaiting PO decision) |
+| ADR-0081 | Generated API type contract | Accepted |
+| ADR-0082 | Persist dates as real `date`/`timestamptz` | Proposed (ADR only; migration staged) |
+| ADR-0083 | One work-item connector abstraction | Accepted |
+| ADR-0084 | i18n scope: localised chrome, English content | Accepted |
+| — | Consolidated `ALL-ADRS.md` (84 ADRs) + generator, CI staleness check | ✅ Delivered |
+
+### 3.5 Verification assets
+- Backend: **507** xUnit tests (incl. fixture-based connector sync tests + a
+ client/server drift guard). ✅
+- Frontend: **145** Vitest tests. ✅
+- Playwright + axe accessibility sweep; Semgrep (SAST), Trivy (deps/secrets/IaC)
+ security jobs — all green in CI. ✅
+
+---
+
+## 4. Remaining scope (tracked, open)
+
+| Item | Description | Why not in this pass |
+|---|---|---|
+| #98 | Whiteboard render/glyph/SVG unification | Interaction-coupled; needs in-app visual verification |
+| #104 (frontend) | Split `Gantt.tsx`, `Admin.tsx`, `Pip.tsx`, and folder-less screens | Needs in-app visual-regression checking; one PR each |
+| #104 (backend) | Split `Dtos.cs` (per-module — surfaces hidden coupling to the boundary ratchet) and `Teams.cs` | Sequenced after the frontend splits |
+| #90 (R4 tail) | Adopt shared `QueryState` in ~34 more screens | Incremental, one batch per screen group |
+| #96 (R10 tail) | Sweep remaining ~442 literal hex colours; flip lint rule to error | Incremental |
+| ADR-0082 migrations | Per-module date-column migrations (`Demand.Date` first) | Deliberately staged; needs a migration window |
+
+---
+
+## 5. Approach & methodology
+
+1. **Analyse first** — measure the finding against current code (facts, not the
+ original ticket text, which may predate other merges).
+2. **Decide & record** — where architectural, an ADR precedes or accompanies the
+ code; the developer-facing rule goes into `CLAUDE.md`.
+3. **Implement** on the designated feature branch, behaviour-preserving.
+4. **Verify** — full backend + frontend suites, build, lint, coverage floors,
+ contract-drift and boundary ratchets — locally and in CI.
+5. **One issue → one PR**, squash-merged after all required CI checks pass.
+
+---
+
+## 6. Acceptance criteria
+
+- All required CI checks green on each PR: frontend (lint/test/build), backend
+ (build/test), API-type-contract drift, accessibility (axe), SAST/Trivy,
+ coverage floors.
+- No regression in the 507 backend / 145 frontend tests.
+- Each finding's issue closed with a summary comment, or explicitly left open
+ with the remaining scope documented.
+- Architectural changes recorded as an Accepted ADR (or Proposed where PO
+ sign-off is required).
+
+> Note: the `github-advanced-security` (Copilot Autofix) check is an external
+> service that intermittently errors independently of the code; it is **not** a
+> gating check for this engagement, per client direction.
+
+---
+
+## 7. Assumptions & constraints
+
+- **On-prem, air-gapped deployment**: no internet egress at runtime; all fonts
+ and assets self-hosted/bundled (ADR-0078). Build-time dev tooling
+ (e.g. `openapi-typescript`) runs in CI only, never ships.
+- **Deployment model**: the client deploys by downloading built files to a
+ Windows server; there is no git on the target. Changes therefore must be
+ self-contained and reproducible from the repo.
+- The approved prototype (`design/Atlas PPM.dc.html`) is the visual source of
+ truth and is not edited; product-owner-approved deviations are recorded in
+ `CLAUDE.md §2` + an ADR.
+- Six canonical backend roles enforce authorization; the 9-identity header
+ switcher is cosmetic.
+
+---
+
+## 8. Roles & responsibilities
+
+| Party | Responsibility |
+|---|---|
+| Engineering (delivery) | Analysis, implementation, tests, ADRs, PRs, CI verification |
+| Product Owner (Birgma) | Sign-off on *Proposed* ADRs (0080 Jira write-back; 0082 date migrations); prioritisation of remaining #104/#90/#96 work |
+| Design team | Regenerate `design/` to reflect approved extensions (tracked, external to this engagement) |
+| Platform/Ops | Provide a migration window for the ADR-0082 date-column migrations when scheduled |
+
+---
+
+## 9. Risks & dependencies
+
+- **Visual-regression risk** on the remaining frontend god-object splits (#104)
+ — mitigated by requiring in-app verification before those PRs merge.
+- **Data-migration risk** (ADR-0082) — `Demand.Date` back-fill must infer a
+ missing year; requires a migration window and is called out per-PR.
+- **Dependency**: R18 backend `Dtos.cs` split may *surface* (not create) latent
+ cross-module coupling once DTOs move into module namespaces — expected and
+ desirable, but may require follow-up boundary fixes.
+- Jira write-back (ADR-0080) reverses a foundational pull-only decision and must
+ not be implemented until it graduates to *Accepted*.
+
+---
+
+*This SoW describes the Atlas PPM code-review remediation engagement (Epic
+#106). If a Statement of Work for the broader Atlas PPM product build (all
+screens, integrations, and governance modules) is what's needed instead, that
+can be produced as a separate document.*
diff --git a/SoW/flows-gallery.html b/SoW/flows-gallery.html
new file mode 100644
index 0000000..1d01206
--- /dev/null
+++ b/SoW/flows-gallery.html
@@ -0,0 +1,26 @@
+
+
Atlas PPM · Statement of Work
Functional Flows
+
Three views of Atlas PPM — how the system moves data, how users (per role) get work done, and how the engineering pieces interact at build, run and deploy.
+
SystemSystem & data flows
00 Application map & navigation
01 Authentication & RBAC gate
02 Dashboard — layout switching & data
03 Demand intake → scoring → approval funnel
04 Portfolio → Project drill-in
05 Project stage gates (G0–G5) & reviews
06 Task board move — realtime, cap-schedule
07 Timeline / Gantt & cross-entity dependencies
08 Resource utilisation & capacity
09 Financials roll-up → portfolio ROI
10 Program detail — stakeholder matrix
11 Products → Releases → deployment
12 OKRs — objectives, key results, linkage
13 Delivery status reporting by period
14 Weekly news wall (edit / view)
15 Connector sync (Jira / Azure DevOps)
16 Whiteboard live co-editing
17 Reports & export
18 Administration
19 Governance & compliance
UserUser journeys
01 Executive — portfolio review
02 PMO — triage & approve a demand
03 PM — create a project (wizard)
04 PM — manage tasks & Jira sync
05 PM — request a stage-gate review
06 Team member — update my work
07 Stakeholder — check my status
08 Manager — My Team (skills · SWOT · dev plan)
09 Platform Admin — administration
10 Chief Architect — governance
DevSoftware-development interaction
01 Change lifecycle — issue → PR → merge
02 CI pipeline — the gating jobs
03 API type contract (OpenAPI → TS) + drift guard
04 Module-boundary ratchet (ADR-0072)
05 Test strategy — unit → integration → e2e → perf
06 Local dev loop (auth on/off)
07 Build & air-gapped deploy
08 Runtime topology (component interaction)
09 Extending a connector (IWorkItemConnector)
\ No newline at end of file
diff --git a/SoW/flows.md b/SoW/flows.md
new file mode 100644
index 0000000..912715c
--- /dev/null
+++ b/SoW/flows.md
@@ -0,0 +1,787 @@
+# Atlas PPM — Functional Flows
+
+Flow diagrams in three views: **system & data flows**, **user journeys** (persona → goal), and **software-development interaction**. Each entry shows live Mermaid + a static PNG in `images/`.
+
+
+## System & data flows
+
+- [Application map & navigation](#00-app-sitemap)
+- [Authentication & RBAC gate](#01-auth-rbac)
+- [Dashboard — layout switching & data](#02-dashboard)
+- [Demand intake → scoring → approval funnel](#03-demands)
+- [Portfolio → Project drill-in](#04-portfolio-project)
+- [Project stage gates (G0–G5) & reviews](#05-project-gates)
+- [Task board move — realtime, cap-schedule](#06-tasks-board)
+- [Timeline / Gantt & cross-entity dependencies](#07-gantt)
+- [Resource utilisation & capacity](#08-resources)
+- [Financials roll-up → portfolio ROI](#09-financials)
+- [Program detail — stakeholder matrix](#10-programs)
+- [Products → Releases → deployment](#11-products-releases)
+- [OKRs — objectives, key results, linkage](#12-okrs)
+- [Delivery status reporting by period](#13-delivery)
+- [Weekly news wall (edit / view)](#14-news)
+- [Connector sync (Jira / Azure DevOps)](#15-integrations-sync)
+- [Whiteboard live co-editing](#16-whiteboard)
+- [Reports & export](#17-reports)
+- [Administration](#18-admin)
+- [Governance & compliance](#19-governance-compliance)
+
+
+## User journeys
+
+- [Executive — portfolio review](#user-01-executive-review)
+- [PMO — triage & approve a demand](#user-02-pmo-demand-approval)
+- [PM — create a project (wizard)](#user-03-pm-create-project)
+- [PM — manage tasks & Jira sync](#user-04-pm-manage-tasks)
+- [PM — request a stage-gate review](#user-05-pm-stage-gate)
+- [Team member — update my work](#user-06-team-member-update)
+- [Stakeholder — check my status](#user-07-stakeholder-status)
+- [Manager — My Team (skills · SWOT · dev plan)](#user-08-manager-team)
+- [Platform Admin — administration](#user-09-platform-admin)
+- [Chief Architect — governance](#user-10-architect-governance)
+
+
+## Software-development interaction
+
+- [Change lifecycle — issue → PR → merge](#dev-01-change-lifecycle)
+- [CI pipeline — the gating jobs](#dev-02-ci-pipeline)
+- [API type contract (OpenAPI → TS) + drift guard](#dev-03-api-type-contract)
+- [Module-boundary ratchet (ADR-0072)](#dev-04-module-boundary)
+- [Test strategy — unit → integration → e2e → perf](#dev-05-test-strategy)
+- [Local dev loop (auth on/off)](#dev-06-local-dev)
+- [Build & air-gapped deploy](#dev-07-build-deploy)
+- [Runtime topology (component interaction)](#dev-08-runtime-topology)
+- [Extending a connector (IWorkItemConnector)](#dev-09-connector-extension)
+
+
+---
+
+# System & data flows
+
+
+
+
+## Application map & navigation
+
+
+
+```mermaid
+graph LR
+ ATLAS(["Atlas PPM"]):::start
+ ATLAS --> WS["Workspace"]
+ ATLAS --> CFG["Configuration"]
+ ATLAS --> STK["Stakeholder"]
+ WS --> W1["Dashboard · Portfolio · Programs Products · OKRs · Demands · Timeline"]
+ WS --> W2["Project Detail · Resources · Financials Delivery · Releases · News"]
+ CFG --> C1["My Team · Methodologies · Integrations Reports · Administration · Help"]
+ STK --> S1["My Projects · My Demands Delivery · Releases · News · Help"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Authentication & RBAC gate
+
+
+
+```mermaid
+graph TD
+ U(["User opens Atlas"]):::start --> A{"VITE_AUTH_ENABLED?"}
+ A -- "No (dev)" --> DEV["Anonymous mode X-Atlas-Role header"]
+ A -- "Yes" --> MSAL["MSAL redirect → Entra ID"]
+ MSAL --> TOK["Bearer token"]
+ DEV --> API["Call /api/v1/* "]
+ TOK --> API
+ API --> RBAC{"Server RBAC capability check"}
+ RBAC -- allow --> OK(["200 + data"]):::start
+ RBAC -- deny --> F["403 Forbidden"]:::deny
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## Dashboard — layout switching & data
+
+
+
+```mermaid
+graph LR
+ N(["Open Dashboard"]):::start --> L{"Layout"}
+ L --> E["Executive"]
+ L --> O["Operational"]
+ L --> C["Compact"]
+ L --> CU["Custom builder drag/add/remove widgets"]
+ E --> Q["useDashboard() query"]
+ O --> Q
+ C --> Q
+ CU --> Q
+ Q --> D{"Data?"}
+ D -- yes --> R["KPIs · charts · tables · pipeline"]
+ D -- empty --> Z["Zeroed KPIs · empty panels"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Demand intake → scoring → approval funnel
+
+
+
+```mermaid
+graph TD
+ C(["Create demand"]):::start --> SC["Score: value + effort (1–5)"]
+ SC --> DR["Draft"]
+ DR --> BK["Backlog"]
+ BK -->|"drag card (live funnel)"| AP{"Approve? governance-gated"}
+ AP -- approved --> PG["In progress"]
+ AP -- hold --> HD["Hold"]
+ PG --> CV["Converted to project"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Portfolio → Project drill-in
+
+
+
+```mermaid
+graph LR
+ P(["Portfolio"]):::start --> T{"Sub-tab"}
+ T --> PJ["Projects filter chips · cards/table"]
+ T --> BK["Blockers list + side panel"]
+ PJ -->|"click project"| PD(["Project Detail"]):::start
+ PD --> TABS["Overview · Tasks · Epics · RAID Artifacts · Costs · Gates · Security"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Project stage gates (G0–G5) & reviews
+
+
+
+```mermaid
+graph LR
+ G0["G0 Concept"] --> G1["G1 Initiate"] --> G2["G2 Plan"] --> G3["G3 Build"] --> G4["G4 Deploy"] --> G5["G5 Close"]
+ R{"Gate review cap-approve"}:::gate
+ G1 -.-> R
+ G3 -.-> R
+ R -- pass --> ADV["Advance to next gate"]
+ R -- fail --> REM["Remediate / hold"]:::deny
+ classDef gate fill:#fff6e6,stroke:#a9791a,color:#5a3d00;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## Task board move — realtime, cap-schedule
+
+
+
+```mermaid
+graph TD
+ U(["Planner drags task card"]):::start --> CAP{"cap-schedule? Admin · PMO · PM · PM Lead"}
+ CAP -- no --> DENY["403 — status change denied"]:::deny
+ CAP -- yes --> MV["PATCH task status"]
+ MV --> HUB["SignalR room tasks:{projectId}"]
+ HUB --> PEERS["Card moves live for every viewer"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## Timeline / Gantt & cross-entity dependencies
+
+
+
+```mermaid
+graph LR
+ SC{"Scope"} --> PJ["Project"]
+ SC --> PG["Program"]
+ PJ --> T["Timeline: phases · bars · milestones"]
+ PG --> T
+ T --> DEP["Finish→Start dependency arrows"]
+ DEP --> S{"source"}
+ S --> M["manual (hand-drawn, cap-projects)"]
+ S --> J["jira (issue-link ingest)"]
+ S --> PL["project links (auto)"]
+```
+
+
+
+
+## Resource utilisation & capacity
+
+
+
+```mermaid
+graph TD
+ R(["Resources roster synced from Entra ID"]):::start --> W{"Period window"}
+ W --> WIN["day/week/month/quarter/half/year or custom date range"]
+ WIN --> ENG["Shared time-phased engine"]
+ ENG --> UT["Avg utilisation = Ops + Project + Product"]
+ UT --> OV{"over 100%?"}
+ OV -- yes --> FLAG["Over-allocation → resource risk"]:::deny
+ OV -- no --> OK["Within capacity"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## Financials roll-up → portfolio ROI
+
+
+
+```mermaid
+graph LR
+ SRC{"Source toggle"} --> BUD["Budget vs Actual"]
+ BUD --> SP["CapEx / OpEx split"]
+ SP --> FAC["Forecast at completion"]
+ FAC --> BEN["Savings / benefit"]
+ BEN --> ROI(["Portfolio ROI"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Program detail — stakeholder matrix
+
+
+
+```mermaid
+graph TD
+ PG(["Program detail"]):::start --> MTX["Stakeholder power/interest matrix"]
+ PG --> LP["Linked projects — roll-up status"]
+ PG --> SY["Sync from Jira (cap-projects E)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Products → Releases → deployment
+
+
+
+```mermaid
+graph LR
+ PRD(["Product"]):::start --> MAP["Jira / ADO tasks mapped"]
+ MAP --> REL["Releases"]
+ REL --> CAL["Release calendar"]
+ CAL --> DEP["Deployment tracking"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## OKRs — objectives, key results, linkage
+
+
+
+```mermaid
+graph TD
+ O(["Objective"]):::start --> KR["Key results"]
+ KR --> L{"Link target"}
+ L --> P["Project"]
+ L --> PG["Program"]
+ L --> PR["Product"]
+ KR --> PROG["Progress roll-up (0–100%)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Delivery status reporting by period
+
+
+
+```mermaid
+graph LR
+ PER{"Period weekly → yearly"} --> AGG["Completed · in-progress · planned"]
+ AGG --> VEL["Velocity + on-time %"]
+ AGG --> BLK["Blockers"]
+ AGG --> BURN["Budget burn"]
+ VEL --> RPT(["Stakeholder delivery report"]):::start
+ BLK --> RPT
+ BURN --> RPT
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Weekly news wall (edit / view)
+
+
+
+```mermaid
+graph TD
+ ED{"Edit mode?"} -- yes --> BLK["Add blocks: headline · metric · shout-out image · milestone · doc"]
+ BLK --> SAVE["Save news wall"]
+ ED -- no --> VIEW(["Masonry news wall (themed)"]):::start
+ SAVE --> VIEW
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Connector sync (Jira / Azure DevOps)
+
+
+
+```mermaid
+sequenceDiagram
+ autonumber
+ actor U as PM · cap-projects E
+ participant API as Atlas API
+ participant Q as SyncQueue⟨T⟩
+ participant W as SyncWorker⟨T⟩
+ participant C as IWorkItemConnector
+ participant EX as Jira / Azure DevOps
+ U->>API: POST /projects/{id}/{conn}/sync?background=true
+ API->>API: gate cap-projects E
+ API->>Q: enqueue job
+ API-->>U: 202 Accepted + jobId
+ W->>C: SyncCoreAsync(targets, delta)
+ C->>EX: pull issues (delta watermark, ISO)
+ EX-->>C: work items
+ C->>API: upsert projects / sprints / epics / tasks
+ W->>API: write audit event
+ U->>API: GET .../sync/status/{jobId}
+ API-->>U: status = done (counts)
+```
+
+
+
+
+## Whiteboard live co-editing
+
+
+
+```mermaid
+graph TD
+ U(["User edits node / edge"]):::start --> OP["Authorized op scope-gated by entity capability"]
+ OP --> SAN["Server sanitises + persists typed row"]
+ SAN --> HUB["Room hub broadcast"]
+ HUB --> PEERS["Live co-edit: presence · cursors field-merge · off-screen peers"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Reports & export
+
+
+
+```mermaid
+graph LR
+ SEL(["Select report portfolio · demand · blocker · audit"]):::start --> BR["Apply branding"]
+ BR --> F{"Export format"}
+ F --> PDF["PDF"]
+ F --> XL["Excel"]
+ F --> PP["PPTX"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Administration
+
+
+
+```mermaid
+graph TD
+ A(["Administration"]):::start --> RBAC["Roles & permissions matrix"]
+ A --> BK["Backups / restore (validated)"]
+ A --> AUD["Audit log"]
+ A --> SY["AD directory sync"]
+ A --> DEL["Deletion requests (GDPR)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Governance & compliance
+
+
+
+```mermaid
+graph TD
+ GOV(["Governance & compliance"]):::start --> SOA["ISO 27001 SoA — 93 Annex A controls"]
+ GOV --> ADR["Decision log (ADR)"]
+ GOV --> TG["TOGAF ADM phases · ARB · waivers"]
+ GOV --> SEC["GDPR · PCI-DSS · EU AI Act · SOC 2 · NIS2"]
+ SOA --> COV["Coverage roll-up"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+---
+
+# User journeys
+
+
+
+
+## Executive — portfolio review
+
+
+
+```mermaid
+graph LR
+ U(["Executive"]):::start --> A["Open Dashboard → Executive layout"]
+ A --> B["Scan portfolio-health donut + KPI cards"]
+ B --> C{"Anything needs attention?"}
+ C -- yes --> D["Open a 'needs attention' project"]
+ D --> E["Read status · budget burn · blockers"]
+ C -- no --> F["Review demand pipeline + recent activity"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## PMO — triage & approve a demand
+
+
+
+```mermaid
+graph LR
+ U(["PMO"]):::start --> A["Open Demands funnel"]
+ A --> B["Review a scored demand (value vs effort)"]
+ B --> C{"Approve?"}
+ C -- yes --> D["Drag card to Approved → confirm"]
+ D --> E["Demand becomes project intake"]
+ C -- no --> F["Move to Hold · add comment"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## PM — create a project (wizard)
+
+
+
+```mermaid
+graph LR
+ U(["Project Manager"]):::start --> A["Methodologies → Create project"]
+ A --> B["Step 1 · pick methodology"]
+ B --> C["Step 2 · name · department · owner"]
+ C --> D["Step 3 · choose integration (Jira / ADO / none)"]
+ D --> E(["Project created → opens Project Detail"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## PM — manage tasks & Jira sync
+
+
+
+```mermaid
+graph LR
+ U(["Project Manager"]):::start --> A["Project → Tasks (board)"]
+ A --> B["Drag a card between columns"]
+ B --> C["Status updates live for the team"]
+ A --> D["Sync from Jira (pull latest)"]
+ D --> E["Board reflects imported issues"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## PM — request a stage-gate review
+
+
+
+```mermaid
+graph LR
+ U(["Project Manager"]):::start --> A["Project → Gates (G0–G5)"]
+ A --> B["Prepare gate evidence / checklist"]
+ B --> C["Request gate review"]
+ C --> D{"Reviewer decision"}
+ D -- pass --> E["Advance to next gate"]
+ D -- fail --> F["Remediate and resubmit"]:::deny
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## Team member — update my work
+
+
+
+```mermaid
+graph LR
+ U(["Team member"]):::start --> A["Dashboard → Operational → My tasks"]
+ A --> B["Open a task"]
+ B --> C["Update status · progress · notes"]
+ C --> D["Saved → rolls up to project + delivery"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Stakeholder — check my status
+
+
+
+```mermaid
+graph LR
+ U(["Stakeholder"]):::start --> A["My Projects (reduced nav)"]
+ A --> B["Open a project → read-only status"]
+ B --> C["Check Delivery status + Releases"]
+ C --> D["Read Weekly Updates (News)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Manager — My Team (skills · SWOT · dev plan)
+
+
+
+```mermaid
+graph LR
+ U(["Manager"]):::start --> A["My Team"]
+ A --> B["Review members + skills matrix"]
+ B --> C["Update team SWOT"]
+ B --> D["Record individual development plan (manager-only)"]
+ C --> E["Saved · governance-gated · audited"]
+ D --> E
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Platform Admin — administration
+
+
+
+```mermaid
+graph LR
+ U(["Platform Admin"]):::start --> A["Administration"]
+ A --> B["Roles & permissions matrix"]
+ A --> C["Backups / restore · audit log"]
+ A --> D["AD directory sync · connector config"]
+ A --> E["Review & action deletion requests (GDPR)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Chief Architect — governance
+
+
+
+```mermaid
+graph LR
+ U(["Chief Architect"]):::start --> A["Governance"]
+ A --> B["Decision log — record an ADR"]
+ A --> C["Architecture gate reviews (G1 / G3)"]
+ A --> D["TOGAF ADM · domains · waivers · ARB"]
+ A --> E["Project → Security: ISO 27001 SoA"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+---
+
+# Software-development interaction
+
+
+
+
+## Change lifecycle — issue → PR → merge
+
+
+
+```mermaid
+graph LR
+ I(["Issue / finding"]):::start --> B["Branch (claude/…)"]
+ B --> IMP["Implement · ADR if architectural"]
+ IMP --> PR["Open ONE PR (one issue → one PR)"]
+ PR --> CI{"CI green?"}
+ CI -- no --> FIX["Fix → push"]
+ FIX --> CI
+ CI -- yes --> RV["Review"]
+ RV --> M(["Squash-merge to main"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## CI pipeline — the gating jobs
+
+
+
+```mermaid
+graph TD
+ P(["Push / Pull request"]):::start --> J{"CI jobs — parallel"}
+ J --> FE["Frontend: lint · test · build · coverage floor"]
+ J --> BE["API: build · test · coverage floor"]
+ J --> CT["API type-contract drift"]
+ J --> AX["Accessibility (Playwright + axe)"]
+ J --> SEC["SAST (Semgrep) · Trivy (deps/secrets/IaC)"]
+ FE --> G{"All required green?"}
+ BE --> G
+ CT --> G
+ AX --> G
+ SEC --> G
+ G -- yes --> MG(["Mergeable"]):::start
+ G -- no --> BL["Blocked"]:::deny
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## API type contract (OpenAPI → TS) + drift guard
+
+
+
+```mermaid
+graph LR
+ DTO["Server DTOs · .Produces<T>"] --> DUMP["Boot API (Atlas:SkipDbInit, no DB)"]
+ DUMP --> DOC["openapi/atlas-v1.json"]
+ DOC --> GEN["openapi-typescript"]
+ GEN --> TS["src/api/generated.ts"]
+ TS --> DIFF{"CI: git diff --exit-code"}
+ DIFF -- drift --> FAIL["Fail — run npm run api:types"]:::deny
+ DIFF -- clean --> OK(["Contract in sync"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## Module-boundary ratchet (ADR-0072)
+
+
+
+```mermaid
+graph LR
+ BUILD(["Build + test"]):::start --> ARCH["NetArchTest / Mono.Cecil ratchet (ADR-0072)"]
+ ARCH --> CHK{"Atlas.Api.<Domain> edges legal?"}
+ CHK -- "Integrations reaches a business module" --> FAIL["Build fails"]:::deny
+ CHK -- "leaf boundaries respected" --> OK(["Pass"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
+```
+
+
+
+
+## Test strategy — unit → integration → e2e → perf
+
+
+
+```mermaid
+graph TD
+ U["Unit — xUnit (server) · Vitest (frontend)"] --> I["Integration — WebApplicationFactory (in-memory DB)"]
+ I --> E["E2E — Playwright + axe (empty-state DOM)"]
+ E --> PF["Performance — k6 budget"]
+ PF --> COV(["Coverage floors gated in CI"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Local dev loop (auth on/off)
+
+
+
+```mermaid
+graph LR
+ DEV(["Developer"]):::start --> A["npm install → npm run dev (:5173)"]
+ A --> B{"VITE_AUTH_ENABLED?"}
+ B -- false --> C["Browse every screen → empty states (no backend)"]
+ B -- true --> D["Entra SSO + VITE_API_PROXY → live API"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Build & air-gapped deploy
+
+
+
+```mermaid
+graph LR
+ SRC(["Source"]):::start --> FE["npm run build (tsc + Vite)"]
+ SRC --> BE["dotnet publish"]
+ FE --> ART["Self-contained artefacts (assets bundled)"]
+ BE --> ART
+ ART --> DL["Download to Windows server (no git on target)"]
+ DL --> NG(["nginx same-origin: app · /api/v1 · /hubs"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Runtime topology (component interaction)
+
+
+
+```mermaid
+graph LR
+ BR(["Browser · React SPA"]):::start --> NG["nginx (same-origin)"]
+ NG --> API["Atlas .NET API · /api/v1"]
+ NG --> HUB["SignalR · /hubs (realtime rooms)"]
+ API --> DB[("PostgreSQL 16")]
+ API --> EXT["Connectors: Jira · Azure DevOps · …"]
+ BR -. "MSAL bearer" .-> ENTRA["Entra ID (SSO)"]
+ API -. "validate token" .-> ENTRA
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
+
+
+
+
+## Extending a connector (IWorkItemConnector)
+
+
+
+```mermaid
+graph LR
+ NEW(["New tracker (e.g. ServiceNow)"]):::start --> IMPL["implement IWorkItemConnector"]
+ IMPL --> REG["register in DI: SyncQueue<T> + SyncWorker<T>"]
+ REG --> EP["reuse shared enqueue · 202/poll · gate"]
+ EP --> PARSE["add ONLY connector-specific parsing"]
+ PARSE --> TST(["fixture tests + boundary stays a leaf"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+```
diff --git a/SoW/flows/00-app-sitemap.mmd b/SoW/flows/00-app-sitemap.mmd
new file mode 100644
index 0000000..6a3f6bf
--- /dev/null
+++ b/SoW/flows/00-app-sitemap.mmd
@@ -0,0 +1,10 @@
+graph LR
+ ATLAS(["Atlas PPM"]):::start
+ ATLAS --> WS["Workspace"]
+ ATLAS --> CFG["Configuration"]
+ ATLAS --> STK["Stakeholder"]
+ WS --> W1["Dashboard · Portfolio · Programs Products · OKRs · Demands · Timeline"]
+ WS --> W2["Project Detail · Resources · Financials Delivery · Releases · News"]
+ CFG --> C1["My Team · Methodologies · Integrations Reports · Administration · Help"]
+ STK --> S1["My Projects · My Demands Delivery · Releases · News · Help"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/01-auth-rbac.mmd b/SoW/flows/01-auth-rbac.mmd
new file mode 100644
index 0000000..a21c547
--- /dev/null
+++ b/SoW/flows/01-auth-rbac.mmd
@@ -0,0 +1,12 @@
+graph TD
+ U(["User opens Atlas"]):::start --> A{"VITE_AUTH_ENABLED?"}
+ A -- "No (dev)" --> DEV["Anonymous mode X-Atlas-Role header"]
+ A -- "Yes" --> MSAL["MSAL redirect → Entra ID"]
+ MSAL --> TOK["Bearer token"]
+ DEV --> API["Call /api/v1/* "]
+ TOK --> API
+ API --> RBAC{"Server RBAC capability check"}
+ RBAC -- allow --> OK(["200 + data"]):::start
+ RBAC -- deny --> F["403 Forbidden"]:::deny
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/02-dashboard.mmd b/SoW/flows/02-dashboard.mmd
new file mode 100644
index 0000000..94967a9
--- /dev/null
+++ b/SoW/flows/02-dashboard.mmd
@@ -0,0 +1,14 @@
+graph LR
+ N(["Open Dashboard"]):::start --> L{"Layout"}
+ L --> E["Executive"]
+ L --> O["Operational"]
+ L --> C["Compact"]
+ L --> CU["Custom builder drag/add/remove widgets"]
+ E --> Q["useDashboard() query"]
+ O --> Q
+ C --> Q
+ CU --> Q
+ Q --> D{"Data?"}
+ D -- yes --> R["KPIs · charts · tables · pipeline"]
+ D -- empty --> Z["Zeroed KPIs · empty panels"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/03-demands.mmd b/SoW/flows/03-demands.mmd
new file mode 100644
index 0000000..f5e1e88
--- /dev/null
+++ b/SoW/flows/03-demands.mmd
@@ -0,0 +1,9 @@
+graph TD
+ C(["Create demand"]):::start --> SC["Score: value + effort (1–5)"]
+ SC --> DR["Draft"]
+ DR --> BK["Backlog"]
+ BK -->|"drag card (live funnel)"| AP{"Approve? governance-gated"}
+ AP -- approved --> PG["In progress"]
+ AP -- hold --> HD["Hold"]
+ PG --> CV["Converted to project"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/04-portfolio-project.mmd b/SoW/flows/04-portfolio-project.mmd
new file mode 100644
index 0000000..bfffa2e
--- /dev/null
+++ b/SoW/flows/04-portfolio-project.mmd
@@ -0,0 +1,7 @@
+graph LR
+ P(["Portfolio"]):::start --> T{"Sub-tab"}
+ T --> PJ["Projects filter chips · cards/table"]
+ T --> BK["Blockers list + side panel"]
+ PJ -->|"click project"| PD(["Project Detail"]):::start
+ PD --> TABS["Overview · Tasks · Epics · RAID Artifacts · Costs · Gates · Security"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/05-project-gates.mmd b/SoW/flows/05-project-gates.mmd
new file mode 100644
index 0000000..623bb05
--- /dev/null
+++ b/SoW/flows/05-project-gates.mmd
@@ -0,0 +1,9 @@
+graph LR
+ G0["G0 Concept"] --> G1["G1 Initiate"] --> G2["G2 Plan"] --> G3["G3 Build"] --> G4["G4 Deploy"] --> G5["G5 Close"]
+ R{"Gate review cap-approve"}:::gate
+ G1 -.-> R
+ G3 -.-> R
+ R -- pass --> ADV["Advance to next gate"]
+ R -- fail --> REM["Remediate / hold"]:::deny
+ classDef gate fill:#fff6e6,stroke:#a9791a,color:#5a3d00;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/06-tasks-board.mmd b/SoW/flows/06-tasks-board.mmd
new file mode 100644
index 0000000..07d16f2
--- /dev/null
+++ b/SoW/flows/06-tasks-board.mmd
@@ -0,0 +1,8 @@
+graph TD
+ U(["Planner drags task card"]):::start --> CAP{"cap-schedule? Admin · PMO · PM · PM Lead"}
+ CAP -- no --> DENY["403 — status change denied"]:::deny
+ CAP -- yes --> MV["PATCH task status"]
+ MV --> HUB["SignalR room tasks:{projectId}"]
+ HUB --> PEERS["Card moves live for every viewer"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/07-gantt.mmd b/SoW/flows/07-gantt.mmd
new file mode 100644
index 0000000..46fdb3c
--- /dev/null
+++ b/SoW/flows/07-gantt.mmd
@@ -0,0 +1,10 @@
+graph LR
+ SC{"Scope"} --> PJ["Project"]
+ SC --> PG["Program"]
+ PJ --> T["Timeline: phases · bars · milestones"]
+ PG --> T
+ T --> DEP["Finish→Start dependency arrows"]
+ DEP --> S{"source"}
+ S --> M["manual (hand-drawn, cap-projects)"]
+ S --> J["jira (issue-link ingest)"]
+ S --> PL["project links (auto)"]
diff --git a/SoW/flows/08-resources.mmd b/SoW/flows/08-resources.mmd
new file mode 100644
index 0000000..4edb25c
--- /dev/null
+++ b/SoW/flows/08-resources.mmd
@@ -0,0 +1,10 @@
+graph TD
+ R(["Resources roster synced from Entra ID"]):::start --> W{"Period window"}
+ W --> WIN["day/week/month/quarter/half/year or custom date range"]
+ WIN --> ENG["Shared time-phased engine"]
+ ENG --> UT["Avg utilisation = Ops + Project + Product"]
+ UT --> OV{"over 100%?"}
+ OV -- yes --> FLAG["Over-allocation → resource risk"]:::deny
+ OV -- no --> OK["Within capacity"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/09-financials.mmd b/SoW/flows/09-financials.mmd
new file mode 100644
index 0000000..43de8fd
--- /dev/null
+++ b/SoW/flows/09-financials.mmd
@@ -0,0 +1,7 @@
+graph LR
+ SRC{"Source toggle"} --> BUD["Budget vs Actual"]
+ BUD --> SP["CapEx / OpEx split"]
+ SP --> FAC["Forecast at completion"]
+ FAC --> BEN["Savings / benefit"]
+ BEN --> ROI(["Portfolio ROI"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/10-programs.mmd b/SoW/flows/10-programs.mmd
new file mode 100644
index 0000000..53db8cc
--- /dev/null
+++ b/SoW/flows/10-programs.mmd
@@ -0,0 +1,5 @@
+graph TD
+ PG(["Program detail"]):::start --> MTX["Stakeholder power/interest matrix"]
+ PG --> LP["Linked projects — roll-up status"]
+ PG --> SY["Sync from Jira (cap-projects E)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/11-products-releases.mmd b/SoW/flows/11-products-releases.mmd
new file mode 100644
index 0000000..01dd6a4
--- /dev/null
+++ b/SoW/flows/11-products-releases.mmd
@@ -0,0 +1,6 @@
+graph LR
+ PRD(["Product"]):::start --> MAP["Jira / ADO tasks mapped"]
+ MAP --> REL["Releases"]
+ REL --> CAL["Release calendar"]
+ CAL --> DEP["Deployment tracking"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/12-okrs.mmd b/SoW/flows/12-okrs.mmd
new file mode 100644
index 0000000..7fe2f9e
--- /dev/null
+++ b/SoW/flows/12-okrs.mmd
@@ -0,0 +1,8 @@
+graph TD
+ O(["Objective"]):::start --> KR["Key results"]
+ KR --> L{"Link target"}
+ L --> P["Project"]
+ L --> PG["Program"]
+ L --> PR["Product"]
+ KR --> PROG["Progress roll-up (0–100%)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/13-delivery.mmd b/SoW/flows/13-delivery.mmd
new file mode 100644
index 0000000..68fda3e
--- /dev/null
+++ b/SoW/flows/13-delivery.mmd
@@ -0,0 +1,9 @@
+graph LR
+ PER{"Period weekly → yearly"} --> AGG["Completed · in-progress · planned"]
+ AGG --> VEL["Velocity + on-time %"]
+ AGG --> BLK["Blockers"]
+ AGG --> BURN["Budget burn"]
+ VEL --> RPT(["Stakeholder delivery report"]):::start
+ BLK --> RPT
+ BURN --> RPT
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/14-news.mmd b/SoW/flows/14-news.mmd
new file mode 100644
index 0000000..72920d6
--- /dev/null
+++ b/SoW/flows/14-news.mmd
@@ -0,0 +1,6 @@
+graph TD
+ ED{"Edit mode?"} -- yes --> BLK["Add blocks: headline · metric · shout-out image · milestone · doc"]
+ BLK --> SAVE["Save news wall"]
+ ED -- no --> VIEW(["Masonry news wall (themed)"]):::start
+ SAVE --> VIEW
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/15-integrations-sync.mmd b/SoW/flows/15-integrations-sync.mmd
new file mode 100644
index 0000000..36d357b
--- /dev/null
+++ b/SoW/flows/15-integrations-sync.mmd
@@ -0,0 +1,19 @@
+sequenceDiagram
+ autonumber
+ actor U as PM · cap-projects E
+ participant API as Atlas API
+ participant Q as SyncQueue⟨T⟩
+ participant W as SyncWorker⟨T⟩
+ participant C as IWorkItemConnector
+ participant EX as Jira / Azure DevOps
+ U->>API: POST /projects/{id}/{conn}/sync?background=true
+ API->>API: gate cap-projects E
+ API->>Q: enqueue job
+ API-->>U: 202 Accepted + jobId
+ W->>C: SyncCoreAsync(targets, delta)
+ C->>EX: pull issues (delta watermark, ISO)
+ EX-->>C: work items
+ C->>API: upsert projects / sprints / epics / tasks
+ W->>API: write audit event
+ U->>API: GET .../sync/status/{jobId}
+ API-->>U: status = done (counts)
diff --git a/SoW/flows/16-whiteboard.mmd b/SoW/flows/16-whiteboard.mmd
new file mode 100644
index 0000000..1b8ee98
--- /dev/null
+++ b/SoW/flows/16-whiteboard.mmd
@@ -0,0 +1,6 @@
+graph TD
+ U(["User edits node / edge"]):::start --> OP["Authorized op scope-gated by entity capability"]
+ OP --> SAN["Server sanitises + persists typed row"]
+ SAN --> HUB["Room hub broadcast"]
+ HUB --> PEERS["Live co-edit: presence · cursors field-merge · off-screen peers"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/17-reports.mmd b/SoW/flows/17-reports.mmd
new file mode 100644
index 0000000..3c57691
--- /dev/null
+++ b/SoW/flows/17-reports.mmd
@@ -0,0 +1,7 @@
+graph LR
+ SEL(["Select report portfolio · demand · blocker · audit"]):::start --> BR["Apply branding"]
+ BR --> F{"Export format"}
+ F --> PDF["PDF"]
+ F --> XL["Excel"]
+ F --> PP["PPTX"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/18-admin.mmd b/SoW/flows/18-admin.mmd
new file mode 100644
index 0000000..3753b64
--- /dev/null
+++ b/SoW/flows/18-admin.mmd
@@ -0,0 +1,7 @@
+graph TD
+ A(["Administration"]):::start --> RBAC["Roles & permissions matrix"]
+ A --> BK["Backups / restore (validated)"]
+ A --> AUD["Audit log"]
+ A --> SY["AD directory sync"]
+ A --> DEL["Deletion requests (GDPR)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/19-governance-compliance.mmd b/SoW/flows/19-governance-compliance.mmd
new file mode 100644
index 0000000..d91b80d
--- /dev/null
+++ b/SoW/flows/19-governance-compliance.mmd
@@ -0,0 +1,7 @@
+graph TD
+ GOV(["Governance & compliance"]):::start --> SOA["ISO 27001 SoA — 93 Annex A controls"]
+ GOV --> ADR["Decision log (ADR)"]
+ GOV --> TG["TOGAF ADM phases · ARB · waivers"]
+ GOV --> SEC["GDPR · PCI-DSS · EU AI Act · SOC 2 · NIS2"]
+ SOA --> COV["Coverage roll-up"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/dev-01-change-lifecycle.mmd b/SoW/flows/dev-01-change-lifecycle.mmd
new file mode 100644
index 0000000..b911847
--- /dev/null
+++ b/SoW/flows/dev-01-change-lifecycle.mmd
@@ -0,0 +1,10 @@
+graph LR
+ I(["Issue / finding"]):::start --> B["Branch (claude/…)"]
+ B --> IMP["Implement · ADR if architectural"]
+ IMP --> PR["Open ONE PR (one issue → one PR)"]
+ PR --> CI{"CI green?"}
+ CI -- no --> FIX["Fix → push"]
+ FIX --> CI
+ CI -- yes --> RV["Review"]
+ RV --> M(["Squash-merge to main"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/dev-02-ci-pipeline.mmd b/SoW/flows/dev-02-ci-pipeline.mmd
new file mode 100644
index 0000000..6de68c7
--- /dev/null
+++ b/SoW/flows/dev-02-ci-pipeline.mmd
@@ -0,0 +1,16 @@
+graph TD
+ P(["Push / Pull request"]):::start --> J{"CI jobs — parallel"}
+ J --> FE["Frontend: lint · test · build · coverage floor"]
+ J --> BE["API: build · test · coverage floor"]
+ J --> CT["API type-contract drift"]
+ J --> AX["Accessibility (Playwright + axe)"]
+ J --> SEC["SAST (Semgrep) · Trivy (deps/secrets/IaC)"]
+ FE --> G{"All required green?"}
+ BE --> G
+ CT --> G
+ AX --> G
+ SEC --> G
+ G -- yes --> MG(["Mergeable"]):::start
+ G -- no --> BL["Blocked"]:::deny
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/dev-03-api-type-contract.mmd b/SoW/flows/dev-03-api-type-contract.mmd
new file mode 100644
index 0000000..980bb13
--- /dev/null
+++ b/SoW/flows/dev-03-api-type-contract.mmd
@@ -0,0 +1,10 @@
+graph LR
+ DTO["Server DTOs · .Produces<T>"] --> DUMP["Boot API (Atlas:SkipDbInit, no DB)"]
+ DUMP --> DOC["openapi/atlas-v1.json"]
+ DOC --> GEN["openapi-typescript"]
+ GEN --> TS["src/api/generated.ts"]
+ TS --> DIFF{"CI: git diff --exit-code"}
+ DIFF -- drift --> FAIL["Fail — run npm run api:types"]:::deny
+ DIFF -- clean --> OK(["Contract in sync"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/dev-04-module-boundary.mmd b/SoW/flows/dev-04-module-boundary.mmd
new file mode 100644
index 0000000..d94d419
--- /dev/null
+++ b/SoW/flows/dev-04-module-boundary.mmd
@@ -0,0 +1,7 @@
+graph LR
+ BUILD(["Build + test"]):::start --> ARCH["NetArchTest / Mono.Cecil ratchet (ADR-0072)"]
+ ARCH --> CHK{"Atlas.Api.<Domain> edges legal?"}
+ CHK -- "Integrations reaches a business module" --> FAIL["Build fails"]:::deny
+ CHK -- "leaf boundaries respected" --> OK(["Pass"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/dev-05-test-strategy.mmd b/SoW/flows/dev-05-test-strategy.mmd
new file mode 100644
index 0000000..9f41070
--- /dev/null
+++ b/SoW/flows/dev-05-test-strategy.mmd
@@ -0,0 +1,6 @@
+graph TD
+ U["Unit — xUnit (server) · Vitest (frontend)"] --> I["Integration — WebApplicationFactory (in-memory DB)"]
+ I --> E["E2E — Playwright + axe (empty-state DOM)"]
+ E --> PF["Performance — k6 budget"]
+ PF --> COV(["Coverage floors gated in CI"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/dev-06-local-dev.mmd b/SoW/flows/dev-06-local-dev.mmd
new file mode 100644
index 0000000..95bc56c
--- /dev/null
+++ b/SoW/flows/dev-06-local-dev.mmd
@@ -0,0 +1,6 @@
+graph LR
+ DEV(["Developer"]):::start --> A["npm install → npm run dev (:5173)"]
+ A --> B{"VITE_AUTH_ENABLED?"}
+ B -- false --> C["Browse every screen → empty states (no backend)"]
+ B -- true --> D["Entra SSO + VITE_API_PROXY → live API"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/dev-07-build-deploy.mmd b/SoW/flows/dev-07-build-deploy.mmd
new file mode 100644
index 0000000..5032b11
--- /dev/null
+++ b/SoW/flows/dev-07-build-deploy.mmd
@@ -0,0 +1,8 @@
+graph LR
+ SRC(["Source"]):::start --> FE["npm run build (tsc + Vite)"]
+ SRC --> BE["dotnet publish"]
+ FE --> ART["Self-contained artefacts (assets bundled)"]
+ BE --> ART
+ ART --> DL["Download to Windows server (no git on target)"]
+ DL --> NG(["nginx same-origin: app · /api/v1 · /hubs"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/dev-08-runtime-topology.mmd b/SoW/flows/dev-08-runtime-topology.mmd
new file mode 100644
index 0000000..28bbeab
--- /dev/null
+++ b/SoW/flows/dev-08-runtime-topology.mmd
@@ -0,0 +1,9 @@
+graph LR
+ BR(["Browser · React SPA"]):::start --> NG["nginx (same-origin)"]
+ NG --> API["Atlas .NET API · /api/v1"]
+ NG --> HUB["SignalR · /hubs (realtime rooms)"]
+ API --> DB[("PostgreSQL 16")]
+ API --> EXT["Connectors: Jira · Azure DevOps · …"]
+ BR -. "MSAL bearer" .-> ENTRA["Entra ID (SSO)"]
+ API -. "validate token" .-> ENTRA
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/dev-09-connector-extension.mmd b/SoW/flows/dev-09-connector-extension.mmd
new file mode 100644
index 0000000..d4dd025
--- /dev/null
+++ b/SoW/flows/dev-09-connector-extension.mmd
@@ -0,0 +1,7 @@
+graph LR
+ NEW(["New tracker (e.g. ServiceNow)"]):::start --> IMPL["implement IWorkItemConnector"]
+ IMPL --> REG["register in DI: SyncQueue<T> + SyncWorker<T>"]
+ REG --> EP["reuse shared enqueue · 202/poll · gate"]
+ EP --> PARSE["add ONLY connector-specific parsing"]
+ PARSE --> TST(["fixture tests + boundary stays a leaf"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-01-executive-review.mmd b/SoW/flows/user-01-executive-review.mmd
new file mode 100644
index 0000000..2ac09b2
--- /dev/null
+++ b/SoW/flows/user-01-executive-review.mmd
@@ -0,0 +1,8 @@
+graph LR
+ U(["Executive"]):::start --> A["Open Dashboard → Executive layout"]
+ A --> B["Scan portfolio-health donut + KPI cards"]
+ B --> C{"Anything needs attention?"}
+ C -- yes --> D["Open a 'needs attention' project"]
+ D --> E["Read status · budget burn · blockers"]
+ C -- no --> F["Review demand pipeline + recent activity"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-02-pmo-demand-approval.mmd b/SoW/flows/user-02-pmo-demand-approval.mmd
new file mode 100644
index 0000000..aec3581
--- /dev/null
+++ b/SoW/flows/user-02-pmo-demand-approval.mmd
@@ -0,0 +1,8 @@
+graph LR
+ U(["PMO"]):::start --> A["Open Demands funnel"]
+ A --> B["Review a scored demand (value vs effort)"]
+ B --> C{"Approve?"}
+ C -- yes --> D["Drag card to Approved → confirm"]
+ D --> E["Demand becomes project intake"]
+ C -- no --> F["Move to Hold · add comment"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-03-pm-create-project.mmd b/SoW/flows/user-03-pm-create-project.mmd
new file mode 100644
index 0000000..5b99564
--- /dev/null
+++ b/SoW/flows/user-03-pm-create-project.mmd
@@ -0,0 +1,7 @@
+graph LR
+ U(["Project Manager"]):::start --> A["Methodologies → Create project"]
+ A --> B["Step 1 · pick methodology"]
+ B --> C["Step 2 · name · department · owner"]
+ C --> D["Step 3 · choose integration (Jira / ADO / none)"]
+ D --> E(["Project created → opens Project Detail"]):::start
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-04-pm-manage-tasks.mmd b/SoW/flows/user-04-pm-manage-tasks.mmd
new file mode 100644
index 0000000..2544e84
--- /dev/null
+++ b/SoW/flows/user-04-pm-manage-tasks.mmd
@@ -0,0 +1,7 @@
+graph LR
+ U(["Project Manager"]):::start --> A["Project → Tasks (board)"]
+ A --> B["Drag a card between columns"]
+ B --> C["Status updates live for the team"]
+ A --> D["Sync from Jira (pull latest)"]
+ D --> E["Board reflects imported issues"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-05-pm-stage-gate.mmd b/SoW/flows/user-05-pm-stage-gate.mmd
new file mode 100644
index 0000000..a83fea8
--- /dev/null
+++ b/SoW/flows/user-05-pm-stage-gate.mmd
@@ -0,0 +1,9 @@
+graph LR
+ U(["Project Manager"]):::start --> A["Project → Gates (G0–G5)"]
+ A --> B["Prepare gate evidence / checklist"]
+ B --> C["Request gate review"]
+ C --> D{"Reviewer decision"}
+ D -- pass --> E["Advance to next gate"]
+ D -- fail --> F["Remediate and resubmit"]:::deny
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
+ classDef deny fill:#f7dede,stroke:#b23a3a,color:#7a1f1f;
diff --git a/SoW/flows/user-06-team-member-update.mmd b/SoW/flows/user-06-team-member-update.mmd
new file mode 100644
index 0000000..63fa629
--- /dev/null
+++ b/SoW/flows/user-06-team-member-update.mmd
@@ -0,0 +1,6 @@
+graph LR
+ U(["Team member"]):::start --> A["Dashboard → Operational → My tasks"]
+ A --> B["Open a task"]
+ B --> C["Update status · progress · notes"]
+ C --> D["Saved → rolls up to project + delivery"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-07-stakeholder-status.mmd b/SoW/flows/user-07-stakeholder-status.mmd
new file mode 100644
index 0000000..1c872dc
--- /dev/null
+++ b/SoW/flows/user-07-stakeholder-status.mmd
@@ -0,0 +1,6 @@
+graph LR
+ U(["Stakeholder"]):::start --> A["My Projects (reduced nav)"]
+ A --> B["Open a project → read-only status"]
+ B --> C["Check Delivery status + Releases"]
+ C --> D["Read Weekly Updates (News)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-08-manager-team.mmd b/SoW/flows/user-08-manager-team.mmd
new file mode 100644
index 0000000..5194154
--- /dev/null
+++ b/SoW/flows/user-08-manager-team.mmd
@@ -0,0 +1,8 @@
+graph LR
+ U(["Manager"]):::start --> A["My Team"]
+ A --> B["Review members + skills matrix"]
+ B --> C["Update team SWOT"]
+ B --> D["Record individual development plan (manager-only)"]
+ C --> E["Saved · governance-gated · audited"]
+ D --> E
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-09-platform-admin.mmd b/SoW/flows/user-09-platform-admin.mmd
new file mode 100644
index 0000000..b68e74e
--- /dev/null
+++ b/SoW/flows/user-09-platform-admin.mmd
@@ -0,0 +1,7 @@
+graph LR
+ U(["Platform Admin"]):::start --> A["Administration"]
+ A --> B["Roles & permissions matrix"]
+ A --> C["Backups / restore · audit log"]
+ A --> D["AD directory sync · connector config"]
+ A --> E["Review & action deletion requests (GDPR)"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/flows/user-10-architect-governance.mmd b/SoW/flows/user-10-architect-governance.mmd
new file mode 100644
index 0000000..2f8cba4
--- /dev/null
+++ b/SoW/flows/user-10-architect-governance.mmd
@@ -0,0 +1,7 @@
+graph LR
+ U(["Chief Architect"]):::start --> A["Governance"]
+ A --> B["Decision log — record an ADR"]
+ A --> C["Architecture gate reviews (G1 / G3)"]
+ A --> D["TOGAF ADM · domains · waivers · ARB"]
+ A --> E["Project → Security: ISO 27001 SoA"]
+ classDef start fill:#2a4c8f,stroke:#22407a,color:#ffffff,font-weight:600;
diff --git a/SoW/images/00-app-sitemap.png b/SoW/images/00-app-sitemap.png
new file mode 100644
index 0000000..f17e8ca
Binary files /dev/null and b/SoW/images/00-app-sitemap.png differ
diff --git a/SoW/images/01-auth-rbac.png b/SoW/images/01-auth-rbac.png
new file mode 100644
index 0000000..8046c6d
Binary files /dev/null and b/SoW/images/01-auth-rbac.png differ
diff --git a/SoW/images/02-dashboard.png b/SoW/images/02-dashboard.png
new file mode 100644
index 0000000..608e5a0
Binary files /dev/null and b/SoW/images/02-dashboard.png differ
diff --git a/SoW/images/03-demands.png b/SoW/images/03-demands.png
new file mode 100644
index 0000000..69e7879
Binary files /dev/null and b/SoW/images/03-demands.png differ
diff --git a/SoW/images/04-portfolio-project.png b/SoW/images/04-portfolio-project.png
new file mode 100644
index 0000000..85ade0a
Binary files /dev/null and b/SoW/images/04-portfolio-project.png differ
diff --git a/SoW/images/05-project-gates.png b/SoW/images/05-project-gates.png
new file mode 100644
index 0000000..b68433c
Binary files /dev/null and b/SoW/images/05-project-gates.png differ
diff --git a/SoW/images/06-tasks-board.png b/SoW/images/06-tasks-board.png
new file mode 100644
index 0000000..0fa81bd
Binary files /dev/null and b/SoW/images/06-tasks-board.png differ
diff --git a/SoW/images/07-gantt.png b/SoW/images/07-gantt.png
new file mode 100644
index 0000000..2d9994f
Binary files /dev/null and b/SoW/images/07-gantt.png differ
diff --git a/SoW/images/08-resources.png b/SoW/images/08-resources.png
new file mode 100644
index 0000000..ce028ea
Binary files /dev/null and b/SoW/images/08-resources.png differ
diff --git a/SoW/images/09-financials.png b/SoW/images/09-financials.png
new file mode 100644
index 0000000..38c1ad0
Binary files /dev/null and b/SoW/images/09-financials.png differ
diff --git a/SoW/images/10-programs.png b/SoW/images/10-programs.png
new file mode 100644
index 0000000..04d1d6f
Binary files /dev/null and b/SoW/images/10-programs.png differ
diff --git a/SoW/images/11-products-releases.png b/SoW/images/11-products-releases.png
new file mode 100644
index 0000000..00a647d
Binary files /dev/null and b/SoW/images/11-products-releases.png differ
diff --git a/SoW/images/12-okrs.png b/SoW/images/12-okrs.png
new file mode 100644
index 0000000..6ff347c
Binary files /dev/null and b/SoW/images/12-okrs.png differ
diff --git a/SoW/images/13-delivery.png b/SoW/images/13-delivery.png
new file mode 100644
index 0000000..e2e0642
Binary files /dev/null and b/SoW/images/13-delivery.png differ
diff --git a/SoW/images/14-news.png b/SoW/images/14-news.png
new file mode 100644
index 0000000..6e02a41
Binary files /dev/null and b/SoW/images/14-news.png differ
diff --git a/SoW/images/15-integrations-sync.png b/SoW/images/15-integrations-sync.png
new file mode 100644
index 0000000..bb3777f
Binary files /dev/null and b/SoW/images/15-integrations-sync.png differ
diff --git a/SoW/images/16-whiteboard.png b/SoW/images/16-whiteboard.png
new file mode 100644
index 0000000..4ca05cc
Binary files /dev/null and b/SoW/images/16-whiteboard.png differ
diff --git a/SoW/images/17-reports.png b/SoW/images/17-reports.png
new file mode 100644
index 0000000..0bd7385
Binary files /dev/null and b/SoW/images/17-reports.png differ
diff --git a/SoW/images/18-admin.png b/SoW/images/18-admin.png
new file mode 100644
index 0000000..243ebcf
Binary files /dev/null and b/SoW/images/18-admin.png differ
diff --git a/SoW/images/19-governance-compliance.png b/SoW/images/19-governance-compliance.png
new file mode 100644
index 0000000..857fc46
Binary files /dev/null and b/SoW/images/19-governance-compliance.png differ
diff --git a/SoW/images/dev-01-change-lifecycle.png b/SoW/images/dev-01-change-lifecycle.png
new file mode 100644
index 0000000..c83e904
Binary files /dev/null and b/SoW/images/dev-01-change-lifecycle.png differ
diff --git a/SoW/images/dev-02-ci-pipeline.png b/SoW/images/dev-02-ci-pipeline.png
new file mode 100644
index 0000000..3312564
Binary files /dev/null and b/SoW/images/dev-02-ci-pipeline.png differ
diff --git a/SoW/images/dev-03-api-type-contract.png b/SoW/images/dev-03-api-type-contract.png
new file mode 100644
index 0000000..0889b90
Binary files /dev/null and b/SoW/images/dev-03-api-type-contract.png differ
diff --git a/SoW/images/dev-04-module-boundary.png b/SoW/images/dev-04-module-boundary.png
new file mode 100644
index 0000000..449fff0
Binary files /dev/null and b/SoW/images/dev-04-module-boundary.png differ
diff --git a/SoW/images/dev-05-test-strategy.png b/SoW/images/dev-05-test-strategy.png
new file mode 100644
index 0000000..b528d98
Binary files /dev/null and b/SoW/images/dev-05-test-strategy.png differ
diff --git a/SoW/images/dev-06-local-dev.png b/SoW/images/dev-06-local-dev.png
new file mode 100644
index 0000000..11afdfa
Binary files /dev/null and b/SoW/images/dev-06-local-dev.png differ
diff --git a/SoW/images/dev-07-build-deploy.png b/SoW/images/dev-07-build-deploy.png
new file mode 100644
index 0000000..0726ccf
Binary files /dev/null and b/SoW/images/dev-07-build-deploy.png differ
diff --git a/SoW/images/dev-08-runtime-topology.png b/SoW/images/dev-08-runtime-topology.png
new file mode 100644
index 0000000..6f6247a
Binary files /dev/null and b/SoW/images/dev-08-runtime-topology.png differ
diff --git a/SoW/images/dev-09-connector-extension.png b/SoW/images/dev-09-connector-extension.png
new file mode 100644
index 0000000..a800ea9
Binary files /dev/null and b/SoW/images/dev-09-connector-extension.png differ
diff --git a/SoW/images/user-01-executive-review.png b/SoW/images/user-01-executive-review.png
new file mode 100644
index 0000000..4f24cbd
Binary files /dev/null and b/SoW/images/user-01-executive-review.png differ
diff --git a/SoW/images/user-02-pmo-demand-approval.png b/SoW/images/user-02-pmo-demand-approval.png
new file mode 100644
index 0000000..efadcf9
Binary files /dev/null and b/SoW/images/user-02-pmo-demand-approval.png differ
diff --git a/SoW/images/user-03-pm-create-project.png b/SoW/images/user-03-pm-create-project.png
new file mode 100644
index 0000000..d00d7f0
Binary files /dev/null and b/SoW/images/user-03-pm-create-project.png differ
diff --git a/SoW/images/user-04-pm-manage-tasks.png b/SoW/images/user-04-pm-manage-tasks.png
new file mode 100644
index 0000000..40bb3cc
Binary files /dev/null and b/SoW/images/user-04-pm-manage-tasks.png differ
diff --git a/SoW/images/user-05-pm-stage-gate.png b/SoW/images/user-05-pm-stage-gate.png
new file mode 100644
index 0000000..43998df
Binary files /dev/null and b/SoW/images/user-05-pm-stage-gate.png differ
diff --git a/SoW/images/user-06-team-member-update.png b/SoW/images/user-06-team-member-update.png
new file mode 100644
index 0000000..02255ba
Binary files /dev/null and b/SoW/images/user-06-team-member-update.png differ
diff --git a/SoW/images/user-07-stakeholder-status.png b/SoW/images/user-07-stakeholder-status.png
new file mode 100644
index 0000000..83030ce
Binary files /dev/null and b/SoW/images/user-07-stakeholder-status.png differ
diff --git a/SoW/images/user-08-manager-team.png b/SoW/images/user-08-manager-team.png
new file mode 100644
index 0000000..700d44a
Binary files /dev/null and b/SoW/images/user-08-manager-team.png differ
diff --git a/SoW/images/user-09-platform-admin.png b/SoW/images/user-09-platform-admin.png
new file mode 100644
index 0000000..2896257
Binary files /dev/null and b/SoW/images/user-09-platform-admin.png differ
diff --git a/SoW/images/user-10-architect-governance.png b/SoW/images/user-10-architect-governance.png
new file mode 100644
index 0000000..dd64056
Binary files /dev/null and b/SoW/images/user-10-architect-governance.png differ
diff --git a/SoW/sow-atlas-ppm-product-build.html b/SoW/sow-atlas-ppm-product-build.html
new file mode 100644
index 0000000..d14bf4f
--- /dev/null
+++ b/SoW/sow-atlas-ppm-product-build.html
@@ -0,0 +1,414 @@
+
+
+
+
+
Statement of Work
+
Atlas PPM — Product Build
+
Portfolio & Project Management platform for Birgma / Biltema Group
+
+
Project
Atlas PPM platform
+
Client
Birgma / Biltema Group
+
Repository
nicpozent/ATLASPPM_AdditionalFeatures
+
Prepared for
nicolas.pozza@birgma.com
+
Date
2026-08-07
+
Document type
For signature — v1.0 (draft)
+
+
+
+
+
1 Background & objectives
+
Atlas is a Portfolio & Project Management web application for Birgma / Biltema Group. This engagement delivers the full application — every screen and all functionality — pixel-faithful to the approved prototype (design/Atlas PPM.dc.html), wired to the .NET 10 minimal API backend, and hardened for an on-premise, air-gapped deployment.
+
+
Reproduce every prototype screen 1:1 — layout, typography, colour, components, states, copy — with no redesign or additions beyond approved extensions.
+
Data-drive every screen from the /api/v1/* API via TanStack Query, with first-class loading / empty / error states (empty by default — no fabricated seed data).
+
Enforce server-authoritative role-based access control; the client is never a security boundary.
+
Meet the non-functional bar: accessibility (WCAG AA), localised chrome, security/compliance modules, and a continuously green automated build.
+
+
+
+
+
2 Scope of work
+
+
2.1 Workspace screens
+
+
Dashboard — four layouts via a segmented control: Executive (portfolio-health donut, budget-burn, KPI cards w/ sparklines, active-projects table, needs-attention, demand pipeline, recent activity), Operational, Compact, and a drag-and-drop Custom builder.
+
Portfolio — Projects (filter chips + cards/table) and Blockers (list + side panel); drill-through to Project Detail.
Reduced navigation: My Projects, My Demands + Delivery, Releases, News, Help.
+
+
2.4 Governance modules
+
Stage gates G0–G5, gate reviews (architecture/security), decision log (ADR), TOGAF ADM phases, architecture domains/waivers/ARB, and a security/compliance module (GDPR, PCI-DSS, ISO 27001, EU AI Act, SOC 2, NIS2) with control mappings — reproduced where the prototype places them.
+
+
2.5 Approved extensions (beyond the frozen prototype)
+
Built in the existing design language and recorded per CLAUDE.md §2 + an ADR: Microsoft Teams notifications; real-time collaboration (SignalR rooms — PI Program Board, demand funnel, task board, live presence/cursors/off-screen peers); Freeform Whiteboard (co-editing, templates, export); Team SWOT and individual development plans; ISO 27001 Statement of Applicability; cross-entity timeline dependencies; period-windowed resource utilisation; quality test tasks + Jira board ingest; project delivery roles (Tech Lead / Scrum Master); and the three Atlas brand themes (Command / Daylight / Carbon).
+
+
2.6 Platform & cross-cutting
+
+
Entra ID (MSAL) SSO with route guards; server-authoritative RBAC (6 canonical roles; 9 cosmetic header identities).
+
Generated API type contract (OpenAPI → TypeScript) with CI drift protection.
+
Self-hosted fonts/assets for air-gapped operation; nginx same-origin serving.
Editing the design reference (design/) — regenerated by the design team.
+
+
+
2.8 User roles & journeys
+
Authorization is enforced server-side on 6 canonical roles; the header's 9 identities are cosmetic (they change the visible nav, not access). Each role's primary journey is a flow diagram in the flow package (SoW/flows/user-*).
Engineering / Service / Dev / Infra Manager & members
Update my work; My Team — skills, SWOT, development plans
user-06, user-08
+
Executive
(leadership)
Portfolio review
user-01
+
Stakeholder
Stakeholder
Check my projects / demands / delivery (reduced nav)
user-07
+
Architecture
Chief Architect
Governance — ADR log, architecture gate reviews, TOGAF ADM, ISO 27001 SoA
user-10
+
+
+
The four Manager identities (Engineering / Service / Dev / Infra) differ only cosmetically and share the Team Member / My Team journeys. Beyond these role journeys the flow package also documents system & data flows (20) and software-development interaction flows (9) — see SoW/flows.md and the gallery.
+
The ten per-role journeys:
+
Executive — portfolio review
PMO — triage & approve a demand
PM — create a project (wizard)
PM — manage tasks & Jira sync
PM — request a stage-gate review
Team member — update my work
Stakeholder — check my status
Manager — My Team
Platform Admin — administration
Chief Architect — governance
+
+
+
+
3 Deliverables
+
+
The complete, prototype-faithful Atlas PPM frontend (React 18 + TS + Vite), one screen component per route, split into local sub-components.
+
The supporting .NET 10 minimal API endpoints each screen consumes (extended where needed), EF Core 10 / PostgreSQL 16.
+
Entra SSO wiring (login/redirect, route guards) and the RBAC capability matrix.
+
Generated API types + api.ts client; TanStack Query hooks with loading/empty/error states.
+
Automated test suites — backend (xUnit, incl. fixtures + architecture boundary tests), frontend (Vitest), accessibility (Playwright + axe), performance (k6) — gated in CI with coverage floors.
+
Flow diagrams (SoW/flows) — 39 diagrams in three views: system & data flows (20), per-role user journeys (10), software-development interaction flows (9), with rendered images and an index/gallery.
+
Architecture Decision Records for every architectural choice, plus a consolidated ALL-ADRS.md.
+
Deployment artefacts for the air-gapped Windows on-prem target (self-contained build output, nginx config, setup/integration guides).
+
+
+
+
+
4 Approach & methodology
+
+
Prototype is the source of truth. Inline styles lifted from the prototype; theme.ts tokens and the three fonts only; computed visuals (charts, donuts, sparklines, gantt geometry) ported faithfully.
+
Empty by default. Real layout with tasteful empty states until the API returns data; never fabricated seed data.
+
Server-authoritative security. The API is the authority for authorization; UI role checks are cosmetic affordances only.
+
Typed, tested, accessible. TypeScript strict; generated API types; ≥44px hit targets, real controls, focus styles, aria-*; every data view has loading/empty/error.
+
Build one screen fully (visually faithful + data-wired + empty state) before the next; compare side-by-side with the prototype.
+
ADR-driven + one-change-one-PR, each verified green in CI before merge.
Deployable — a clean build runs on the air-gapped Windows target from the provided artefacts.
+
+
+
+
+
8 Assumptions & constraints
+
+
On-prem, air-gapped — no runtime internet egress; all fonts/assets self-hosted (ADR-0078); dev-only tooling runs in CI, never ships.
+
Deployment — client downloads built files to a Windows server; no git on target — artefacts must be self-contained.
+
Identity — Entra ID (Azure AD) tenant available for SSO; directory sync for Resources.
+
Prototype freeze — design/Atlas PPM.dc.html is authoritative and not edited; approved deviations recorded in CLAUDE.md §2 + an ADR, and flagged for the design team to regenerate design/.
+
Roles — six canonical backend roles enforce access; the nine-identity header switcher is cosmetic.
+
+
+
+
+
9 Roles & responsibilities
+
+
Party
Responsibility
+
+
Engineering (delivery)
Frontend + API implementation, tests, ADRs, CI, deployment artefacts
+
Product Owner (Birgma)
Prototype sign-off, approval of extensions & Proposed ADRs, milestone prioritisation
+
Design team
Own design/; regenerate to reflect approved extensions
+
Platform / IT (Birgma)
Entra tenant, on-prem/nginx environment, DB provisioning, deploy windows
Data integrity — typed dates (date/timestamptz); no display-string date columns (ADR-0082).
+
+
+
+
+
11 Risks & dependencies
+
+
Risk / dependency
Mitigation
+
+
Prototype fidelity disputes
Side-by-side review as an explicit acceptance gate
+
Air-gapped runtime (no CDNs)
Self-host all assets; verify offline build
+
Entra tenant / directory access
Confirm tenant + app registration early (M9 depends on it)
+
Personnel-data features (SWOT / dev plans)
Gated off until DPIA + MBL §11 sign-off (ADR-0063)
+
External connector availability (Jira/ADO/etc.)
Empty/degraded states; connectors dormant until configured
+
Compliance-module accuracy
Review with Security/Compliance before acceptance
+
+
+
+
+
+
12 Commercials & timeline
+
To be completed by the parties. The figures below are placeholders — Atlas engineering scope, milestones and acceptance are fixed by this document; pricing, rates and calendar dates are commercial terms to be agreed and filled in before signature.
+
+
Term
Value
+
+
Pricing model
‹fixed-price / capped T&M / T&M — to be agreed›
+
Total price / not-to-exceed
‹to be agreed›
+
Rate card (if T&M)
‹to be agreed›
+
Estimated effort
‹to be agreed›
+
Payment schedule
On acceptance of each milestone (M1–M9, §6) ‹split % to be agreed›
+
Expenses & travel
‹to be agreed›
+
Start date
‹TBD›
+
Target completion
‹TBD› (milestone dates per §6)
+
Warranty / support
‹to be agreed›
+
Governing agreement
This SoW is issued under ‹MSA / framework agreement ref — TBD›
+
+
+
Change control: any change to the fixed scope (§2) is handled by a written change request priced against the agreed model before work proceeds.
+
+
+
+
13 Acceptance & sign-off
+
Work is accepted milestone-by-milestone against the criteria in §7. This Statement of Work is agreed and authorised by the undersigned.
B Appendix — Software-development interaction flows
+
Change lifecycle
CI pipeline
API type contract + drift
Module-boundary ratchet
Test strategy
Local dev loop
Build & air-gapped deploy
Runtime topology
Extending a connector
+
+
+
Companion document: a separate SoW covers the code-review remediation engagement (Epic #106) — security hardening, structural refactors, and ADRs 0080–0084 — with per-item delivery status.