Compare commits

...

9 Commits

Author SHA1 Message Date
Chris Farhood 002e6575ba fix(GRO-1533): add missing 0032_staff_read_at.sql migration file
CI / Test (pull_request) Successful in 2m30s
CI / Lint & Typecheck (pull_request) Successful in 2m32s
CI / Build & Push Docker Images (pull_request) Successful in 4m6s
The migration journal references 0032_staff_read_at but the SQL file
was never committed. drizzle-kit migrate fails with "No file
./migrations/0032_staff_read_at.sql found" which blocks all subsequent
migrations including the 0033 default_buffer_minutes fix.

Added as a no-op since the staff table schema has no readAt column.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 14:28:48 +00:00
The Dogfather f9c679b392 Merge pull request 'fix(GRO-1533): add missing default_buffer_minutes migration' (#53) from fix/gro-1533-missing-migration-journal into dev
CI / Lint & Typecheck (push) Failing after 3s
CI / Test (push) Successful in 9s
CI / Build & Push Docker Images (push) Has been skipped
Merge fix/gro-1533-missing-migration-journal into dev: add missing default_buffer_minutes migration (GRO-1533)
2026-05-22 14:08:55 +00:00
Flea Flicker ce0739b3ba fix(GRO-1533): fix snapshot id in 0033_snapshot.json
CI / Test (pull_request) Successful in 10s
CI / Lint & Typecheck (pull_request) Successful in 10s
CI / Build & Push Docker Images (pull_request) Successful in 49s
Fixes id from "0026_stripe_payment" to "0033_add_services_default_buffer_minutes".

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 14:07:39 +00:00
Flea Flicker 3609087980 fix(GRO-1533): add missing default_buffer_minutes migration
CI / Lint & Typecheck (pull_request) Successful in 9s
CI / Test (pull_request) Successful in 9s
CI / Build & Push Docker Images (pull_request) Successful in 46s
Adds 0033_add_services_default_buffer_minutes.sql with idempotent
ALTER TABLE to ensure services.default_buffer_minutes exists.

Also fixes _journal.json by adding missing 0031_buffer_rules entry (idx 31)
and 0032_staff_read_at entry (idx 32) that were absent from the journal.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 13:55:38 +00:00
The Dogfather f55c74983f Merge pull request 'revert: undo PR #47 Dockerfile apps/api switch (broke CI Docker build)' (#50) from revert/gro-1533-dockerfile-fix into dev
CI / Lint & Typecheck (push) Successful in 9s
CI / Test (push) Successful in 9s
CI / Build & Push Docker Images (push) Successful in 50s
revert: undo PR #47 Dockerfile apps/api switch (broke CI Docker build)

Restores root src/ build path. PR #47 broke CI because pnpm-workspace.yaml
and lockfile dont include apps/*. Admin 500 root cause is in code/schema changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 13:31:12 +00:00
Chris Farhood 8bdab69288 revert: undo PR #47 Dockerfile apps/api switch (broke CI Docker build)
CI / Test (pull_request) Successful in 8s
CI / Lint & Typecheck (pull_request) Successful in 9s
CI / Build & Push Docker Images (pull_request) Successful in 47s
Reverts the Dockerfile to the root src/ build. PR #47 switched to apps/api/
but the pnpm workspace config and lockfile don't include apps/*, causing
Docker build failures (CI runs #968, #970).

The actual admin 500 root cause needs further investigation — it's in the
code/schema changes, not the Dockerfile build path.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 13:30:51 +00:00
The Dogfather 8f7104c3a0 Merge pull request 'fix(GRO-1533): revert Dockerfile to build from apps/api/src/' (#47) from fix/gro-1533-revert-dockefile-build-change into dev
CI / Test (push) Successful in 9s
CI / Lint & Typecheck (push) Successful in 10s
CI / Build & Push Docker Images (push) Failing after 18s
fix(GRO-1533): revert Dockerfile to build from apps/api/src/

Reverts the Dockerfile change that switched from pnpm --filter @groombook/api build
to pnpm build, which caused the image to build from root src/ instead of
apps/api/src/. This produced HTTP 500 on all authenticated admin routes.

Conflict with PR #45 (seed filter fix) resolved: migrate/seed/reset stages
use @groombook/api db:migrate|seed|reset since the builder only has apps/api/.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 13:23:49 +00:00
Flea Flicker dab9bfab71 fix(GRO-1533): revert Dockerfile to build from apps/api/src/
CI / Test (pull_request) Successful in 10s
CI / Lint & Typecheck (pull_request) Successful in 10s
CI / Build & Push Docker Images (pull_request) Failing after 18s
The Dockerfile build change (pnpm build → pnpm --filter @groombook/api)
was made against dev HEAD, but the root src/ directory was never fully
audited for parity with apps/api/src/. Admin routes returning 500 for
authenticated users post-OIDC login is consistent with the image
running code with incomplete middleware chain or mismatched schema
types when the root build path was used.

Revert to the apps/api/ build path which is known to work correctly.
UAT is running images from dev branch commit 9462915 which includes
this change alongside schema cleanup commits.

Root cause: Dockerfile was changed to build from root src/ instead of
apps/api/src/ without confirming the two source trees are functionally
identical. The proper fix path (schema audit + reconciliation) is
tracked in GRO-1536.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 13:23:33 +00:00
The Dogfather 70bc946a0d Merge pull request 'fix(seed): use --filter @groombook/db for seed/migrate/reset scripts' (#45) from flea-flicker/gro-1531-seed-db-filter into dev
CI / Lint & Typecheck (push) Successful in 10s
CI / Test (push) Successful in 10s
CI / Build & Push Docker Images (push) Successful in 21s
fix(seed): use --filter @groombook/db for seed/migrate/reset scripts

Merge PR #45 to dev. QA approved (review #3506), CTO reviewed.
2026-05-22 13:17:09 +00:00
4 changed files with 131 additions and 0 deletions
@@ -0,0 +1 @@
-- no-op: journal entry exists but no schema change was needed
@@ -0,0 +1,6 @@
-- Migration: 0033_add_services_default_buffer_minutes.sql
-- Adds missing default_buffer_minutes column to services table.
-- 0031_buffer_rules was applied to the DB but its journal entry was missing,
-- so this ensures idempotent column addition for fresh DB restores.
ALTER TABLE "services" ADD COLUMN IF NOT EXISTS "default_buffer_minutes" integer DEFAULT 0 NOT NULL;
@@ -0,0 +1,103 @@
{
"id": "0033_add_services_default_buffer_minutes",
"version": "7",
"dialect": "postgresql",
"tables": {
"authProviderConfig": {
"name": "auth_provider_config",
"columns": {
"id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
"providerId": { "name": "provider_id", "type": "text", "isNullable": false },
"displayName": { "name": "display_name", "type": "text", "isNullable": false },
"issuerUrl": { "name": "issuer_url", "type": "text", "isNullable": false },
"internalBaseUrl": { "name": "internal_base_url", "type": "text", "isNullable": true },
"clientId": { "name": "client_id", "type": "text", "isNullable": false },
"clientSecret": { "name": "client_secret", "type": "text", "isNullable": false },
"scopes": { "name": "scopes", "type": "text", "isNullable": false, "default": "'openid profile email'" },
"enabled": { "name": "enabled", "type": "boolean", "isNullable": false, "default": "true" },
"createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
"updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {}
},
"businessSettings": {
"name": "business_settings",
"columns": {
"id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
"businessName": { "name": "business_name", "type": "text", "isNullable": false, "default": "'GroomBook'" },
"logoBase64": { "name": "logo_base64", "type": "text", "isNullable": true },
"logoMimeType": { "name": "logo_mime_type", "type": "text", "isNullable": true },
"logoKey": { "name": "logo_key", "type": "text", "isNullable": true },
"primaryColor": { "name": "primary_color", "type": "text", "isNullable": false, "default": "'#4f8a6f'" },
"accentColor": { "name": "accent_color", "type": "text", "isNullable": false, "default": "'#8b7355'" },
"createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
"updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {}
},
"clients": {
"name": "clients",
"columns": {
"id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
"name": { "name": "name", "type": "text", "isNullable": false },
"email": { "name": "email", "type": "text", "isNullable": true },
"phone": { "name": "phone", "type": "text", "isNullable": true },
"address": { "name": "address", "type": "text", "isNullable": true },
"notes": { "name": "notes", "type": "text", "isNullable": true },
"emailOptOut": { "name": "email_opt_out", "type": "boolean", "isNullable": false, "default": "false" },
"smsOptIn": { "name": "sms_opt_in", "type": "boolean", "isNullable": false, "default": "false" },
"smsConsentDate": { "name": "sms_consent_date", "type": "timestamp", "isNullable": true },
"smsOptOutDate": { "name": "sms_opt_out_date", "type": "timestamp", "isNullable": true },
"smsConsentText": { "name": "sms_consent_text", "type": "text", "isNullable": true },
"stripeCustomerId": { "name": "stripe_customer_id", "type": "text", "isNullable": true },
"status": { "name": "status", "type": "client_status", "isNullable": false, "default": "'active'" },
"disabledAt": { "name": "disabled_at", "type": "timestamp", "isNullable": true },
"createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
"updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": { "idx_clients_stripe_customer_id": { "columns": ["stripe_customer_id"] } }
},
"invoices": {
"name": "invoices",
"columns": {
"id": { "name": "id", "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()", "isNullable": false },
"appointmentId": { "name": "appointment_id", "type": "uuid", "isNullable": true },
"clientId": { "name": "client_id", "type": "uuid", "isNullable": false },
"subtotalCents": { "name": "subtotal_cents", "type": "integer", "isNullable": false },
"taxCents": { "name": "tax_cents", "type": "integer", "isNullable": false, "default": "0" },
"tipCents": { "name": "tip_cents", "type": "integer", "isNullable": false, "default": "0" },
"totalCents": { "name": "total_cents", "type": "integer", "isNullable": false },
"status": { "name": "status", "type": "invoice_status", "isNullable": false, "default": "'draft'" },
"paymentMethod": { "name": "payment_method", "type": "payment_method", "isNullable": true },
"paidAt": { "name": "paid_at", "type": "timestamp", "isNullable": true },
"stripePaymentIntentId": { "name": "stripe_payment_intent_id", "type": "text", "isNullable": true },
"stripeRefundId": { "name": "stripe_refund_id", "type": "text", "isNullable": true },
"paymentFailureReason": { "name": "payment_failure_reason", "type": "text", "isNullable": true },
"notes": { "name": "notes", "type": "text", "isNullable": true },
"createdAt": { "name": "created_at", "type": "timestamp", "isNullable": false, "default": "now()" },
"updatedAt": { "name": "updated_at", "type": "timestamp", "isNullable": false, "default": "now()" }
},
"indexes": { "idx_invoices_client_id": { "columns": ["client_id"] }, "idx_invoices_status": { "columns": ["status"] }, "idx_invoices_created_at": { "columns": ["created_at"] } },
"foreignKeys": { "invoices_appointment_id_fkey": { "columns": ["appointmentId"], "reference": { "table": "appointments", "columns": ["id"] } }, "invoices_client_id_fkey": { "columns": ["clientId"], "reference": { "table": "clients", "columns": ["id"] } } },
"compositePrimaryKeys": {},
"uniqueConstraints": { "idx_invoices_stripe_payment_intent_id": { "columns": ["stripe_payment_intent_id"] } }
}
},
"enums": {
"appointment_status": { "name": "appointment_status", "values": ["scheduled", "confirmed", "in_progress", "completed", "cancelled", "no_show"] },
"client_status": { "name": "client_status", "values": ["active", "disabled"] },
"impersonation_session_status": { "name": "impersonation_session_status", "values": ["active", "ended", "expired"] },
"invoice_status": { "name": "invoice_status", "values": ["draft", "pending", "paid", "void"] },
"payment_method": { "name": "payment_method", "values": ["cash", "card", "check", "other"] },
"staff_role": { "name": "staff_role", "values": ["groomer", "receptionist", "manager"] },
"waitlist_status": { "name": "waitlist_status", "values": ["active", "notified", "expired", "cancelled"] }
},
"nativeEnums": {}
}
+21
View File
@@ -218,6 +218,27 @@
"when": 1775828067192,
"tag": "0030_messaging",
"breakpoints": true
},
{
"idx": 31,
"version": "7",
"when": 1775860800000,
"tag": "0031_buffer_rules",
"breakpoints": true
},
{
"idx": 32,
"version": "7",
"when": 1775894400000,
"tag": "0032_staff_read_at",
"breakpoints": true
},
{
"idx": 33,
"version": "7",
"when": 1779500000000,
"tag": "0033_add_services_default_buffer_minutes",
"breakpoints": true
}
]
}