feat(service): M2b — Postgres persistence (sqlx) behind a feature flag #7

Merged
charles merged 1 commit from feat/m2b-postgres into main 2026-06-17 13:18:21 +00:00
Owner

Roadmap M2b, step 2: real persistence. postgres feature is off by default → CI stays DB-less.

Changes

  • domain + trip: serde Serialize/Deserialize on all types (Tree → JSONB; also the basis for the JSON API).
  • service: optional sqlx (rustls/postgres/json/macros/migrate) behind feature postgres.
    • pg::Pg implements TreeStore/QuotaStore/SessionStore on a PgPool with runtime queries (no compile-time DB) — trees as JSONB, atomic quota via INSERT…ON CONFLICT…WHERE used<limit, session upsert.
    • migrations/0001_init.sql.
    • tests/pg.rs gated on feature + DATABASE_URL (skips DB-less).

Verification

  • Ran against a real postgres:16 (ephemeral docker): JSONB round-trip, session attach/adopt-owner, quota consume→exceed→refund — all pass.
  • just qa green: default cargo test is DB-less; --all-features clippy compiles the pg path + sqlx.

Traces: FR-ACC-09/13, FR-IMP-18 · tech-spec 02 §2.4, 12 §12.1.

Roadmap **M2b**, step 2: real persistence. `postgres` feature is **off by default** → CI stays DB-less. ## Changes - **domain + trip**: serde `Serialize`/`Deserialize` on all types (Tree → JSONB; also the basis for the JSON API). - **service**: optional `sqlx` (rustls/postgres/json/macros/migrate) behind feature `postgres`. - `pg::Pg` implements `TreeStore`/`QuotaStore`/`SessionStore` on a `PgPool` with **runtime queries** (no compile-time DB) — trees as JSONB, atomic quota via `INSERT…ON CONFLICT…WHERE used<limit`, session upsert. - `migrations/0001_init.sql`. - `tests/pg.rs` gated on feature + `DATABASE_URL` (skips DB-less). ## Verification - **Ran against a real postgres:16** (ephemeral docker): JSONB round-trip, session attach/adopt-owner, quota consume→exceed→refund — all pass. - `just qa` green: default `cargo test` is DB-less; `--all-features` clippy compiles the pg path + sqlx. Traces: FR-ACC-09/13, FR-IMP-18 · tech-spec 02 §2.4, 12 §12.1.
feat(service): M2b — Postgres persistence (sqlx) behind postgres feature
All checks were successful
qa / qa-1 (pull_request) Successful in 47s
qa / qa (pull_request) Successful in 0s
qa / qa-1 (push) Successful in 6m6s
qa / qa (push) Successful in 0s
3277ebaf2a
- domain + trip: derive serde Serialize/Deserialize on all types (Tree → JSONB;
  also the basis for the JSON REST API). serde dep added.
- service: optional sqlx (rustls, postgres, json, macros, migrate) behind a
  `postgres` feature — OFF by default so qa/CI need no database.
  - pg::Pg implements TreeStore/QuotaStore/SessionStore on a PgPool using
    runtime queries (no compile-time DB); trees stored as JSONB, atomic
    quota consume via INSERT…ON CONFLICT…WHERE used<limit, session upsert.
  - migrations/0001_init.sql (users/trees/quotas/sessions).
  - tests/pg.rs: gated on feature + DATABASE_URL — skips DB-less.

Verified against a real postgres:16: JSONB round-trip, session adopt, quota
consume/exceed/refund all pass. just qa green (default DB-less; --all-features
clippy compiles the pg path + sqlx).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
charles/geneatrip!7
No description provided.