Add docs/inspirations.md as the durable record of the 2026-07-05/06
prior-art research — per-project learnings with source paths, canonical
credit lines, and the changes each spawned — and extend the
acknowledgment lists in philosophy.md/architecture.md (Organic Maps,
Endurain, wanderer).
New OpenSpec changes (proposal/design/specs/tasks each):
- Organic Maps: elevation-profile-hardening, gpx-parser-robustness,
hiking-time-estimate, poi-index, hiking-foot-profile
- Endurain: account-export, activity-duplicate-review,
fit-parsing-hardening, activity-locations, self-hosting-guide,
activity-privacy-controls
- wanderer: federation-hardening, link-share-tokens
- credits-page (user-visible acknowledgments)
Updated in-flight changes with wanderer prior-art sections:
route-federation, route-discovery.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Gap analysis of docs/architecture.md against openspec/ and docs/ideas/
found the envisioned-but-uncaptured remainder. This commit captures it:
New OpenSpec change (validated):
- route-federation — the collaboration half of the federation vision:
routes as dereferenceable trails:Route objects, Create/Update
fan-out, Invite/Accept collaboration mirroring (arch decision #2),
cross-instance Planner edits via HTTP-Signature-requested scoped
tokens (decisions #3/#12), mirror sync healing (#16). Depends on
social-federation §6 + route-sharing; carries the 2026-06-07 soak
lessons as design constraints.
New docs/ideas/ explorations:
- instance-administration — registration toggle, suspend/ban,
federation blocklists, reports (moderation now gates the federated
comments idea)
- social-interactions — local likes + comments (don't exist even
locally; the foundation federated kudos/comments attach to)
- activity-participants — group tagging with confirm/decline +
federated mentions (the participants jsonb column is an untyped stub)
- multi-day-collections — architecture open question #1, directions
evaluated
architecture.md cleanup:
- Mastodon-compat section annotated with shipped/captured state + the
live-soak interop lessons (attachment arrays, tombstones, 10s
timeout, no backfill)
- api.trails.cool removed (contradicted resolved decision #18)
- Phase 1 ticked (shipped); Phase 2/3 items annotated with where each
is tracked; specs/ → openspec/, activity.* → journal.*, cx21 → cx23
- brouter-web open question marked resolved-in-practice; new section
pointing to where the unshipped vision is tracked
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lands sections 6 and 8 of relocate-brouter-to-dedicated-host on top
of the host compose in #291.
## Observability (section 6)
- **Prometheus**: new `brouter-cadvisor` job scraping
`10.0.1.10:8080` over the vSwitch, labeled `host="brouter"`.
- **cAdvisor sidecar** on the dedicated host's compose
(`--docker_only --whitelisted_container_labels=trails.cool.service`)
so metrics only cover trails containers, never the operator's
unrelated workloads on the shared box.
- **Promtail sidecar** on the dedicated host, Docker SD with relabel-
drop on missing `trails.cool.service` label, pushing to flagship
Loki at `http://10.0.0.2:3100/loki/api/v1/push`.
- **Flagship compose**: Loki now publishes port 3100 on the vSwitch
IP only (10.0.0.2:3100) — Hetzner Cloud firewall blocks it from
the public internet.
- **Grafana dashboard**: `brouter.json` — scrape up/down, request
rate (from Planner-side `brouter_request_duration_seconds`),
p50/p95/p99, container memory/CPU, Loki logs panel.
- **Alert**: `brouter-scrape-down` fires on
`up{job="brouter-cadvisor"} < 1 for 2m`; `noDataState: Alerting`
so a total scrape failure still pages.
Operator needs one UFW rule on the dedicated host for the cAdvisor
port — documented in `infrastructure/brouter-host/README.md`.
## Documentation (section 8)
- `CLAUDE.md` — hosts table + updated deployment table with SSH
targets per workflow; BRouter host SSH is `-p 2232 trails@...`,
different key.
- `docs/architecture.md` — Hosting section rewritten to cover both
hosts, vSwitch boundary, and the observability-scoping rationale
for the shared dedicated host.
- `docs/deployment.md` (new) — full operator runbook: host layout,
first-time BRouter provisioning, SOPS rotation (including the
macOS `SOPS_AGE_KEY_FILE` gotcha), cutover procedure with
rollback, manual workflow triggers.
Task 8.4 (infrastructure/README.md) skipped: that file doesn't
exist and the ground is covered by brouter-host/README.md +
docs/deployment.md.
## Validation
- `docker compose config` on both the flagship and brouter-host
compose files — both validate.
- `pnpm typecheck`, `pnpm lint`, `pnpm test` — all clean (full
turbo cache hits; no code changes in this commit).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI pipeline with parallel jobs for fast feedback:
- typecheck, lint, unit tests, build run in parallel
- e2e tests run after build
- Playwright artifacts uploaded on failure
ESLint wired into both apps with sensible defaults:
- underscore-prefixed unused vars allowed
- root package.json marked as type: module
Architecture updated: Caddy as reverse proxy with auto HTTPS.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>