This directory records every architecture decision from technical-architecture.md, one decision per ADR. ADRs 0001–0007 resolve specific contradictions. ADRs 0008–0070 capture the rest of the architecture document.
Each ADR has Status, Date, Scope, Source, and Related fields, followed by Context, Decision, Consequences, and ToDos sections.
- Scope follows ADR 0007:
Required (v1),Required (production)/Required (before first production release),Conditional, orDeferred. - Source links the section of the architecture document the decision was taken from.
Every open point starts with ToDo: and one of these tags:
| Tag | Meaning |
|---|---|
[Contradiction] |
Two statements in the architecture (or between ADRs) conflict. One must change. |
[Clarify] |
The statement is vague or leaves a choice open. |
[Missing] |
Something another decision depends on is not decided at all. |
[Verify] |
A factual assumption (versions, upstream project status, tool behaviour) that should be checked against current sources. |
List them all with:
grep -rn "ToDo:" docs/adr/
grep -rn "ToDo: \[Contradiction\]" docs/adr/ToDo: review the ADRs as a set and reconcile any remaining open questions before implementation begins.
- 0001 - Include Valkey in the production deployment
- 0002 - Treat object storage as a v1 capability with feature-gated bucket adoption
- 0003 - Separate direct local development from containerized integration testing
- 0004 - Keep the repo boundary separate from the external infrastructure repo
- 0005 - Use Alloy/Loki for production logs and reserve Dozzle for private operator access
- 0006 - Keep NFS backups separate from application object storage
- 0007 - Classify baseline requirements versus future enhancements
- 0008 - Use FeathersJS v5 with TypeScript for the API
- 0009 - Pin Node.js 22 LTS and pnpm 10 across all environments
- 0010 - Use TypeScript strict mode with additional index-access checks
- 0011 - Use PostgreSQL 17 as the system of record
- 0012 - Use the Feathers Knex adapter and explicit, deployment-time migrations
- 0013 - Use TypeBox schemas and enforce validation and authorization at the service boundary
- 0014 - Put PgBouncer in session pooling mode between the API and PostgreSQL
- 0015 - Separate database roles and connection paths for API, migrations, and backups
- 0016 - Use a pnpm workspace monorepo without a task orchestrator
- 0017 - Share Feathers service contracts in
packages/contracts; defer OpenAPI - 0018 - Target repository layout
- 0019 - Single shared application context without multi-tenancy in v1
- 0020 - v1 domain model of shared-app users plus a basic document/profile object
- 0021 - Role-based authorization with
feathers-casl(owner, admin, user)
- 0022 - Use Feathers local email/password authentication
- 0023 - Hybrid JWT authentication with in-memory access tokens and an HttpOnly refresh cookie
- 0024 - Store rotating refresh sessions in PostgreSQL
auth_sessions - 0025 - Valkey-backed, fail-closed rate limits for login and password reset
- 0026 - Require real email delivery for password reset and verification before production
- 0027 - Record minimal, successful activity events with 90-day retention
- 0028 - Daily maintenance job for session and activity-event cleanup
- 0029 - Build the frontend with Vue 3, Quasar (Vite), and
feathers-pinia - 0030 - Ship the frontend as a static-asset container image
- 0031 - Frontend security baseline (CSP, safe rendering, dependency hygiene)
- 0032 - Route production traffic through external Nginx to loopback-published API and web containers
- 0033 - Expose only HTTPS (and optional HTTP) publicly on the production host
- 0034 - Run production on one Linux host with rootless Podman and systemd Quadlet
- 0035 - Segment production containers into
backend,object, andmonitoringnetworks - 0036 - Use rootless Podman everywhere and run images as non-root users
- 0037 - Define local/CI topology in
compose.yamland production in Quadlet units - 0038 - Build production images on the host from versioned release sources; no registry initially
- 0039 - Release procedure of backup, migrate, validate, switch, with image-tag rollback
- 0040 - Defer scale-out (separate database/Valkey nodes, multiple hosts)
- 0041 - PostgreSQL operations baseline (storage, tuning, major upgrades)
- 0042 - Expand-and-contract migrations; roll back code, not schema
- 0043 - Self-host S3-compatible object storage (MinIO as initial candidate)
- 0044 - Mediate all browser object access through the API; defer presigned URLs
- 0045 - Limit uploads to 50 MiB and an explicit type allowlist, streamed without buffering
- 0046 - Separate buckets for uploads and exports; backup staging bucket only in local/CI
- 0047 - Best-effort RPO of 48 hours and RTO of 4 hours; defer WAL archiving
- 0048 - Daily
pg_dumpencrypted with restic onto NFS, retained 30 days - 0049 - Coordinated daily object export with a write pause, snapshotted by restic
- 0050 - Dedicated, mandatory NFS mount at
/srv/backupswith no local fallback - 0051 - Run backups in an isolated, unattended rootless container with separate credentials
- 0052 - Monthly full restore drills and CI restore tests define backup validity
- 0053 - Local development environment, ports, and explicit seeding
- 0054 - Repository-owned, test-only Nginx for integration and end-to-end tests
- 0055 - Use
mkcertfor local HTTPS in the test Nginx profile - 0056 - GitHub Actions CI building the deployment Containerfiles and testing against an ephemeral stack
- 0057 - Split tests into unit, integration, and end-to-end layers with isolated data
- 0058 - Playwright end-to-end tests against the built frontend behind test Nginx
- 0059 - Create production initial data only through a manual, one-time bootstrap command
- 0060 - Separate private liveness and readiness endpoints
- 0061 - Structured JSON logs to stdout without secrets
- 0062 - Private Prometheus
/metricsendpoint including bounded business aggregates - 0063 - Authenticated
/statsAPI for application dashboards, separate from/metrics - 0064 - Self-hosted Grafana, Prometheus, Loki, Alloy, and Dozzle on the production host with fixed budgets
- 0065 - Baseline alert set with an owner and response action per alert
- 0066 - Defer distributed tracing (OpenTelemetry, Grafana Tempo)
- 0067 - Host-managed secrets and environment-based configuration; no secrets platform yet
- 0068 - API security baseline (origins, least privilege, consistent hooks, updates)
- 0069 - Documentation convention (README, architecture overview, ADRs)
- 0070 - Keep deployment-specific values outside the repository; define pre-production deliverables