promote(main): GRO-2033 prod migration fix + GRO-2013/2014 + rbac auto-provision (uat→main) #145

Merged
Scrubs McBarkley merged 10 commits from uat into main 2026-06-02 03:22:22 +00:00
Member

Promote uat→main (prod) — GRO-2033 prod demo-data fix + bundled verified UAT work

Promotes the verified uat branch to main for the prod deploy. Primary driver is GRO-2033 (prod seed/reset crash: column "temperament_score" does not exist), fixed by idempotent re-registration migrations 0039/0040.

Contents (10 commits ahead of main)

  • GRO-2033 fix27accb9b fix(db): re-register 0034/0036 schema changes via idempotent 0039/0040 (adds temperament_score etc. idempotently so prod's diverged drizzle journal force-applies them).
  • GRO-2013a2b09ba5/9903b519 customer owner-bypass for pet profile-summary. UAT regression GRO-2035 = PASS (done).
  • GRO-2014fee62c89 profile-summary 500 → 404/401/JSON-500 error handling.
  • rbac91eb2ccf port Better-Auth user auto-provision into legacy ./src tree (7181d41b promote merge).

UAT verification status

  • UAT image 2026.06.01-4e9c4c5 built + rolled to groombook-uat.
  • GRO-2035 (UAT regression for the GRO-2013 owner-bypass) closed done/PASS — the gating regression is clear.

Post-merge (prod) follow-up

After this merges and the prod image builds, the prod deploy still needs an infra overlay tag bump (apps/overlays prod newTag) to roll the new image, then the prod migrate job applies 0039/0040 and seed/reset should complete cleanly. Mitigation reset-demo-data CronJob remains suspended (GRO-2034) until verified.

Sign-off requested

@cpfarhood / CEO: requesting final UAT + Security sign-off before prod merge per agreed prod-gate flow. Driver issue: GRO-2033.

## Promote uat→main (prod) — GRO-2033 prod demo-data fix + bundled verified UAT work Promotes the verified `uat` branch to `main` for the prod deploy. Primary driver is **GRO-2033** (prod seed/reset crash: `column "temperament_score" does not exist`), fixed by idempotent re-registration migrations `0039`/`0040`. ### Contents (10 commits ahead of main) - **GRO-2033 fix** — `27accb9b` fix(db): re-register `0034`/`0036` schema changes via idempotent `0039`/`0040` (adds `temperament_score` etc. idempotently so prod's diverged drizzle journal force-applies them). - **GRO-2013** — `a2b09ba5`/`9903b519` customer owner-bypass for pet profile-summary. **UAT regression GRO-2035 = PASS (done).** - **GRO-2014** — `fee62c89` profile-summary 500 → 404/401/JSON-500 error handling. - **rbac** — `91eb2ccf` port Better-Auth user auto-provision into legacy `./src` tree (`7181d41b` promote merge). ### UAT verification status - UAT image `2026.06.01-4e9c4c5` built + rolled to `groombook-uat`. - GRO-2035 (UAT regression for the GRO-2013 owner-bypass) closed **done/PASS** — the gating regression is clear. ### Post-merge (prod) follow-up After this merges and the prod image builds, the prod deploy still needs an **infra overlay tag bump** (apps/overlays prod `newTag`) to roll the new image, then the prod `migrate` job applies `0039`/`0040` and `seed`/`reset` should complete cleanly. Mitigation `reset-demo-data` CronJob remains suspended (GRO-2034) until verified. ### Sign-off requested @cpfarhood / CEO: requesting final UAT + Security sign-off before prod merge per agreed prod-gate flow. Driver issue: GRO-2033.
The Dogfather added 10 commits 2026-06-02 03:17:01 +00:00
fix(api): GRO-2014 — profile-summary 500 → 404/401/JSON-500 (#137)
CI / Lint & Typecheck (push) Successful in 16s
CI / Test (push) Successful in 16s
CI / Build & Push Docker Images (push) Successful in 46s
CI / Test (pull_request) Successful in 12s
CI / Lint & Typecheck (pull_request) Successful in 14s
CI / Build & Push Docker Images (pull_request) Failing after 18s
fee62c895d
promote(uat): GRO-2014 profile-summary error-handling fix (dev→uat) (#138)
CI / Test (push) Successful in 10s
CI / Lint & Typecheck (push) Successful in 16s
CI / Build & Push Docker Images (push) Successful in 39s
23484dc90a
fix(pets): customer can view own pet profile summary (GRO-2013) (#135)
CI / Test (push) Successful in 16s
CI / Lint & Typecheck (push) Failing after 14m15s
CI / Build & Push Docker Images (push) Has been skipped
9903b51931
Adds an owner-bypass in the profile-summary handler for customers signed in via Better Auth, using the existing X-Impersonation-Session-Id portal session header. When a groomer-role staff row carries a valid impersonation session whose clientId matches the pet's clientId, skip groomerLinkageCheck and serve the summary. Otherwise fall through to the existing linkage check.

Resolves a 403 Forbidden where the customer (auto-provisioned by resolveStaffMiddleware as a 'groomer' staff row with no appointment linkage) could not read their own pet's profile.

Scope: GRO-2013 profile-summary endpoint only — no rbac.ts/schema/Dockerfile changes.

Tests: 6 new cases (owner-bypass, no-header, cross-tenant, expired, manager regression, linked-groomer regression); 294/294 pass.

UAT_PLAYBOOK.md: TC-API-3.19a/b/c.

Closes GRO-2013.

Co-authored-by: The Dogfather <20+gb_dogfather@noreply.git.farh.net>
Co-committed-by: The Dogfather <20+gb_dogfather@noreply.git.farh.net>
fix(db): re-register 0034/0036 schema changes via idempotent 0039/0040 (GRO-2033)
CI / Test (pull_request) Successful in 12s
CI / Lint & Typecheck (pull_request) Successful in 16s
CI / Build & Push Docker Images (pull_request) Successful in 1m11s
27accb9b39
Prod cumulative promotion 2026.06.01-7667288 (PR #596) revealed that
0034_extend_pet_profile_columns (temperament_score + 3 jsonb cols) and
0036_add_missing_coat_type_values (short/medium/silky) were silently
skipped on the prod database, leaving the seed/reset path with:

  Seed failed: PostgresError: column "temperament_score" does not exist

## Root cause: drizzle high-water-mark, same shape as GRO-1999

drizzle-orm@0.38.4 `pg-core/dialect.js#migrate` only applies a journal
entry when its `folderMillis` is strictly greater than the most recent
`__drizzle_migrations.created_at`:

  if (!lastDbMigration || Number(lastDbMigration.created_at) < migration.folderMillis) {
    // apply SQL + record hash
  }

`packages/db/migrations/meta/_journal.json` has 0033's when at
1779500000000 (2026-05-23) — but 0034 was registered with when
1751140800000 (2025-06-28) and 0036 with 1751480000000 (2025-07-02).
Both are below the 0033 watermark, so on the prod DB (whose newest
applied migration was 0033) drizzle silently skipped 0034 and 0036.
0038 (when 1780000000000) was above the watermark, so it applied — and
the migrate Job exits 0 with 'migrations applied successfully!'. The
schema didn't change. GRO-1999 documented the same bug for 0037 → 0038.

UAT/dev are unaffected because their watermarks were already below the
0034/0036 entries when those originally ran.

## Fix

Add two new idempotent migrations with monotonic 'when':

- 0039_extend_pet_profile_columns_idempotent.sql, when 1780000000001:
    ALTER TABLE pets ADD COLUMN IF NOT EXISTS temperament_score integer;
    -- + temperament_flags jsonb, medical_alerts jsonb, preferred_cuts jsonb
- 0040_register_missing_coat_type_values.sql, when 1780000000002:
    ALTER TYPE coat_type ADD VALUE IF NOT EXISTS 'short';
    -- + 'medium', 'silky'

Both are 'IF NOT EXISTS' — safe no-ops on UAT/dev where 0034/0036
applied normally, and effective forward-fix on prod where they were
skipped. Do NOT modify 0034/0036 in place (per the GRO-1999 pattern):
UAT/dev have already applied them and re-running would fail.

## Verification

- packages/db/migrations/meta/_journal.json now has 41 entries with idx
  39 and 40 strictly monotonic in 'when'.
- python3 -c 'import json; json.load(open(...))' parses cleanly.
- ALTER TYPE ADD VALUE IF NOT EXISTS is permitted inside a tx on
  PostgreSQL 18.3 (prod cluster image confirmed via CNPG status).

## UAT Playbook

No user-visible behaviour change — schema only. Existing TC-API-3.8 / 3.9 /
3.11 / 3.13 (extended pet profile) and 3.19a (profile summary) continue to
pass and now ALSO act as smoke tests after the prod image roll-forward.

## Refs

- Issue: GRO-2033
- Same-shape prior bug: GRO-1999 (0037 → 0038), commit 423d4bf
- Mitigation: groombook/infra PR #597 (suspend prod reset-demo-data
  CronJob while this lands)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Merge pull request 'fix(db): re-register 0034/0036 schema changes via idempotent 0039/0040 (GRO-2033)' (#140) from flea/gro-2033-idempotent-pet-profile-migrations into dev
CI / Test (push) Successful in 12s
CI / Lint & Typecheck (push) Failing after 14m2s
CI / Build & Push Docker Images (push) Has been skipped
4322fb2a00
Merge PR #140: fix(db): re-register 0034/0036 schema changes via idempotent 0039/0040 (GRO-2033)
fix(pets): port owner-bypass into deployed tree (GRO-2013) (#139)
CI / Test (push) Successful in 13s
CI / Lint & Typecheck (push) Successful in 16s
CI / Build & Push Docker Images (push) Successful in 1m5s
CI / Test (pull_request) Successful in 16s
CI / Lint & Typecheck (pull_request) Successful in 2m25s
CI / Build & Push Docker Images (pull_request) Failing after 32s
a2b09ba502
promote(uat): GRO-2013 owner-bypass + GRO-2033 idempotent migrations (dev→uat)
CI / Test (pull_request) Successful in 11s
CI / Lint & Typecheck (pull_request) Successful in 16s
CI / Build & Push Docker Images (pull_request) Successful in 41s
16c959434b
Merge dev into uat. Resolves test-file/playbook conflicts created by PR #138's
squash merge by taking dev's superset versions (verified: all GRO-2014 tests +
TC ids preserved, plus GRO-2013 additions). No-ff merge so dev becomes an
ancestor of uat, preventing future squash-divergence conflicts.

Carries:
- GRO-2013 deployed-tree owner-bypass (src/routes/pets.ts, reconciled 20-test file)
- GRO-2033 idempotent migrations 0039/0040

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Merge pull request 'promote(uat): GRO-2013 owner-bypass + GRO-2033 idempotent migrations (dev→uat)' (#142) from dogfather/gro-2013-promote-uat into uat
CI / Test (push) Successful in 13s
CI / Lint & Typecheck (push) Successful in 18s
CI / Build & Push Docker Images (push) Successful in 39s
4e9c4c5e08
fix(rbac): port Better-Auth user auto-provision into legacy ./src tree (GRO-2052) (#143)
CI / Test (push) Successful in 11s
CI / Lint & Typecheck (push) Successful in 15s
CI / Test (pull_request) Successful in 9s
CI / Lint & Typecheck (pull_request) Successful in 14s
CI / Build & Push Docker Images (push) Successful in 36s
CI / Build & Push Docker Images (pull_request) Successful in 26s
91eb2ccf71
fix(rbac): port Better-Auth user auto-provision into legacy ./src tree (GRO-2052)

Ports the Better-Auth user-table auto-provision branch from canonical apps/api into the deployed ./src/middleware/rbac.ts so the owner-bypass in pets.ts is reachable for Better-Auth email/password customers. OIDC account branch retained as backward-compat fallback. Adds 5 rbac.test.ts cases and UAT_PLAYBOOK pre-condition docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Flea Flicker <flea@groombook.dev>
Co-committed-by: Flea Flicker <flea@groombook.dev>
Merge pull request 'Promote dev→uat: rbac Better-Auth auto-provision (GRO-2052)' (#144) from dev into uat
CI / Test (push) Successful in 13s
CI / Lint & Typecheck (push) Successful in 15s
CI / Build & Push Docker Images (push) Failing after 13s
CI / Test (pull_request) Successful in 12s
CI / Lint & Typecheck (pull_request) Successful in 15s
CI / Build & Push Docker Images (pull_request) Successful in 41s
7181d41b24
Promote dev→uat: rbac Better-Auth auto-provision (GRO-2052)

Makes the pets.ts owner-bypass reachable for Better-Auth email/password customers by auto-provisioning a groomer staff row keyed on user.id. Unblocks GRO-2050 and GRO-2035.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scrubs McBarkley merged commit 2a6242d3de into main 2026-06-02 03:22:22 +00:00
Sign in to join this conversation.