Commit Graph

334 Commits

Author SHA1 Message Date
Paperclip 90794e4e14 fix(gro-540): add missing OIDC env vars to prod API deployment
Updates infra submodule to include OIDC_ISSUER, OIDC_CLIENT_ID,
OIDC_CLIENT_SECRET, and OIDC_INTERNAL_BASE env vars in prod api-patch.yaml.

This fixes the auth initialization failure where initAuth() found no
provider config because OIDC env vars were missing from the prod deployment
even though the groombook-auth sealed secret contained the credentials.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 21:57:48 +00:00
groombook-cto[bot] 373e35ef8e feat(GRO-537): add UAT user personas to seed script
feat(GRO-537): add UAT user personas to seed script
2026-04-10 20:23:15 +00:00
Pawla Abdul 46416586ea feat(GRO-537): add UAT Super User and Staff Groomer to seed script 2026-04-10 20:13:20 +00:00
groombook-cto[bot] 515389e067 Merge pull request #251 from groombook/fleaflicker/gro-528-seed-uat-personas
feat(db): add UAT persona staff records to seed script (GRO-528)
2026-04-10 16:16:58 +00:00
groombook-cto[bot] 191e3499fc Merge branch 'main' into fleaflicker/gro-528-seed-uat-personas 2026-04-10 16:13:03 +00:00
groombook-cto[bot] 921d708ccd Merge pull request #252 from groombook/fix/gro-534-seed-image-tag
fix: remove hardcoded seed image in promote-to-uat workflow (GRO-534)
2026-04-10 10:53:49 +00:00
Flea Flicker 5b4562d5d7 fix: let Kustomize images transformer set seed/migrate image tags
The promote-to-uat workflow was bypassing the Kustomize images transformer
by hardcoding image tags directly on the Job spec containers. Since Jobs
use immutable templates, Flux cannot update a running Job's pod template
when the image tag changes. Instead, let the UAT overlay's images: newTag
field handle tag injection via the images transformer, which correctly
produces the updated image reference in the rendered manifest before Flux
reconciles it.

This reverts the explicit image tag writes added in 916a207 for migrate
and seed, while keeping the Job name (with short SHA) and deploy-version
annotation updates which are correctly handled separately.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 10:36:42 +00:00
Flea Flicker 7f405ccc67 fix: remove dead kubectl delete step from promote-to-uat workflow
The CTO correctly identified that the delete step was dead code:
- gcloud/kubectl silently fail in the runner (no GKE credentials)
- Architecturally wrong for GitOps (Flux handles reconciliation)
- Unique Job names + ttlSecondsAfterFinished handle lifecycle

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 06:07:22 +00:00
Flea Flicker 916a2071d9 fix: update seed job image tag in promote-to-uat workflow
The workflow was not updating the seed job image tag when promoting to UAT,
causing Flux to apply a stale image. Now it updates the image like it
does for the migrate job.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 06:05:41 +00:00
Flea Flicker 0c135ac580 Revert "chore: update migrate and seed Job image tags during UAT promotion" image update for seed
The hardcoded image update for seedJob conflicts with Kustomize images transformer
override. Reverting only the seed image line (line 70), keeping migrate image update
and Job deletion step.

Root cause: Kustomize images transformer correctly overrides ghcr.io/groombook/seed
when newTag is set in UAT overlay. Overwriting the container[0].image directly in
the workflow causes the old tag (2026.04.05-b090f8b) to be baked into the YAML that
Flux reconciles, bypassing the Kustomize override.

Fix: groombook/groombook#247

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 05:12:54 +00:00
Flea Flicker 4c1207a5ae chore: update migrate and seed Job image tags during UAT promotion
Previously the Kustomize images transformer was not overriding the hardcoded
image tags in migrate-job.yaml and seed-job.yaml (base/ containers), causing
UAT deployments to use stale image tags. This change adds explicit yq updates
to set the correct image tag on both Job containers during promotion.

Fixes: groombook/groombook#247
2026-04-10 04:59:56 +00:00
Flea Flicker 8bfc6c970b feat(db): add UAT persona staff records to seed script
- Add UAT Super User and Staff User staff records creation in seedKnownUsers()
- Staff records created with oidcSub from SEED_UAT_*_OIDC_SUB env vars
- Supports linking Terraform-provisioned Authentik users to staff records

GRO-528
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 04:10:41 +00:00
groombook-engineer[bot] 1255fd91cd feat: parameterize seed script with SEED_PROFILE env var (GRO-526)
Adds SEED_PROFILE env var accepting 'dev', 'uat', or 'demo' values:

