Compare commits

...

15 Commits

Author SHA1 Message Date
Flea Flicker d95a2ede36 fix(e2e): add paginated mock for /api/invoices and remove fragile networkidle wait
- Return { data: [], total: 0 } for /api/invoices instead of falling through to generic []
- Removes waitForLoadState('networkidle') from admin invoices test (fragile in CI)
- Fixes GRO-558
2026-04-11 15:42:56 +00:00
Flea Flicker fb892cadad fix flaky E2E test: add networkidle wait before admin invoices assertions
Fixes GRO-557
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-11 15:31:42 +00:00
groombook-cto[bot] 24a032dd9d fix(api): move Google/GitHub from plugins[] to socialProviders{} in Better-Auth config
fix(api): move Google/GitHub from plugins[] to socialProviders{} in Better-Auth config
2026-04-11 15:25:03 +00:00
Flea Flicker 13f2550ee2 fix(api): move Google/GitHub from plugins[] to socialProviders{} in Better-Auth config 2026-04-11 15:12:44 +00:00
groombook-cto[bot] f29ac2e40d Merge pull request #258 from groombook/fleaflicker/gro-546-fix-oauth-redirect-uri
CTO approved. Infra submodule update adds social auth env vars (GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET) to UAT api-patch.yaml.
2026-04-11 13:21:01 +00:00
groombook-cto[bot] bdcad0d9dc Merge pull request #257 from groombook/fleaflicker/gro-546-fix-oauth-redirect-uri
Fix GitHub/Google OAuth redirect URI configuration (GRO-546)
2026-04-11 03:01:13 +00:00
groombook-cto[bot] b1124e6a6c Merge pull request #256 from groombook/fix/gro-540-prod-oidc-env
fix(GRO-540): add missing OIDC env vars to prod API deployment
2026-04-10 22:04:52 +00:00
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 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
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
2 changed files with 20 additions and 19 deletions
+16 -18
View File
@@ -1,7 +1,6 @@
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { genericOAuth } from "better-auth/plugins";
import { google, github } from "better-auth/social-providers";
import { getDb, authProviderConfig, eq } from "@groombook/db";
import { decryptSecret } from "@groombook/db";
@@ -173,22 +172,6 @@ export async function initAuth(): Promise<void> {
const callbackBase = `${BETTER_AUTH_URL}/api/auth/callback`;
const socialPlugins = [];
if (hasGoogle) {
socialPlugins.push(google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
redirectURI: `${callbackBase}/google`,
}));
}
if (hasGitHub) {
socialPlugins.push(github({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
redirectURI: `${callbackBase}/github`,
}));
}
// Build Better-Auth instance using resolved config
authInstance = betterAuth({
database: drizzleAdapter(db, {
@@ -216,8 +199,23 @@ export async function initAuth(): Promise<void> {
},
],
}),
...socialPlugins,
],
socialProviders: {
...(hasGoogle ? {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
redirectURI: `${callbackBase}/google`,
},
} : {}),
...(hasGitHub ? {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
redirectURI: `${callbackBase}/github`,
},
} : {}),
},
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days
updateAge: 60 * 60 * 24, // 1 day
+4 -1
View File
@@ -44,7 +44,10 @@ test.beforeEach(async ({ page }) => {
json: { newClients: [], activeInPeriodCount: 0, churnRisk: [], churnRiskTotal: 0 },
});
}
// Appointments, clients, services, staff, invoices, book, etc.
if (url.includes("/api/invoices")) {
return route.fulfill({ json: { data: [], total: 0 } });
}
// Appointments, clients, services, staff, book, etc.
return route.fulfill({ json: [] });
});
});