0.11.1: the arc42 examples cover all twelve sections

Numbered cards for the text sections (1.1-1.3, 2, 4, 11, 12) on the
overview, domain interfaces on the technical context, black-box
descriptions for every building block, blocks mapped to nodes in the
deployment view, crosscutting concepts on level 1, and a 1000-quality
folder with the quality tree. The example test checks each section's card.
This commit is contained in:
root-at-skic committed 2026-11-08 23:10:24 +02:00
1 parent 2ab4287f02
commit f4663c089d
23 files changed
+511 -91

No files matched your search

@@ -28,3 +28,12 @@ connections:
- { from: tickets, to: psp, label: REST webhook, variant: security }
- { from: tickets, to: mail, label: SMTP TLS }
- { from: tickets, to: pos, label: REST VPN }
cards:
- dot: cyan
title: 3 Domain interfaces
items:
- "Moviegoer: in shows, seats, payment start; out seat map, QR tickets"
- "Usher: in scanned QR codes; out valid or invalid, seat"
- "Payment provider: out checkout session; in paid or failed webhook"
- "E-mail service: out ticket e-mails with QR and receipt"
- "Box-office POS: in counter sales; out seat availability"
@@ -58,7 +58,9 @@ cards:
- dot: amber
title: 8 Crosscutting concepts
items:
- "Persistence: PostgreSQL is the truth; Redis only for holds"
- "Security: OIDC for staff apps; card data never stored"
- "Errors: idempotency keys; failed webhooks are retried"
- "Times in UTC; shown in cinema local time"
- "Every write carries an idempotency key"
- "QR payload signed with an Ed25519 key"
- "Structured logs with order id as trace key"
@@ -5,7 +5,10 @@ meta:
output: production.html
components:
- ref: customer
pos: [40, 160]
pos: [40, 260]
size: [130, 60]
- ref: mobile
pos: [40, 60]
size: [130, 60]
- id: ingress
type: security
@@ -44,6 +47,9 @@ boundaries:
- kind: security-group
label: Managed data zone
wraps: [seatlock, db]
- kind: region
label: Customer phones
wraps: [mobile]
- kind: region
label: Cinema site
wraps: [pos, scanner]
@@ -56,3 +62,13 @@ connections:
- { from: ticketing, to: db, label: TLS }
- { from: possync, to: pos, label: VPN, variant: security }
- { from: scanner, to: ingress, label: HTTPS }
- { from: mobile, to: ingress, label: HTTPS }
cards:
- dot: slate
title: 7 Mapping
items:
- "Web Shop, Booking API, Ticket Service, POS Sync -> EU k8s cluster"
- "Seat Locks -> managed Redis; Tickets DB -> managed PostgreSQL"
- "Mobile App -> customer phones"
- "Scanner App -> door phones at the cinema site"
- "Box-office POS -> cinema site, VPN to POS Sync"
@@ -0,0 +1,75 @@
schema_version: 1
diagram_type: architecture
meta:
title: Quality tree
output: quality-tree.html
components:
- id: quality
type: cloud
label: Quality
pos: [40, 260]
size: [130, 60]
- id: reliability
type: backend
label: Reliability
pos: [250, 60]
size: [130, 60]
- id: performance
type: backend
label: Performance
pos: [250, 210]
size: [130, 60]
- id: availability
type: backend
label: Availability
pos: [250, 360]
size: [130, 60]
- id: security
type: security
label: Security
pos: [250, 460]
size: [130, 60]
- id: s-nodouble
type: external
label: No double sale
pos: [460, 10]
size: [150, 60]
- id: s-payfail
type: external
label: Failed pay frees seats
pos: [460, 110]
size: [170, 60]
- id: s-peak
type: external
label: Checkout < 2 s at peak
pos: [460, 210]
size: [170, 60]
- id: s-offline
type: external
label: Offline door scans
pos: [460, 360]
size: [170, 60]
- id: s-forged
type: external
label: Forged QR rejected
pos: [460, 460]
size: [170, 60]
connections:
- { from: quality, to: reliability }
- { from: quality, to: performance }
- { from: quality, to: availability }
- { from: quality, to: security }
- { from: reliability, to: s-nodouble }
- { from: reliability, to: s-payfail }
- { from: performance, to: s-peak }
- { from: availability, to: s-offline }
- { from: security, to: s-forged }
cards:
- dot: emerald
title: 10 Quality scenarios
items:
- "500 holds on one show in 1 min: no seat sold twice"
- "Payment fails or is abandoned: seats free again within 8 min"
- "Friday 19:00 peak, 300 checkouts/min: p95 under 2 s"
- "Wi-Fi down at the door: scans go on, check-ins sync later"
- "Edited or forged QR code scanned: rejected at once"
@@ -3,13 +3,14 @@ model:
id: cinema-tickets
name: Cinema Tickets
description: >
An arc42 example: online and mobile seat booking for a small
cinema chain. This overview is section 3 (business context) with
cards for sections 1, 2, 10, 11 and 12. 0300-context holds the
technical context (3), 0500-building-blocks the building block
view (5), 0600-runtime the runtime view (6), 0700-deployment the
deployment view (7), decisions/ the architecture decisions (9).
Crosscutting concepts (8) are a card on the level-1 diagram.
An arc42 example: seat booking for the fictional Lantern Cinemas.
1 Requirements, quality goals, stakeholders; 2 Constraints;
4 Solution strategy; 11 Risks; 12 Glossary: cards on this overview.
3 Context: this overview (business) and 0300-context (technical).
5 Building blocks: 0500-building-blocks, black boxes in registry/.
6 Runtime: 0600-runtime. 7 Deployment: 0700-deployment.
8 Crosscutting concepts: card on 0500-building-blocks/level-1.
9 Decisions: decisions/. 10 Quality: 1000-quality.
diagram_type: architecture
meta:
title: Cinema Tickets - business context
@@ -40,12 +41,26 @@ connections:
- { from: tickets, to: mail, label: tickets }
- { from: tickets, to: pos, label: seat sales }
cards:
- dot: orange
title: 1.1 Requirements
items:
- "Browse shows and pick seats on a seat map"
- "Hold seats, pay online, get QR tickets by e-mail"
- "Ushers check tickets in at the door"
- "Box-office POS sells from the same seats"
- dot: cyan
title: 1 Quality goals
title: 1.2 Quality goals
items:
- "No seat is ever sold twice"
- "Checkout under 2 s at Friday peak"
- "Door check-in works offline"
- dot: amber
title: 1.3 Stakeholders
items:
- "Moviegoer: quick booking, tickets on the phone"
- "Usher: fast scans even without Wi-Fi"
- "Box-office staff: one seat map with online sales"
- "Lantern Cinemas management: fewer refunds, low cost"
- dot: slate
title: 2 Constraints
items:
@@ -53,16 +68,20 @@ cards:
- "Card data only at the provider"
- "Team of four; hosted in the EU"
- dot: emerald
title: 10 Quality scenarios
title: 4 Solution strategy
items:
- "500 holds on one show in 1 min: no double sale"
- "Wi-Fi down at the door: scans go on, sync later"
- "Payment fails: seats free again within 8 min"
- "Node.js, PostgreSQL, Redis on managed EU k8s: fits a team of four"
- "Three services by job: booking, tickets, POS sync"
- "No double sale: Booking API sole seat owner (booking-owns-seat-inventory)"
- "Checkout speed: Redis holds with TTL (seat-holds-with-ttl)"
- "Offline check-in: signed QR codes (signed-qr-codes)"
- dot: rose
title: 11 Risks
title: 11 Risks and technical debt
items:
- "POS vendor API is slow and undocumented"
- "Forwarded QR e-mails: first scan wins"
- "Risk: POS vendor API is slow and undocumented"
- "Risk: forwarded QR e-mails, first scan wins"
- "Debt: POS Sync adapter has no automated tests"
- "Debt: QR key rotation needs an app release"
- dot: violet
title: 12 Glossary
items:
@@ -6,52 +6,67 @@ elements:
sublabel: React
brand: react
description: >
Programme, seat map and checkout in the browser.
Responsibility: programme, seat map and checkout in the browser.
Interfaces: provides the web UI; requires Booking API (JSON)
and the provider's hosted checkout page.
mobile:
type: frontend
label: Mobile App
sublabel: iOS and Android
description: >
The same booking flow as the web shop, plus a ticket wallet.
Responsibility: the web shop's booking flow plus a ticket wallet.
Interfaces: provides the iOS/Android UI; requires Booking API
(JSON).
scanner:
type: frontend
label: Scanner App
sublabel: door phones
description: >
Reads QR codes at the door; checks signatures offline.
Responsibility: reads QR codes at the door, checks signatures
offline. Interfaces: provides the usher UI; requires Ticket
Service (POST /checkins), queued while offline.
booking:
type: backend
label: Booking API
sublabel: Node.js
brand: node-js
description: >
Shows, seat maps, seat holds and orders; the only writer of
the seat inventory.
Responsibility: shows, seat maps, holds and orders; the only
writer of the seat inventory. Interfaces: provides REST JSON to
the apps and the payment webhook; requires Seat Locks, Tickets
DB, payment provider, Ticket Service.
diagram: 0500-building-blocks/booking.archify
ticketing:
type: backend
label: Ticket Service
sublabel: QR, check-in
description: >
Issues signed QR tickets, sends them by e-mail and records
check-ins at the door.
Responsibility: issues signed QR tickets, mails them and records
check-ins. Interfaces: provides issue and POST /checkins;
requires Tickets DB and the e-mail service (SMTP).
possync:
type: backend
label: POS Sync
sublabel: adapter
description: >
Exchanges seat sales with the box-office POS in both directions.
Responsibility: exchanges seat sales with the box-office POS.
Interfaces: provides a REST adapter to the POS over VPN;
requires Tickets DB (SQL).
seatlock:
type: database
label: Seat Locks
sublabel: Redis
brand: redis
description: >
Short-lived seat holds with a TTL while the customer pays.
Responsibility: short-lived seat holds with a TTL while the
customer pays. Interfaces: provides Redis SET NX/GET/DEL to the
Booking API; requires nothing.
db:
type: database
label: Tickets DB
sublabel: PostgreSQL
brand: postgresql
description: >
Shows, seats, orders and tickets; the source of truth.
Responsibility: shows, seats, orders and tickets; the source of
truth. Interfaces: provides SQL to Booking API, Ticket Service
and POS Sync; requires nothing.
@@ -33,3 +33,13 @@ connections:
- { from: heat-pump, to: telemetry-platform, label: MQTT 8883, variant: emphasis, decisions: [mqtt-with-mutual-tls] }
- { from: telemetry-platform, to: push-service, label: HTTP/2 }
- { from: telemetry-platform, to: service-desk, label: webhook }
cards:
- dot: cyan
title: 3 Domain interfaces
items:
- "Heat pump: in telemetry and fault codes; out none"
- "Homeowner: in app requests; out status, history, alerts"
- "Ops engineer: in queries; out fleet dashboards"
- "Installer: in device serial; out device certificate"
- "Push service: out alert notifications"
- "Service desk: out tickets for faults needing a visit"
@@ -73,5 +73,8 @@ cards:
title: 8 Crosscutting concepts
items:
- Device identity, one X.509 certificate per device
- Security, OIDC login for people, mTLS for devices
- Persistence, PostgreSQL dialect for all stores
- Idempotent writes, keyed by device id and timestamp
- Error handling, invalid readings to dead letters
- Observability, metrics and traces on every service
@@ -29,6 +29,12 @@ components:
- ref: device-registry
pos: [760, 260]
size: [130, 60]
- ref: ops-dashboard
pos: [1030, 160]
size: [130, 60]
- ref: customer-app
pos: [490, 440]
size: [130, 60]
boundaries:
- kind: region
label: Kubernetes cluster, eu-central
@@ -36,9 +42,26 @@ boundaries:
- kind: security-group
label: Managed DB zone
wraps: [tsdb, device-registry]
- kind: region
label: Ops network, managed Grafana
wraps: [ops-dashboard]
- kind: region
label: Homeowner phones
wraps: [customer-app]
connections:
- { from: heat-pump, to: mqtt-broker, label: "8883", variant: emphasis }
- { from: mqtt-broker, to: ingest, label: in-cluster }
- { from: ingest, to: tsdb, label: "5432", variant: emphasis }
- { from: ingest, to: rules, label: gRPC }
- { from: device-api, to: device-registry, label: "5432" }
- { from: tsdb, to: ops-dashboard, label: read-only }
- { from: customer-app, to: device-api, label: HTTPS }
cards:
- dot: slate
title: 7 Mapping
items:
- "mqtt-broker, ingest, rules -> Kubernetes cluster, eu-central"
- "provisioning, device-api -> Kubernetes cluster, eu-central"
- "tsdb, device-registry -> managed DB zone, eu-central"
- "ops-dashboard -> ops network, managed Grafana"
- "customer-app -> homeowner phones, app stores"
@@ -0,0 +1,75 @@
schema_version: 1
diagram_type: architecture
meta:
title: Quality tree
output: quality-tree.html
components:
- id: quality
type: cloud
label: Quality
pos: [40, 240]
size: [130, 100]
- id: reliability
type: backend
label: Reliability
pos: [250, 60]
size: [130, 60]
- id: performance
type: backend
label: Performance
pos: [250, 210]
size: [130, 60]
- id: security
type: security
label: Security
pos: [250, 360]
size: [130, 60]
- id: operability
type: backend
label: Operability
pos: [250, 460]
size: [130, 60]
- id: q-no-loss
type: frontend
label: Broker restart, no loss
pos: [460, 60]
size: [180, 60]
- id: q-alert-60s
type: frontend
label: Fault alert in 60 s
pos: [460, 160]
size: [180, 60]
- id: q-peak-load
type: frontend
label: 4,000 readings/s
pos: [460, 260]
size: [180, 60]
- id: q-revoke
type: frontend
label: Revoke cert in 15 min
pos: [460, 360]
size: [180, 60]
- id: q-new-device
type: frontend
label: New device in 10 min
pos: [460, 460]
size: [180, 60]
connections:
- { from: quality, to: reliability }
- { from: quality, to: performance }
- { from: quality, to: security }
- { from: quality, to: operability }
- { from: reliability, to: q-no-loss }
- { from: performance, to: q-alert-60s }
- { from: performance, to: q-peak-load }
- { from: security, to: q-revoke }
- { from: operability, to: q-new-device }
cards:
- dot: emerald
title: 10 Quality scenarios
items:
- "Broker restarts under load: devices reconnect, no accepted reading lost"
- "Heat pump sends a fault code: homeowner gets a push within 60 s"
- "Fleet peaks at 4,000 readings/s: p95 ingest lag stays under 5 s"
- "A device certificate is stolen: ops revoke it, broker refuses it within 15 min"
- "Installer registers a new heat pump: data visible in the app within 10 min"
@@ -5,11 +5,14 @@ model:
description: >
An arc42 example: a fictional heat pump maker collects device telemetry
over MQTT, stores it, raises alerts and shows it to operations and customers.
main.archify holds section 3 business context with cards for sections
1 goals, 2 constraints, 10 quality, 11 risks and 12 glossary;
0300-context the technical context; 0500-building-blocks section 5;
0600-runtime section 6; 0700-deployment section 7; decisions/ section 9;
the crosscutting concepts of section 8 are a card on level-1.
Where the 12 arc42 sections live:
1 introduction and goals, 2 constraints, 4 solution strategy,
11 risks and 12 glossary are cards on this overview;
3 business context is this overview, technical context in 0300-context;
5 building blocks in 0500-building-blocks (black boxes in the registry);
6 runtime in 0600-runtime; 7 deployment in 0700-deployment;
8 crosscutting concepts a card on 0500-building-blocks/level-1;
9 decisions in decisions/; 10 quality tree in 1000-quality.
diagram_type: architecture
meta:
title: Business context
@@ -44,29 +47,47 @@ connections:
- { from: telemetry-platform, to: push-service, label: alerts }
- { from: telemetry-platform, to: service-desk, label: tickets }
cards:
- dot: orange
title: 1.1 Requirements
items:
- Collect telemetry from every heat pump every 30 s
- Alert homeowner and ops on fault codes
- Show live and historic data in app and dashboard
- Register and provision new devices on site
- dot: cyan
title: 1 Quality goals
title: 1.2 Quality goals
items:
- Reliability, no telemetry lost once accepted
- Timeliness, alert within 60 s of a fault
- Security, every device authenticated
- dot: emerald
title: 1.3 Stakeholders
items:
- "Homeowner: sees status, gets alerts quickly"
- "Ops engineer: fleet view, few false alarms"
- "Installer: register a device in minutes"
- "Firmware partner: stable MQTT contract"
- dot: slate
title: 2 Constraints
items:
- Devices speak MQTT only; firmware by a partner
- Data stays in one EU region
- Team of six; PostgreSQL skills in house
- dot: emerald
title: 10 Quality scenarios
- dot: amber
title: 4 Solution strategy
items:
- A fault code reaches the homeowner within 60 s
- Broker restart, devices reconnect, no data lost
- A stolen certificate is revoked within 15 min
- MQTT with mutual TLS for devices (security, ADR 0001)
- TimescaleDB for telemetry, SQL everywhere (ADR 0002)
- Ingest acks only after commit (reliability)
- Rules engine on the ingest stream (timeliness)
- Split by flow, ingest vs read vs provisioning
- dot: rose
title: 11 Risks
title: 11 Risks and technical debt
items:
- R1 fleet growth beyond one TSDB node
- R2 partner firmware delays certificate rotation
- "Risk: fleet growth beyond one TSDB node"
- "Risk: partner firmware delays cert rotation"
- "Debt: payload v1 decoder kept for old firmware"
- "Debt: rules configured in code, no UI"
- dot: violet
title: 12 Glossary
items:
@@ -5,14 +5,18 @@ elements:
label: MQTT broker
sublabel: mutual TLS
description: >
Terminates device connections; one topic per device.
Responsibility: terminates device connections, one topic per device.
Interfaces: provides MQTT 8883 with mTLS; requires certs and
revocation checks from Provisioning.
ingest:
type: backend
label: Ingest
sublabel: Go
brand: go
description: >
Decodes, validates and stores telemetry; forwards it to the rules.
Responsibility: decodes, validates and stores telemetry.
Interfaces: requires MQTT subscription, TSDB, device registry;
provides the reading stream to the rules engine.
diagram: 0500-building-blocks/ingest.archify
tsdb:
type: database
@@ -20,42 +24,52 @@ elements:
sublabel: TimescaleDB
brand: postgresql
description: >
Raw telemetry for 90 days and hourly rollups for 10 years.
Responsibility: raw telemetry 90 days, hourly rollups 10 years.
Interfaces: provides SQL on 5432 to Device API and dashboard;
requires batched writes from Ingest.
rules:
type: backend
label: Rules engine
sublabel: alerting
description: >
Evaluates thresholds and fault codes; raises alerts.
Responsibility: evaluates thresholds and fault codes, raises alerts.
Interfaces: requires the reading stream from Ingest;
provides alerts to the push service and service desk.
provisioning:
type: security
label: Provisioning
sublabel: device certs
description: >
Registers devices and issues their client certificates.
Responsibility: registers devices and issues client certificates.
Interfaces: provides a REST register call for installers and
revocation checks for the broker; requires the device registry.
device-registry:
type: database
label: Device registry
sublabel: PostgreSQL
brand: postgresql
description: >
Devices, owners, firmware versions and certificate state.
Responsibility: devices, owners, firmware and certificate state.
Interfaces: provides SQL on 5432 to Ingest, Provisioning, Device API.
device-api:
type: backend
label: Device API
sublabel: REST
description: >
Serves telemetry and device data to the customer app.
Responsibility: serves telemetry and device data to the customer app.
Interfaces: provides REST over HTTPS; requires TSDB and device registry.
ops-dashboard:
type: frontend
label: Ops dashboard
sublabel: Grafana
brand: grafana
description: >
Fleet view for the operations team, read only on the TSDB.
Responsibility: fleet view for the operations team.
Interfaces: provides web UI over HTTPS; requires read-only SQL on TSDB.
customer-app:
type: frontend
label: Customer app
sublabel: mobile
description: >
Shows the homeowner their heat pump and its alerts.
Responsibility: shows the homeowner their heat pump and alerts.
Interfaces: provides the mobile UI; requires Device API and push.
@@ -24,3 +24,11 @@ connections:
- { from: wiki-admin, to: wiki, label: kubectl }
- { from: wiki, to: idp, label: OIDC, variant: security }
- { from: wiki, to: object-store, label: S3 API }
cards:
- dot: cyan
title: 3 Domain interfaces
items:
- "Engineer: in edits, queries, files; out pages, results"
- "Wiki admin: in deploys, restore commands; out status, logs"
- "Identity provider: out sign-in code, groups; in token requests"
- "Object storage: out attachments, backups; in signed URL reads"
@@ -42,6 +42,9 @@ cards:
- dot: amber
title: 8 Crosscutting concepts
items:
- Access - every request checked against space groups
- Logs - JSON to stdout, collected by the cluster
- Config - environment variables, secrets from the vault
- "Security: OIDC session, every request checked against space groups"
- "Persistence: PostgreSQL is the only source of truth"
- "Errors: API returns problem JSON; the web app shows a retry"
- "Logging: JSON to stdout, collected by the cluster"
- "Backups: nightly dump to object storage, 30 days"
- "Config: environment variables, secrets from the vault"
@@ -36,8 +36,11 @@ boundaries:
label: Company cluster
wraps: [ingress, web, api, db, backup-job]
- kind: security-group
label: Namespace team-wiki
wraps: [web, api, db, backup-job]
label: App node pool
wraps: [web, api]
- kind: security-group
label: Data node
wraps: [db, backup-job]
connections:
- { from: engineer, to: ingress, label: HTTPS, variant: emphasis }
- { from: ingress, to: web, label: static }
@@ -46,3 +49,12 @@ connections:
- { from: api, to: idp, label: OIDC, variant: security, labelAt: [525, 234] }
- { from: backup-job, to: db, label: dump }
- { from: backup-job, to: object-store, label: S3 }
cards:
- dot: slate
title: 7 Mapping
items:
- "Web App -> app node pool, nginx pod, namespace team-wiki"
- "Wiki API -> app node pool, 2 pods behind the ingress"
- "Database -> data node, PostgreSQL stateful set with volume"
- "Backup job -> data node, Kubernetes CronJob"
- "Attachments, backups -> company object storage buckets"
@@ -0,0 +1,77 @@
schema_version: 1
diagram_type: architecture
meta:
title: Quality tree
output: quality-tree.html
legend:
mode: hidden
components:
- id: quality
type: cloud
label: Quality
pos: [40, 200]
size: [130, 120]
- id: usability
type: frontend
label: Usability
pos: [250, 60]
size: [130, 60]
- id: security
type: security
label: Security
pos: [250, 160]
size: [130, 60]
- id: reliability
type: backend
label: Reliability
pos: [250, 310]
size: [130, 60]
- id: maintainability
type: backend
label: Maintainability
pos: [250, 460]
size: [130, 60]
- id: q-search
type: external
label: Search under 1 s
pos: [460, 60]
size: [170, 60]
- id: q-leaver
type: external
label: Leaver out in 5 min
pos: [460, 160]
size: [170, 60]
- id: q-restore
type: external
label: Restore in 30 min
pos: [460, 260]
size: [170, 60]
- id: q-pod
type: external
label: Pod back in 1 min
pos: [460, 360]
size: [170, 60]
- id: q-upgrade
type: external
label: Upgrade in 1 hour
pos: [460, 460]
size: [170, 60]
connections:
- { from: quality, to: usability }
- { from: quality, to: security }
- { from: quality, to: reliability }
- { from: quality, to: maintainability }
- { from: usability, to: q-search }
- { from: security, to: q-leaver }
- { from: reliability, to: q-restore }
- { from: reliability, to: q-pod }
- { from: maintainability, to: q-upgrade }
cards:
- dot: emerald
title: 10 Quality scenarios
items:
- "Search: an engineer searches 5000 pages; results in under 1 s"
- "Leaver: HR disables an account; wiki access ends within 5 minutes"
- "Restore: the database is lost; the admin restores last night in 30 minutes"
- "Crash: an API pod dies; the cluster restarts it, no data lost, back in 1 minute"
- "Upgrade: a new wiki version ships; one admin rolls it out in 1 hour"
+42 -23
View File
@@ -3,12 +3,14 @@ model:
id: team-wiki
name: Team Wiki
description: >
An arc42 example: a small self-hosted wiki for an engineering
team. Sections 1 goals, 2 constraints, 3 business context,
10 quality, 11 risks and 12 glossary are on this overview;
0300-context holds 3 technical context, 0500-building-blocks
5 building blocks, 0600-runtime 6 runtime, 0700-deployment
7 deployment and decisions 9 architecture decisions.
An arc42 example: a small self-hosted wiki for an engineering team.
1 Requirements, quality goals, stakeholders; 2 Constraints;
4 Solution strategy; 11 Risks; 12 Glossary: cards on this overview.
3 Context: this overview (business) and 0300-context (technical).
5 Building blocks: 0500-building-blocks, black boxes in registry/.
6 Runtime: 0600-runtime. 7 Deployment: 0700-deployment.
8 Crosscutting concepts: card on 0500-building-blocks/level-1.
9 Decisions: decisions/. 10 Quality: 1000-quality.
diagram_type: architecture
meta:
title: Team Wiki - business context
@@ -36,31 +38,48 @@ connections:
- { from: wiki, to: idp, label: sign-in, variant: security }
- { from: wiki, to: object-store, label: files }
cards:
- dot: cyan
title: 1 Quality goals
- dot: orange
title: 1.1 Requirements
items:
- Findability - any page found in two searches
- Security - only current staff can read
- Operability - one person runs it in an hour a week
- "Create, edit and version pages in team spaces"
- "Full-text search over every page a user may read"
- "Attach files to pages"
- "Admin restores the wiki from a nightly backup"
- dot: cyan
title: 1.2 Quality goals
items:
- "Findability: any page found in two searches"
- "Security: only current staff can read"
- "Operability: one person runs it in an hour a week"
- dot: amber
title: 1.3 Stakeholders
items:
- "Engineer: fast search, simple editor"
- "Wiki admin: little routine work, easy restore"
- "Security officer: no access after leaving"
- "Team lead: one place for team knowledge"
- dot: slate
title: 2 Constraints
items:
- Runs on the company Kubernetes cluster
- Sign-in only via the company identity provider
- "Runs on the company Kubernetes cluster"
- "Sign-in only via the company identity provider"
- dot: emerald
title: 10 Quality scenarios
title: 4 Solution strategy
items:
- A search over 5000 pages answers in under 1 s
- A leaver loses access within 5 minutes
- The admin restores last night's state in 30 minutes
- "React, Node.js API, PostgreSQL: one stack the team knows"
- "Three blocks plus a backup job: operability"
- "Findability: PostgreSQL full-text search (postgres-full-text-search)"
- "Security: OIDC at the company IdP only (sso-only-via-company-idp)"
- "Operability: files and backups in company object storage"
- dot: rose
title: 11 Risks
title: 11 Risks and technical debt
items:
- Identity provider outage blocks all sign-ins
- Backups untested until a restore drill is run
- "Risk: identity provider outage blocks all sign-ins"
- "Risk: backups untested until a restore drill is run"
- "Debt: attachments are not virus-scanned yet"
- dot: violet
title: 12 Glossary
items:
- Space - pages of one team, mapped to a group
- Revision - one saved version of a page
- Attachment - a file stored beside a page
- "Space: pages of one team, mapped to a group"
- "Revision: one saved version of a page"
- "Attachment: a file stored beside a page"
@@ -6,15 +6,17 @@ elements:
sublabel: React
brand: react
description: >
Page editor, viewer and search box in the browser; talks
only to the API.
Responsibility: page editor, viewer and search box in the
browser. Interfaces: provides the UI over HTTPS; requires
the Wiki API (JSON).
api:
type: backend
label: Wiki API
sublabel: REST
description: >
Pages, search, attachments and access checks; the only
writer of the database.
Responsibility: pages, search, attachments and access checks;
the only writer of the database. Interfaces: provides REST
JSON; requires the IdP (OIDC), the database (SQL), object storage (S3).
diagram: 0500-building-blocks/wiki-api.archify
db:
type: database
@@ -22,12 +24,14 @@ elements:
sublabel: PostgreSQL
brand: postgresql
description: >
Pages, revisions, users and the full-text index; the
source of truth.
Responsibility: pages, revisions, users and the full-text
index; the source of truth. Interfaces: provides SQL to the
API and dumps to the backup job.
backup-job:
type: backend
label: Backup job
sublabel: nightly
description: >
Dumps the database at 02:00 and writes it to the backup
bucket; keeps 30 days.
Responsibility: dumps the database at 02:00, keeps 30 days.
Interfaces: requires the database (pg_dump) and the backup
bucket (S3); provides none.