- dev: 4 staff (1 manager, 1 receptionist, 2 groomers), 100 clients,
  7d/30d appointment window, ~1000 invoices, no UAT clients
- uat: 8 staff (1 manager, 1 receptionist, 3 groomers, 3 bathers),
  500 clients, 30d/90d window, ~4000 invoices, includes UAT clients
- demo: same volume as uat

Unset SEED_PROFILE defaults to 'uat' for backwards compatibility.
SEED_KNOWN_USERS_ONLY=true path unchanged.
All appointment dates computed relative to NOW() at seed time.
Supplemental completed appointments generated when profile invoice
target exceeds organic appointment count.

Closes groombook/groombook#247

Co-authored-by: Flea Flicker <flea-flicker@groombook.ing>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-10 04:00:37 +00:00
Flea Flicker b8b054316c Parameterize seed script with SEED_PROFILE env var
Adds SEED_PROFILE env var accepting 'dev', 'uat', or 'demo' values:

- dev: 4 staff (1 manager, 1 receptionist, 2 groomers), 100 clients,
  7d/30d appointment window, ~1000 invoices, no UAT clients
- uat: 8 staff (1 manager, 1 receptionist, 3 groomers, 3 bathers),
  500 clients, 30d/90d window, ~4000 invoices, includes UAT clients
- demo: same volume as uat

Unset SEED_PROFILE defaults to 'uat' for backwards compatibility.
SEED_KNOWN_USERS_ONLY=true path unchanged.
All appointment dates computed relative to NOW() at seed time.
Supplemental completed appointments generated when profile invoice
target exceeds organic appointment count.

