Documentation Strategy — Design Spec¶
Date: 2026-04-27 Status: Draft for review Author: Jim Holmes (with brainstorming session) Tracking issue / PR: TBD
1. Purpose & scope¶
Build the documentation surface for the clinical-data-model platform across multiple audiences (SMT, internal tech team, auditors, regulators, integrators, procurement) so that the platform is presentable, audit-ready, and discoverable without a forcing event.
Mode: general readiness — no specific deadline (e.g. an audit, regulatory filing, or named customer) is driving this work. Scope decisions optimise for breadth-first scaffolding so structure is in place even if individual artifacts are filled in over time.
Approach: stay in CLI / git-versioned text for ~80% of the work — markdown narratives, Mermaid/D2 diagrams, generated artifacts (SBOM, license inventory, OpenAPI). Switch to graphical tooling only for one-off polished hero visuals (board / SMT decks).
2. Audience priorities (v1)¶
2.1 v1 content (real narratives + content)¶
- SMT / leadership — exec-level capability and direction overview; ≤10 pages total
- Tech team (internal) — architecture, service catalogue, cross-service flows, runbook templates; mostly aggregation of existing specs/plans
- Compliance pack (auditors + regulatory) — combined because the artifact set overlaps heavily for a medical device platform; security model + data model + audit + retention narratives, plus auto-generated SBOM, licenses, SOUP
2.2 v1 scaffold-only (placeholder + auto-generated)¶
- Integrators — placeholder index + auto-generated OpenAPI per service; getting-started guides deferred until a real integration partner needs them
- Procurement / commercial — auto-generated license inventory; sub-processor list deferred (manual artifact)
2.3 Deferred from v1 (no v1 ship)¶
- Risk management file (ISO 14971-style) — large, medical-device-specific, needs clinical input
- Threat model (STRIDE-style) — valuable but a separate engagement
- Traceability matrix (req → design → code → tests) — useful only when a regulator asks specifically
- Pen test summary — external work
- Reviewer-facing UI — separate frontend track (out of doc scope)
3. Audience-specific v1 deliverables¶
3.1 SMT — 4 documents + 1 hero diagram¶
| File | Purpose |
|---|---|
audiences/smt/overview.md |
Executive narrative: what the platform is, who it serves, current state |
audiences/smt/capability-map.md |
Plain-English description of each module (clinical-api, ai-review, orchestrator, human-review, etc.) |
audiences/smt/architecture-glance.md |
Single architecture diagram + 1-paragraph intro |
audiences/smt/roadmap.md |
Shipped / next / deferred snapshot |
3.2 Tech team — service catalogue + per-service deep-dives + flows + runbooks¶
| File / folder | Purpose |
|---|---|
audiences/tech/README.md |
Service catalogue index — 8 services + 3 packages, one-liner each |
audiences/tech/services/{service}.md |
Per-service summary: purpose, key endpoints, key DB tables, dependencies, link to spec |
audiences/tech/packages.md |
Shared package overview (@sa-platform/{events,common,auth-client,...}) |
audiences/tech/flows/ai-review-flow.md |
Sequence diagram + narrative |
audiences/tech/flows/orchestrator-flow.md |
Orchestrator-driven workflow flow |
audiences/tech/runbooks/service-down-triage.md |
Starter runbook: incident triage |
audiences/tech/runbooks/deployment-rollback.md |
Starter runbook: deploy rollback |
audiences/tech/runbooks/database-migration.md |
Starter runbook: Prisma migration ops |
audiences/tech/adrs/README.md |
Index pointing at docs/superpowers/specs/ (ADR-style design records already exist) |
3.3 Compliance pack — 5 narratives + 4 generated artifacts¶
| File / artifact | Type | Purpose |
|---|---|---|
audiences/compliance/README.md |
HW | Pack overview + entry point |
audiences/compliance/security-model.md |
HW | Auth (OAuth2, JWT, scopes), encryption (at rest + in transit), tenancy isolation, secrets handling |
audiences/compliance/data-model-phi.md |
HW | PHI classification table + data flow + storage |
audiences/compliance/audit-trail.md |
HW | What's logged, by which service, retention semantics |
audiences/compliance/retention-erasure.md |
HW | Retention policy mechanism, GDPR Article 17 erasure flow, crypto-shredding |
audiences/compliance/architecture.md |
HW | Network topology, service map, data-flow diagram (D2 / Mermaid) |
audiences/compliance/generated/sbom.cdx.json |
AG | CycloneDX SBOM |
audiences/compliance/generated/sbom.spdx.json |
AG | SPDX SBOM (FDA-preferred format) |
audiences/compliance/generated/licenses.{json,md} |
AG | Dependency license inventory |
audiences/compliance/generated/soup.md |
AG + HW | SOUP (Software of Unknown Provenance) classification |
3.4 Integrators — scaffold + auto-generated¶
| File | Purpose |
|---|---|
audiences/integrators/README.md |
"Coming soon" + pointer to current state |
audiences/integrators/generated/openapi/{service}.json |
Per-service OpenAPI specs (from NestJS Swagger module) |
3.5 Procurement — scaffold + auto-generated¶
| File | Purpose |
|---|---|
audiences/procurement/README.md |
Scaffold |
audiences/procurement/generated/licenses.md |
Same source as compliance/generated |
audiences/procurement/sub-processors.md |
Hand-written; auto-list in v2 |
4. Repository structure¶
docs/
├── README.md # Top-level discovery: "I'm an X, take me to Y"
├── CONTRIBUTING.md # How to add a doc, frontmatter, owner conventions
├── audiences/
│ ├── smt/
│ │ ├── overview.md
│ │ ├── capability-map.md
│ │ ├── architecture-glance.md
│ │ └── roadmap.md
│ ├── tech/
│ │ ├── README.md
│ │ ├── services/{ai-review,orchestrator,human-review,clinical-api,consent,auth,notifications,user-management}.md
│ │ ├── packages.md
│ │ ├── flows/{ai-review-flow,orchestrator-flow}.md
│ │ ├── runbooks/{service-down-triage,deployment-rollback,database-migration}.md
│ │ └── adrs/README.md
│ ├── compliance/
│ │ ├── README.md
│ │ ├── security-model.md
│ │ ├── data-model-phi.md
│ │ ├── audit-trail.md
│ │ ├── retention-erasure.md
│ │ ├── architecture.md
│ │ └── generated/
│ │ ├── sbom.cdx.json
│ │ ├── sbom.spdx.json
│ │ ├── licenses.{json,md}
│ │ ├── soup.md
│ │ └── README.md # "Generated by scripts/generate-docs.sh — do not edit"
│ ├── integrators/
│ │ ├── README.md
│ │ └── generated/openapi/{service}.json
│ └── procurement/
│ ├── README.md
│ └── generated/licenses.md
├── superpowers/ # EXISTING — not moved
│ ├── specs/
│ └── plans/
└── diagrams/ # Single source of truth for diagram source
├── architecture-glance.mmd
├── ai-review-sequence.mmd
├── orchestrator-sequence.mmd
├── network-topology.d2
└── data-model-erd.mmd
Key choices:
- Audience-segmented top-level discovery. Top-level
docs/README.mdroutes readers ("If you're an auditor, start ataudiences/compliance/; if you're a developer onboarding, start ataudiences/tech/"). Lower friction than a single flat index. - Generated subdirectories per audience. Auto-emitted artifacts live next to the audience that consumes them, marked do-not-edit. Same SBOM may be referenced from multiple audiences — easiest is to generate to one location and symlink, or simply re-emit (generation is cheap).
diagrams/as single source of truth. All Mermaid.mmdand D2.d2source files in one place; markdown docs reference rendered SVG output. Updates flow source → all consumers.superpowers/stays intact. Design specs and plans are engineering history, not audience-facing. Tech ADR index links to them; structure doesn't move.
Alternatives considered and rejected:
- By artifact type (
docs/diagrams/,docs/runbooks/,docs/policies/) — clean for editors, hostile for readers. Less friendly for "I'm an auditor, where do I start?". - Single flat
docs/with naming conventions — simplest, but quickly noisy at this many artifact types.
5. Generation toolchain¶
All tools CLI-driven, scripted, and CI-runnable. Added to root devDependencies or installed in CI only.
| Artifact | Tool | Source | Output |
|---|---|---|---|
| SBOM (CycloneDX) | @cyclonedx/cdxgen |
pnpm-lock.yaml |
sbom.cdx.json |
| SBOM (SPDX) | cdxgen --output-format spdx-json |
same | sbom.spdx.json |
| License inventory | pnpm licenses list --json |
runtime deps | licenses.json + licenses.md |
| SOUP classification | custom script | merges CycloneDX + manual soup-classification.yaml |
soup.md |
| OpenAPI per service | NestJS Swagger module + @nestjs/swagger CLI |
controllers | openapi/{service}.json |
| Mermaid → SVG | @mermaid-js/mermaid-cli (mmdc) |
.mmd source |
.svg |
| D2 → SVG | d2 CLI |
.d2 source |
.svg |
| Markdown → PDF | pandoc + custom template |
per-audience folder | compliance-pack.pdf etc. |
Scripts:
scripts/generate-docs.sh— orchestrator script, runs all sub-scriptsscripts/docs/sbom.sh— SBOM generation (both formats)scripts/docs/licenses.sh— license inventoryscripts/docs/soup.sh— SOUP classification (merges generated + manual classifications)scripts/docs/openapi.sh— per-service OpenAPI export (one Swagger CLI invocation per service)scripts/docs/diagrams.sh— render Mermaid + D2 sources to SVGscripts/docs/pdf.sh— Pandoc-driven per-audience PDF bundles
6. Cadence & freshness¶
On every commit to main (CI): regenerate SBOM, licenses, OpenAPI, Mermaid SVGs. Recommend keeping generated files out of git (built artifacts only); served via GitHub Pages or attached to CI runs. Reduces diff noise; eliminates stale-generated-file failure mode.
On every release tag (CI): full doc bundle build — SBOMs cryptographically signed (e.g. via cosign), per-audience PDFs generated via Pandoc, attached to the GitHub release. This is what auditors get a link to.
Manual / on-demand: hand-written narratives. Each document has a last_reviewed frontmatter field; scripts/docs/check-staleness.sh runs in CI and warns if any doc hasn't been reviewed in 90 days. Soft warning, not failing.
Per-PR: a path-based mapping (.github/docs-codeowners.yml) flags affected docs in PR descriptions. If a PR touches services/clinical-api/src/auth/..., the PR description gets a comment: "Consider reviewing docs/audiences/compliance/security-model.md for accuracy."
7. Export formats¶
- Markdown source — primary format, lives in repo, rendered by GitHub
- HTML site — generated via
mkdocs materialordocusaurus, deployed to GitHub Pages on every commit to main. Single discovery URL for all audiences. Worth doing in v1 because auditors prefer a portal link, not a tarball. - PDF — per-audience PDF generated via Pandoc on release tag; specifically:
compliance-pack.pdf(everything inaudiences/compliance/+audiences/compliance/generated/*)tech-pack.pdf(selective tech-audience content; less critical but useful for onboarding new engineers offline)smt-summary.pdf(4 docs + hero diagram, for board/exec)- SBOM — CycloneDX JSON + SPDX JSON, both formats. Different consumers prefer different ones (FDA leans SPDX; most tooling speaks CycloneDX).
8. Update governance¶
Each markdown file gets a frontmatter block:
---
title: Security Model
audience: compliance
owner: tech-lead
last_reviewed: 2026-04-27
review_cycle_days: 90
---
scripts/docs/check-staleness.sh reads the frontmatter, warns on stale docs in CI (non-blocking on PR; daily summary as a separate workflow).
docs/CONTRIBUTING.md documents:
- How to add a new doc to a given audience
- Where to put diagrams (
docs/diagrams/) — and the source-then-render pipeline - Naming + frontmatter convention
- How generated artifacts work (don't manually edit; how to regenerate locally)
- Review cycle expectations per audience
- How the per-PR doc-impact mapping works
Each audiences/*/README.md lists the audience-level owner and review cadence as a whole.
9. v1 ship list (consolidated)¶
| Audience | v1 deliverable |
|---|---|
| SMT | 4 markdown docs (overview, capability-map, architecture-glance, roadmap) + 1 architecture Mermaid diagram |
| Tech | Service catalogue + 8 per-service summaries + 1 packages doc + 2 flow diagrams + 3 runbook templates + ADR index |
| Compliance | 5 narrative docs (security-model, data-model-phi, audit-trail, retention-erasure, architecture) + 4 generated artifacts (CycloneDX SBOM, SPDX SBOM, licenses, SOUP) |
| Integrators | Scaffold + auto-generated OpenAPI per service |
| Procurement | Scaffold + auto-generated license inventory |
Generation toolchain: 6 scripts in scripts/docs/ + 1 orchestrator script. CI workflow on every commit (artifacts as outputs) and every release tag (full bundle attached).
Static site: MkDocs Material build pointed at docs/, deployed to GitHub Pages on every commit to main.
PDFs: Pandoc + custom template, generated on release tag, attached to GitHub release.
Governance: frontmatter staleness check (90-day default, soft warning) + per-PR diff awareness via path-based docs-codeowners mapping.
10. Out-of-scope / deferred¶
- ISO 14971 risk management file (medical-device-specific; large effort)
- STRIDE-style threat model (valuable; separate engagement)
- Traceability matrix (req → design → code → tests; only useful when a regulator asks)
- Pen test summary (external work)
- Hand-drawn / branded SMT visuals (one-off, may be done in Claude.ai if needed)
- Reviewer-facing UI documentation (separate frontend track)
- Customer-specific security review packs (driven by named customers; templated from compliance pack when one arrives)
- Translated / localised documentation (English only in v1)
- Live "documentation as code" portal (e.g. Backstage TechDocs) — MkDocs Material is the v1 pragmatic choice
- Automated linting of doc prose (e.g. Vale, Alex) — could add later, not v1
11. Open questions for implementation plan¶
- MkDocs vs Docusaurus for the static HTML site. MkDocs Material is simpler to bootstrap and renders Mermaid natively; Docusaurus has stronger React-based extensibility. Lean MkDocs for v1; Docusaurus if a richer interactive surface is later needed.
- SBOM signing tool — cosign is the most common; consider whether the existing CI has the appropriate secrets infrastructure or if it needs to be set up.
- Where to host the static site: GitHub Pages (free, simple) vs. an internal docs domain (e.g.
docs.skinanalytics.internalvia a separate static-host pipeline). v1 default GitHub Pages on the repo'sgh-pagesbranch. - Diagram source format split — Mermaid for sequence/architecture diagrams is fine; for network topology, D2 vs Graphviz vs Excalidraw text format. Lean D2 for the network diagram only; Mermaid everywhere else.
- OpenAPI extraction — NestJS Swagger module needs to be installed and configured per service; some services may already have it (verify ai-review, orchestrator), others may not. Implementation plan should audit.