feat: dev environment — flake, seeded local GoatCounter, walking skeleton, VM check #3

Merged
synapse merged 5 commits from feat/dev-environment into develop 2026-08-21 02:37:16 +00:00
Owner

Implements the dev-environment OpenSpec change (store: goatcounter-stats-gateway) — the project's ground layer. All 14 tasks complete, nix flake check green on a clean clone.

  • Flake + dev shell: rust toolchain, rust-analyzer, bacon, sqlite, goatcounter 2.7.0, direnv .envrc
  • dev-goatcounter: one-command local seeded GoatCounter — site + API token created non-interactively (stats-read permission bit 64 OR'd in via sqlite; no CLI name for it in 2.7.0), 45 deterministic backdated pageviews seeded via /api/v0/count with distinct sessions (identical anonymous hits dedupe), polls the stats API before reporting ready. Idempotent, reset subcommand, verified fully offline in a loopback-only netns
  • Walking skeleton: axum binary, GET /healthz 200, 404 everywhere else, GATEWAY_LISTEN env config; unit tests
  • crane packaging: packages.default + checks.{package,fmt,clippy,test} sharing one dep build
  • nixosModules.default: hardened DynamicUser systemd unit — the consumption contract for chiba
  • VM integration test: services.goatcounter (nixpkgs) + the gateway module in one VM, /healthz 200 + 404-contract asserted

Zero stats endpoints — all five API design questions stay open for the next change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01T5j3dAJVcUjZv9k76sRTt9

Implements the `dev-environment` OpenSpec change (store: goatcounter-stats-gateway) — the project's ground layer. All 14 tasks complete, `nix flake check` green on a clean clone. - **Flake + dev shell**: rust toolchain, rust-analyzer, bacon, sqlite, goatcounter 2.7.0, direnv `.envrc` - **`dev-goatcounter`**: one-command local seeded GoatCounter — site + API token created non-interactively (stats-read permission bit 64 OR'd in via sqlite; no CLI name for it in 2.7.0), 45 deterministic backdated pageviews seeded via `/api/v0/count` with distinct sessions (identical anonymous hits dedupe), polls the stats API before reporting ready. Idempotent, `reset` subcommand, verified fully offline in a loopback-only netns - **Walking skeleton**: axum binary, `GET /healthz` 200, 404 everywhere else, `GATEWAY_LISTEN` env config; unit tests - **crane packaging**: `packages.default` + `checks.{package,fmt,clippy,test}` sharing one dep build - **`nixosModules.default`**: hardened DynamicUser systemd unit — the consumption contract for chiba - **VM integration test**: `services.goatcounter` (nixpkgs) + the gateway module in one VM, `/healthz` 200 + 404-contract asserted Zero stats endpoints — all five API design questions stay open for the next change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01T5j3dAJVcUjZv9k76sRTt9
devShells.default: rust toolchain, rust-analyzer, bacon, sqlite,
goatcounter 2.7.0. crane input locked for upcoming packaging.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5j3dAJVcUjZv9k76sRTt9
axum binary serving GET /healthz only, listen addr via GATEWAY_LISTEN.
Tests cover 200 and the 404-everywhere contract. packages.default via
crane with shared dep artifacts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5j3dAJVcUjZv9k76sRTt9
CLI-created site + api token; the stats-read permission (bit 64) has no
CLI name in 2.7.0 so it's OR'd in via sqlite. Seeds 45 deterministic
backdated pageviews via /api/v0/count with distinct sessions (identical
anonymous hits dedupe to one), polls /api/v0/stats/total until visible.
reset subcommand wipes state; re-run is idempotent; verified offline in
a loopback-only netns.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5j3dAJVcUjZv9k76sRTt9
nixosModules.default runs the gateway as a hardened DynamicUser unit
(GATEWAY_LISTEN from module options). checks: package, fmt, clippy
(-D warnings), test — all sharing one crane dep build — plus a NixOS VM
test running services.goatcounter (nixpkgs) beside the gateway module,
asserting /healthz 200 and 404 elsewhere.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5j3dAJVcUjZv9k76sRTt9
nix flake check verified green on a clean clone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5j3dAJVcUjZv9k76sRTt9
synapse merged commit 830bd848fa into develop 2026-08-21 02:37:16 +00:00
synapse deleted branch feat/dev-environment 2026-08-21 02:37:17 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
synapse/goatcounter-stats-gateway!3
No description provided.