Closes groombook/groombook#247

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 03:38:55 +00:00
groombook-cto[bot] 0f944c537d Merge pull request #249 from groombook/fix/gro-531-social-login
feat: add Google/GitHub social login for Demo environment (GRO-531)
2026-04-10 02:37:56 +00:00
Flea Flicker dd646fb273 feat: add Google/GitHub social login for Demo environment (GRO-531)
- auth.ts: add google/github social providers from better-auth/social-providers
- auth.ts: add getActiveProviders() to enumerate configured OAuth/social providers
- index.ts: add /api/auth/providers public endpoint for frontend
- App.tsx: update LoginPage to show Google/GitHub buttons based on /api/auth/providers response

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 02:06:44 +00:00
groombook-cto[bot] 75ddf62e9c Merge pull request #246 from groombook/fix/gro-516-reset-cronjob-v2
feat: implement SEED_ADMIN_EMAIL support for admin staff survival on demo resets
2026-04-09 22:45:52 +00:00
Flea Flicker 63256b8bc0 feat: implement SEED_ADMIN_EMAIL support in seedKnownUsers and full seed
- Add admin upsert to seedKnownUsers() for prod path
- Add admin upsert to seed() for UAT path
- Idempotent: skips if SEED_ADMIN_EMAIL not set

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-09 22:33:15 +00:00
groombook-cto[bot] 01c545ed23 fix: remove reset-demo-data CronJob from prod — move to dev/UAT only (#245)
fix: remove reset-demo-data CronJob from prod — move to dev/UAT only
2026-04-08 19:54:44 +00:00
Flea Flicker bb9f677a9b fix: confirm reset-demo-data CronJob only in dev/UAT overlays
Verification (kubectl kustomize):
- dev:  CronJob present
- uat:  CronJob present
- prod: CronJob absent

No structural changes needed — state already correct in main.
2026-04-08 19:47:03 +00:00
groombook-cto[bot] d12c3b4a60 fix: set isSuperUser=false for Jordan Lee in full seed path (#242)
fix: set isSuperUser=false for Jordan Lee in full seed path
2026-04-08 03:05:14 +00:00
Paperclip a84d5e7b9a fix: set isSuperUser=false for Jordan Lee in full seed
Jordan Lee was being created with isSuperUser=true in the full seed path,
causing GET /api/setup/status to return needsSetup=false after UAT reset.
2026-04-08 02:56:31 +00:00
groombook-cto[bot] 4261058565 Merge pull request #241 from groombook/fleaflicker/gro-505-paginated-invoices
GRO-505: Use paginated invoices API, eliminate over-fetching
2026-04-07 21:49:17 +00:00
Flea Flicker 94764d8532 Frontend: use paginated invoices API, eliminate over-fetching
- Replace loadAll() with single GET /api/invoices?limit=50&offset=0
- Remove parallel fetches of clients/appointments/services/staff from list load
- Use clientName from API response instead of client-side enrichment
- Add offset-based pagination controls with Previous/Next buttons
- Lazy-load staff/appointments only when opening invoice detail modal
- Lazy-load clients/appointments/services only when opening create form
- Filter changes only re-fetch invoices, not all endpoints

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-07 20:11:24 +00:00
Flea Flicker 9be6a87105 chore: implement hourly reset CronJob for prod and UAT
- Add ALLOW_RESET env var override to reset.ts safety guard
- Add reset Docker build target to Dockerfile
- Add reset image build step to CI docker job
- Add reset image tag update to CD job dev overlay update

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-07 20:01:56 +00:00
groombook-cto[bot] 19880e36de feat(invoices): add indexes, pagination, and client name enrichment (GRO-504)
feat(invoices): add indexes, pagination, and client name enrichment (GRO-504)
2026-04-07 19:43:07 +00:00
Flea Flicker 0fe10434e1 feat(invoices): add indexes, pagination, and client name enrichment
- Add database migration 0024 with indexes on invoices, invoice_line_items, and invoice_tip_splits
- Update Drizzle schema with index definitions for sync
- Add pagination (limit/offset) to GET /api/invoices with max 200 limit
- Add LEFT JOIN to include clientName in invoice list response
- Return { data: [...], total: N } response shape for pagination

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-07 19:23:03 +00:00
groombook-cto[bot] 83f0c8d3db Merge pull request #236 from groombook/fix/gro-493-oobe-loop
fix(web): resolve OOBE loop after setup completion (GRO-494)
2026-04-05 23:19:27 +00:00
Flea Flicker e435fe344e fix(web): clear needsSetup state after OOBE completion to prevent loop
When SetupWizard completes POST /api/setup and navigates to /admin,
App.tsx still has needsSetup=true in React state, causing an immediate
redirect back to /setup. Pass onSetupComplete callback to SetupWizard
which clears the state before navigating, breaking the loop.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 23:09:47 +00:00
groombook-qa[bot] f56e2de165 fix(web): redirect authenticated admin users to /admin (#235)
fix(web): redirect authenticated admin users to /admin
2026-04-05 21:35:06 +00:00
Flea Flicker e576c06c92 Merge remote-tracking branch 'origin/main' into fix/gro-488-admin-login-redirect 2026-04-05 21:26:34 +00:00
Flea Flicker 5effe07cd6 fix(web): redirect authenticated admin users to /admin
Preserve customer portal impersonation flow via ?sessionId= query param.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 21:16:53 +00:00
groombook-qa[bot] 8e6bfaaaa0 Merge pull request #234 from groombook/fix/gro-485-oobe-staff-middleware
fix(api): exempt OOBE setup from staff middleware and auto-create staff (GRO-485)
2026-04-05 20:22:40 +00:00
groombook-qa[bot] aa36d4ba87 Merge branch 'main' into fix/gro-485-oobe-staff-middleware 2026-04-05 20:16:12 +00:00
Flea Flicker 8348f1c152 fix(api): resolve CI typecheck failures in GRO-485 fix
Fix type errors that caused CI Lint & Typecheck job to fail:
- setup.ts: replace unavailable isNull import with sql template tag
  (isNull not exported from @groombook/db; sql IS exported)
- setup.ts: add non-null assertion on newStaff after insert.returning()
- setup.test.ts: add sql mock template tag to @groombook/db mock
- setup.test.ts: fix evaluateCond to handle sql template tag type
- setup.test.ts: add type assertions for body.staff in OOBE regression tests
- setup.test.ts: fix dbStaffRows type casts in mock insert function

All 18 tests pass, full typecheck clean.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 20:05:53 +00:00
Flea Flicker fa18c41677 fix(api): exempt OOBE setup from staff middleware and auto-create staff (GRO-485)
Exempt POST /api/setup from resolveStaffMiddleware so OOBE users (with no
pre-existing staff record) can complete the out-of-box experience without
getting blocked by the "no staff record found" 403 error.

Changes:
- rbac.ts: add /api/setup to path exemption alongside /api/auth/
- setup.ts POST /: add find-or-create logic that:
  - Looks up existing staff by userId from JWT
  - Auto-links legacy staff records by email if userId is null
  - Creates a new staff record if none exists (OOBE case)
  - Returns 400 if JWT has no email and no staff record found
- setup.test.ts: add regression tests for all scenarios

Fixes GRO-485 (OOBE regression introduced by GRO-480).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 19:37:23 +00:00
groombook-cto[bot] 8ab47a738d Merge pull request #233 from groombook/fix/gro-478-auto-link-staff-user
fix(ci): remove dead kubectl steps from promote workflows (GRO-482)
2026-04-05 17:33:33 +00:00
Flea Flicker 25ac34828f fix(ci): remove dead kubectl steps and misleading TTL fallback lines
These steps always fail because the runner has no kubeconfig. Job names
are already unique per deploy (include SHORT_SHA), and base manifests
already set ttlSecondsAfterFinished: 120 for auto-cleanup.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 16:32:23 +00:00
groombook-cto[bot] 736c94664e Merge pull request #232 from groombook/fix/gro-478-auto-link-staff-user
fix(ci): delete completed Jobs before Flux reconciles (GRO-481)
2026-04-05 15:57:29 +00:00
Flea Flicker 006c05ac77 fix(ci): delete completed Jobs before Flux reconciles (GRO-481)
Both promote-to-uat and promote-prod workflows now delete any
existing completed Jobs with the same short SHA suffix before Flux
reconciles. This prevents the immutable-podTemplate error that was
blocking UAT at image tag a67e541:

  Job.batch "migrate-schema-xxx" is invalid: spec.template: field is immutable

Also added missing failure notification step to promote-prod workflow.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 15:47:04 +00:00
groombook-qa[bot] a67e541657 Merge pull request #231 from groombook/fix/gro-478-auto-link-staff-user
fix(api): auto-link staff to Better-Auth user via email on first SSO login (GRO-480)
2026-04-05 15:05:50 +00:00
groombook-qa[bot] 9a3d8d1516 Merge branch 'main' into fix/gro-478-auto-link-staff-user 2026-04-05 14:59:21 +00:00
Flea Flicker e39924b236 fix(api): import isNull from @groombook/db instead of drizzle-orm directly
drizzle-orm is not a direct dependency of @groombook/api, causing
TS2307 at typecheck time. Re-export isNull from @groombook/db and
update the import in rbac.ts.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 14:39:22 +00:00
Flea Flicker 711981e6f3 fix(api): auto-link staff to Better-Auth user via email on first SSO login (GRO-480)
When a staff record exists with a matching email but no userId (e.g. seed data
or admin UI-created records), resolveStaffMiddleware now auto-links it to the
Better-Auth user record on first SSO login instead of returning 403.

Safety: only links when userId IS NULL, never overwrites an existing link.
Email matching is safe since it comes from the trusted SSO provider (Authentik).
Staff emails are unique by schema.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 14:30:25 +00:00
groombook-cto[bot] 6ed4b5bc93 fix(ci): rename base Jobs in promote-to-uat and promote-prod workflows (GRO-311) (#230)
fix(ci): rename base Jobs in promote-to-uat and promote-prod workflows (GRO-311)
2026-04-05 11:31:08 +00:00
groombook-cto[bot] bb8030e49a Merge branch 'main' into fix/gro-311-promote-job-names 2026-04-05 11:24:27 +00:00
Flea Flicker 90ad46f0d5 fix(ci): rename base Jobs in promote-to-uat and promote-prod workflows (GRO-311)
Both workflows now update base migration/seed Job names with short SHA
extracted from the image tag, matching the dev CI cd job pattern.
This prevents Flux immutable-field errors on consecutive UAT/prod
promotions.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-05 11:14:17 +00:00
groombook-engineer[bot] b090f8b810 fix(GRO-472): exclude OAuth callback from service worker caching (#228)
The NetworkFirst route for /api/* was intercepting the OIDC callback
(/api/auth/oauth2/callback/authentik?code=...), returning a cached
index.html instead of forwarding to the API server.

Added navigateFallbackDenylist regex to exclude the callback path
from service worker navigation handling, allowing the callback request
to reach the API server normally.

Fixes GRO-472.

Co-authored-by: Flea Flicker <flea-flicker@groombook.farh.net>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-05 08:55:07 +00:00
groombook-engineer[bot] ff216ea54c fix(api): remove duplicate authProviderRouter registration (#226)
The authProviderRouter was registered twice at /admin/auth-provider in
apps/api/src/index.ts. The second registration is a no-op but creates
confusion. Remove the duplicate line.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-04 23:29:18 +00:00
groombook-qa[bot] 0bb70b291d Merge pull request #225 from groombook/fix/gro-454-test-schema
fix(db): generate unique random salt per encryptSecret call (GRO-453)
2026-04-04 22:22:51 +00:00