ADR-0068: Confluence/Jira QMS Import — Staged, Read-Only, Repeatable¶
- Status: accepted (mapping M-1..M-7 confirmed by Nicolas 2026-07-14: "sounds good to me"; staging repeatability explicitly requested the same day)
- Date: 2026-07-14
- Deciders: Nicolas Burri (mapping decisions, access model), design by Claude from the live recon.
- Relates to: ADR-0064 (workflow role bindings — the import's Autor/Prüfer/Freigeber target), ADR-0065 (diagram attachment valve — the draw.io landing), ADR-0052/0053 (acknowledgements — the schulungspflichtig mapping), ADR-0007 (server-enforced authz — the importer is a plain API client), ADR-0044 (search indexing happens as a consequence of normal writes).
- Amended by: ADR-0075 (M-4/M-7 — prior version history arrives as a claims record, continuity without forged audit).
- Superseded for real instances by: ADR-0113 (project arrival import: released documents arrive released with their true approved bodies, source dates and EXTERNAL authors; nothing backdated).
Context¶
The company QMS lives in the Johner Institute eQMS: a Confluence space (~454 pages, one page per
document plus navigation; draw.io diagrams as attachments) joined to a Jira project (one ticket
per document carrying the lifecycle: type, state, released version, role-coded Autor/Prüfer/
Freigeber, training flag, periodic-review date, purpose/scope texts, Confluence page URL). Access
is via two product-scoped read tokens of a restricted account (scoped tokens work only against
api.atlassian.com/ex/{product}/{cloudId}/…). The import feeds an extended functional test of
LQMS with real structure — it is NOT (yet) a validated migration.
Decision¶
- Two-phase, staged, repeatable. Phase FETCH (rare, the only phase touching Atlassian,
strictly read-only) snapshots pages, bodies, attachments and tickets into
import-staging/(git-ignored; imported content NEVER enters the repository). Phase LOAD (frequent, offline) transforms the snapshot and writes into a local LQMS stack through the public REST API as a normal authenticated client — no SQL side door, so RLS/authz/audit/search behave exactly as in production use. After any stack reset the LOAD re-runs identically; idempotency is keyed by source page id (a re-run against a stack already carrying an import is detected and skipped, not duplicated). - Mapping (M-1..M-7, confirmed):
- M-1 One scope; the page tree becomes the folder tree.
- M-2 Document types 1:1: SOP, WI, TPL, REC, DOC, QM.
- M-3 Their role codes (QMB, TL, HOT, GL, …) become catalog roles; each document's Autor/Prüfer/Freigeber binds into the AUTHOR/REVIEWER/RELEASER groups (ADR-0064). User staffing is NOT imported; demo personas receive a few key roles to drive the flows.
- M-4 Current released version only: "Dokument in Verwendung" → RELEASED (source version number recorded), "Dokument obsolet" → REVOKED, "unspezifiziertes Dokument"/ticketless → DRAFT. Page-version history stays in the source (provenance link) — replaying it here would fabricate audit trails nobody attested.
- M-5 Storage-XML → content tree natively (headings/tables/lists/images/links); info/note/warning → admonitions; expand → heading+body; toc/jira/document-state/Scroll macros dropped (their data is captured as metadata); internal page links → doc-link references in a second pass; Zweck/Anwendungsbereich render as a metadata header section.
- M-6 draw.io sources + PNG previews imported as attachment pairs (ADR-0065 valve:
source preserved, preview displayed, Excalidraw conversion optional later); PDF/Office
attachments carried;
.tmpautosaves skipped. - M-7 Provenance on every imported version (source page URL, page version, ticket key, fetch timestamp); the import runs as a dedicated persona; schulungspflichtig=ja → acknowledgement required; periodic-review due dates recorded.
- Trial-first rollout: the first LOAD covers one representative process area (DC — Document Control) for Nicolas's inspection; the full run follows his go.
Consequences¶
- New
import-staging/git-ignore entry; importer scripts live underscripts/import/(code in git, data never). - The importer needs an LQMS API token/user with CREATE/EDIT/workflow permissions in the target scope — provisioned by the seed, like the demo personas.
- RELEASED imports must pass our own gates (submit/approve/release by the import persona wearing the required roles) — the audit trail will honestly show the import persona, not fabricated historical actors; source actors stay visible in the provenance block.
- Refreshing from the live system is an explicit re-FETCH; drift between snapshot and live Confluence is expected and acceptable for the test-data use case.