4. Solution Strategy¶
Summary of fundamental decisions and solution approaches. Each entry should reference an ADR.
| Topic | Approach | Decision |
|---|---|---|
| Document storage & versioning | PostgreSQL as single source of truth for all state; version content as immutable, SHA-256-keyed blobs behind a storage interface (file system now, S3 later); a version may hold multiple content parts bound by a manifest hash; git only as a possible export view | ADR-0001, ADR-0017 |
| Topology & multi-mandator separation | One instance with a scope hierarchy (global base → mandator → project); copy-on-derive of released versions; row-level tenancy enforced by PostgreSQL RLS; scope behavior via capability flags, not code branches | ADR-0002 |
| Self-managed QMS | The operating organization is an internal mandator; its QMS operations are ordinary project scopes deriving the same masters as customer products — one process master serves both. Global base = master development; project scopes = operating processes (records), the QMS included | ADR-0010 |
| Life cycle engine | Fixed states (DRAFT → IN_REVIEW → RELEASED → REVOKED); configurable review policies per scope/document type (required role approvals, four-eyes default-on, transition permissions, release mode) | ADR-0003 |
| Roles & document types | Global curated catalogs; per-scope opt-in activation; multi-role staffing; derive-time validation of policy role references | ADR-0004 |
| Architecture style | Modular monolith: one Quarkus app, one database, build-enforced module boundaries; search and storage extraction-ready behind interfaces |
ADR-0005 |
| Search | Three layers: PostgreSQL FTS baseline; local RAG (local embeddings, pgvector under RLS); pluggable LLM provider with per-mandator policy and chunk-level audit logging | ADR-0006 |
| Frontend | Angular (separate app on the REST API); frontend is never an enforcement point; E2E suite doubles as CSV regression evidence; i18n designed in from the first screen | ADR-0007 |
| Authentication | OIDC SSO (pluggable provider / bundled Keycloak), no credentials in LQMS; stateless BFF sessions in an encrypted, httpOnly token-state cookie (no server-side store), bounded lifetimes, revocation by per-request re-evaluation; OAuth2 bearer for machine/MCP clients (hybrid); authn≠authz, scopes resolved into the RLS context per request | ADR-0011, ADR-0028 |
| Authorization & bootstrap | Fixed closed permission set, configurably mapped to roles; permissions cascade over the scope subtree; admin ≠ content permissions (separation preserved); review policies still own transitions; configured break-glass bootstrap admin; first-run auto-creates base + internal QMS scopes | ADR-0012 |
| User identity lifecycle | Identity anchored to a stable OIDC subject; invite (pre-provision) + JIT; states invited/active/deactivated; deactivation never deletes and preserves attribution; no shared human accounts | ADR-0013 |
| Electronic signatures | An approval becomes a signature when the policy requires it: signer + meaning + timestamp + content-hash binding + re-auth proof, manifested in renderings/exports; continuous-session step-up re-auth; configurable per policy; Part 11 / Annex 11-capable | ADR-0014 |
| Effectivity & periodic review | Effective date as a derived attribute (release ≠ effective); per-type periodic-review interval with recorded review evidence; optional validity; overdue/expired flagged & escalated, never auto-revoked | ADR-0015 |
| Retention, disposal & privacy | Retention-primary (retention outweighs erasure for regulated records); configurable retention + legal hold + deliberate audited disposal; minimization; pseudonymous attribution so PII can be severed; erasure narrow; crypto-shredding deferred to GAP-10 | ADR-0016 |
| Non-functional targets | Single-node "small" tier (~100 users, ~100k versions); ~99.5% business-hours availability, nightly backup (RPO ≤ 24h), RTO ≤ 1 business day; TLS + transparent at-rest encryption + dependency scanning + least-privilege DB role | ADR-0018 |
| Notifications & tasks | New event-driven notification module; distinct actionable tasks (tracked, assigned, reminders/escalation) vs. informational notifications; in-app inbox + pluggable email; scope-keyed under RLS; audit trail stays the record of truth |
ADR-0019 |
| Internationalization | UTC timestamps (unambiguous on signatures/audit), locale formatting; document content language per-document with translations as independently controlled linked documents; language-aware search | ADR-0020 |
| Draft cancellation | Terminal CANCELLED state from DRAFT/IN_REVIEW; abandoned versions retained & audited, never reopened | ADR-0024 |
| Disposal & erasure mechanics | Storage delete(hash); disposal removes content/manifest blobs + synchronously purges index rows; manifest persisted as a blob; backups forward-only within a bounded retention window |
ADR-0025 |
| RLS runtime safety | Scope context request-bounded (SET LOCAL/reset) so pooled connections can't leak scopes; separation test covers connection reuse; app-side scope resolution is the committed model |
ADR-0026 |
| Document relationships | One typed, directional relationship model (derived-from, translation-of, supersedes, references, related-to); provenance & translation are instances | ADR-0021 |
| Read-acknowledgement | Define required roles per document; track read/acknowledged with optional simple questionnaire; controlled records, tasks on release; not full training management | ADR-0022 |
| Migration/import | Import current released state + metadata as baseline (marked imported-from); prior history archived in source; detailed tooling deferred | ADR-0023 |