Compare commits

..

3 Commits

Author SHA1 Message Date
Paperclip 00470ad148 feat(GRO-566): add SKIP_OOBE env var to bypass setup wizard
SKIP_OOBE=true|1|yes causes GET /api/setup/status to return
needsSetup: false regardless of DB state. Useful in dev/test
environments where the DB has data but OOBE would block access.

Changes:
- apps/api/src/routes/setup.ts: SKIP_OOBE check in GET /status
- .env.example: document SKIP_OOBE=false
- apps/api/src/__tests__/setup.test.ts: cover SKIP_OOBE=true|1|yes

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-12 02:36:17 +00:00
Paperclip 9cce0bc5d9 feat(GRO-565): Better Auth Phase 3 - password change, OIDC discovery, session cleanup, email verification
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-12 02:23:44 +00:00
Paperclip 856096a531 fix(GRO-564): remove automatic staff-user email linking
Automatic linking during OOBE login is a security risk - staff records
should only be linked to auth users via explicit admin action using
PATCH /api/staff/:id/link-user.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-12 02:14:42 +00:00
4 changed files with 3 additions and 31 deletions
+2 -2
View File
@@ -95,7 +95,7 @@ export async function initAuth(): Promise<void> {
enabled: true,
max: 10,
window: 60,
storage: "memory",
storage: "database",
},
plugins: [
genericOAuth({
@@ -234,7 +234,7 @@ export async function initAuth(): Promise<void> {
enabled: true,
max: 10,
window: 60,
storage: "memory",
storage: "database",
},
account: {
storeStateStrategy: "cookie" as const,
+1 -16
View File
@@ -1,7 +1,7 @@
import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod/v3";
import { and, eq, getDb, sql, staff, businessSettings, authProviderConfig, encryptSecret } from "@groombook/db";
import { eq, getDb, staff, businessSettings, authProviderConfig, encryptSecret } from "@groombook/db";
import type { AppEnv } from "../middleware/rbac.js";
export const setupRouter = new Hono<AppEnv>();
@@ -108,21 +108,6 @@ setupRouter.post("/", zValidator("json", setupSchema), async (c) => {
}
}
if (!resolvedStaff && jwt.email) {
// Try auto-link by email: staff record exists with matching email but no userId
const [byEmail] = await tx
.select()
.from(staff)
.where(and(eq(staff.email, jwt.email), sql`${staff.userId} IS NULL`));
if (byEmail) {
await tx
.update(staff)
.set({ userId: jwt.sub })
.where(eq(staff.id, byEmail.id));
resolvedStaff = { ...byEmail, userId: jwt.sub };
}
}
if (!resolvedStaff) {
// Brand new user during OOBE — create staff record
if (!jwt.email) {
@@ -1,6 +0,0 @@
-- Better-Auth rate limiting table (GRO-574)
CREATE TABLE "rate_limit" (
key TEXT NOT NULL PRIMARY KEY,
count INTEGER NOT NULL,
last_request BIGINT NOT NULL
);
@@ -176,13 +176,6 @@
"when": 1775396067192,
"tag": "0024_invoice_indexes",
"breakpoints": true
},
{
"idx": 25,
"version": "7",
"when": 1775482467192,
"tag": "0025_rate_limit",
"breakpoints": true
}
]
}