AUG 2026
ADR 0082
31 Aug 2026
Run infrastructure probes as Rust integration tests in the CI suite
Infrastructure checks are tests in the suite CI runs, reading the configuration that's actually deployed.
ADR 0080
23 Aug 2026
Check the GraphQL schema against a committed compatibility floor
The schema only grows, and the build checks it against a committed floor of the oldest supported schema.
ADR 0079
23 Aug 2026
Bound GraphQL request cost at input size instead of per-field query complexity
Limits go on input size where data enters, and superlinear reads are bugs to fix.
ADR 0078
12 Aug 2026
Grant tailnet membership reachability only, and make every service authenticate
Being on the tailnet grants reachability and no authority, so every service authenticates on its own.
JUL 2026
ADR 0075
29 Jul 2026
Converge concurrent edits by id-addressed replay and escalate non-commuting pairs
Concurrent edits converge by replay, and combinations nobody intended are flagged to a person.
ADR 0074
27 Jul 2026
Address destinations by id and batch-local handles in the effect vocabulary
Effects name destinations by id, with batch-local handles for things created in the same batch.
ADR 0073
20 Jul 2026
Replay the effect log on-device through a shared Rust core
The app replays the trip locally through the same Rust core the server runs, and syncs changes it has already applied.
JUN 2026
ADR 0070
15 Jun 2026
Build native macOS from the iOS SwiftUI target with an adaptive NavigationSplitView root
One target serves both platforms: presentation adapts to the platform and logic never forks.
ADR 0069
12 Jun 2026
Replace the pre-merge click-through with Maestro flows run locally on maestro-runner
Black-box Maestro flows against a seeded backend replace the manual check before merging, run locally.
ADR 0068
3 Jun 2026
Deploy NixOS nodes with Colmena, building closures on an ephemeral x86 Hetzner builder
Nodes run NixOS and deploy with Colmena, with closures built on a throwaway x86 machine that holds no cluster credentials.
MAY 2026
ADR 0049
9 May 2026
Replace upsert effects with create, update and remove, and embed bookings in creates
Separate create, update and remove effects, bookings embedded in their create effect, and ids derived per kind.
APR 2026
ADR 0067
12 Apr 2026
Serve MCP over stateless Streamable HTTP with JSON responses
Every MCP request stands alone, so any replica can serve it.
ADR 0065
11 Apr 2026
Route every modification write through one apply-and-rebuild service method
One service method stores, rebuilds, commits and publishes every modification for every transport.
ADR 0064
11 Apr 2026
Test MCP tool selection with a multi-model Promptfoo eval suite
Promptfoo evals run against the real server instructions and gate every change to tool descriptions.
ADR 0063
11 Apr 2026
Hand-roll a minimal OAuth 2.1 authorization server for MCP
A small in-house OAuth 2.1 server issues our own tokens, where oxide-auth didn't fit.
ADR 0062
11 Apr 2026
Serve the planning engine as deterministic MCP tools from the GraphQL binary
MCP tools wrap the same domain services as GraphQL, and the user's own model is the agent.
ADR 0048
14 Apr 2026
Diff versions on the server as fork point, branch history and end state
The server returns a typed diff of fork point, each branch's history and the end states, so agents never compare trips themselves.
MAR 2026
ADR 0056
7 Mar 2026
Accept every booking and derive discrepancies from the rebuilt trip
Every booking is accepted, and anything that doesn't fit the plan becomes a dismissible notice.
ADR 0055
21 Mar 2026
Deploy each ready pull request as its own Nomad job and Postgres database
Each pull request gets its own Nomad deploy, database and Redis namespace on the production cluster.
ADR 0051
26 Mar 2026
Order a trip's modifications under a FOR UPDATE lock on the trip row
Writes lock the trip row, and replay orders by the position assigned under that lock, never by timestamp.
ADR 0046
26 Mar 2026
Model trip versions as named refs into a modification tree
Modifications form a tree and versions are pointers into it, which replaced copy-on-branch and a what-if mode.
ADR 0045
22 Mar 2026
Wrap every domain identifier in its own UUID newtype
Every identifier is its own type, so a swapped ID fails to compile instead of corrupting a trip.
ADR 0044
18 Mar 2026
Use generated types directly in the iOS app instead of a hand-written mirror model
The app uses generated and shared types directly and keys the cache by type and id, with no hand-written mirror model.
FEB 2026
ADR 0041
15 Feb 2026
Publish trip-id signals over GraphQL subscriptions and filter each device's own echo on the server
Subscriptions carry only a trip id, the server drops each device's own echo, and clients pull the change.
JAN 2026
ADR 0053
30 Jan 2026
Trace from the app through to the backend via a per-node Grafana Alloy collector that holds every credential
Traces run from the app into the backend, and only the per-node collector holds telemetry credentials.
ADR 0040
30 Jan 2026
Detect intrusions from Traefik and sshd logs with CrowdSec
CrowdSec bans attackers from Traefik and SSH logs, since packet inspection can't see inside TLS.
ADR 0039
29 Jan 2026
Back up Postgres with pgBackRest in weekly fulls and daily differentials
Weekly fulls kept for a year, daily differentials and incrementals, stored in R2 for free egress on restore.
DEC 2025
ADR 0077
3 Dec 2025
Generate each domain's error types with a declarative macro
A macro generates each domain's error codes, types and GraphQL extensions, replacing anyhow and hand-written thiserror glue.
OCT 2025
ADR 0038
7 Oct 2025
Generate neighbourhood guides with Exa's answer endpoint and keep the output display-only
Exa generates neighbourhood overviews, and the output is only ever displayed, which bounds what a prompt injection can do.
ADR 0037
7 Oct 2025
Reference accommodations by Apple Maps Place ID with a name and coordinate snapshot
An accommodation stores a Place ID plus a small snapshot, and never a copy of details that go stale.
ADR 0036
2 Oct 2025
Geocode destinations on-device with MapKit and record the result as an effect
The phone geocodes locations with Apple's geocoder, so the backend needs no paid geocoding API.
SEPT 2025
ADR 0058
1 Sept 2025
Make discoverable WebAuthn passkeys the primary sign-in
Passkeys are the main sign-in, with email and password as the fallback.
ADR 0034
13 Sept 2025
Test external API calls against recorded reqwest-vcr cassettes
Tests replay recorded model responses, re-recorded in the same change that alters a prompt.
ADR 0033
3 Sept 2025
Event-source trips as an append-only log of effects
A trip is rebuilt from an append-only log of resolved effects, and removing a destination keeps its bookings.
ADR 0032
3 Sept 2025
Generate effects directly with GPT-5 as S-expressions under a Lark grammar
The model writes effects directly as S-expressions, constrained by a Lark grammar that tests hold to the effect enum.
AUG 2025
ADR 0031
17 Aug 2025
Write component-specific GraphQL queries instead of reusable ones
Each view writes its own query for exactly what it shows, instead of sharing queries that fetch everything.
JUL 2025
ADR 0076
10 Jul 2025
Serve the API as GraphQL with async-graphql on Axum
The API is GraphQL on async-graphql, because the app is built around Apollo's cache.
ADR 0028
30 Jul 2025
Use device-bound PASETO tokens as the only session state
The PASETO token is the whole session: user and device only, device-bound, 90 days sliding, refreshed through a response header.
ADR 0022
24 Jul 2025
Serialize PASETO key rotation across nodes with pg_try_advisory_xact_lock
A non-blocking, transaction-scoped Postgres lock makes sure one node rotates keys, with no extra coordination service.
ADR 0015
27 Jul 2025
Persist Apollo's normalized cache in SQLite and clear it on sign-out
The GraphQL cache lives in SQLite so it survives a restart and works offline, and it's cleared on sign-out.
ADR 0009
12 Jul 2025
Organise the backend into domain modules that query Postgres through sqlx directly
Code is grouped by business domain, with no technical layers and no repository abstraction.
ADR 0006
11 Jul 2025
Return GraphQL error codes in extensions and localize them on iOS
The API returns machine-readable error codes and the app turns them into localized messages, so the server never writes English for the user.
ADR 0004
10 Jul 2025
Test and preview iOS services over a mocked Apollo network transport
Unit tests and SwiftUI previews both run real services over a mocked Apollo network transport.
ADR 0003
10 Jul 2025
Serve SwiftUI views from @Observable environment services over Apollo's normalized cache
Thin SwiftUI views call observable services from the environment, with Apollo's cache as the source of truth for fetched data, in place of MVVM or a global store.