fix(gro-38): prod/demo auth and API-based seed (#117)

Closes GRO-38. Adds POST /api/admin/seed (manager-only, gated by SEED_KNOWN_USERS_ONLY) and separates dev vs prod seeding paths. Reviewed and approved by CTO and QA.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit was merged in pull request #117.
This commit is contained in:
groombook-engineer[bot]
2026-03-26 20:51:08 +00:00
committed by GitHub
parent d0b4baf5aa
commit e3220af9ce
11 changed files with 990 additions and 5 deletions
+35
View File
@@ -312,3 +312,38 @@ export const groomingVisitLogs = pgTable("grooming_visit_logs", {
groomedAt: timestamp("groomed_at").notNull().defaultNow(),
createdAt: timestamp("created_at").notNull().defaultNow(),
});
export const waitlistStatusEnum = pgEnum("waitlist_status", [
"active",
"notified",
"expired",
"cancelled",
]);
export const waitlistEntries = pgTable(
"waitlist_entries",
{
id: uuid("id").primaryKey().defaultRandom(),
clientId: uuid("client_id")
.notNull()
.references(() => clients.id, { onDelete: "cascade" }),
petId: uuid("pet_id")
.notNull()
.references(() => pets.id, { onDelete: "cascade" }),
serviceId: uuid("service_id")
.notNull()
.references(() => services.id, { onDelete: "cascade" }),
preferredDate: text("preferred_date").notNull(),
preferredTime: text("preferred_time").notNull(),
status: waitlistStatusEnum("status").notNull().default("active"),
notifiedAt: timestamp("notified_at"),
expiresAt: timestamp("expires_at"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
},
(t) => [
index("idx_waitlist_client_id").on(t.clientId),
index("idx_waitlist_preferred_date").on(t.preferredDate),
index("idx_waitlist_status").on(t.status),
]
);