Compare commits

...

11 Commits

Author SHA1 Message Date
Chris Farhood 1ea319e122 merge: resolve conflicts with dev (keep Node 22 + add Gitea CI images)
CI / Lint & Typecheck (pull_request) Failing after 14s
CI / Test (pull_request) Failing after 20s
CI / Build & Push Docker Images (pull_request) Has been skipped
- Dockerfile: keep node:22-alpine for both base and runner stages
- package.json: keep dev's full content + add packageManager field
- .gitea/workflows/ci.yml: keep fixed version with all 4 image targets
- petsExtendedFields.test.ts: keep dev UUIDs + PR's vi.fn() mocks

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 02:58:11 +00:00
The Dogfather da913d600f fix(ci): add Gitea CI workflow with all 4 image targets + Node 22 (GRO-1522)
CI / Lint & Typecheck (pull_request) Failing after 9s
CI / Test (pull_request) Failing after 10s
CI / Build & Push Docker Images (pull_request) Has been skipped
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 02:56:20 +00:00
Flea Flicker ce9fcfb362 fix: resolve pre-existing test and TypeScript errors for CI compliance
CI / Lint & Typecheck (pull_request) Failing after 6s
CI / Test (pull_request) Successful in 21s
CI / Build (pull_request) Has been skipped
CI / Build & Push Docker Images (pull_request) Has been skipped
CI / Update Infra Image Tags (pull_request) Has been skipped
- Fix CLIENT_ID/PET_ID in petsExtendedFields.test.ts to valid UUIDs so
  createPetSchema validation (z.string().uuid()) passes in tests
- Replace top-level imports of and/eq/exists/or with vi.fn() stubs in
  petsExtendedFields.test.ts mock to avoid vi.mock hoisting ReferenceError
- Add impersonationAuditLogs proxy + insert() chain to portal.test.ts mock
  to fix audit-log write failures
- Add 5 missing extended fields to buildPet factory defaults
- Add non-null assertion on petRows[0] in makeDeleteChainable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 02:36:18 +00:00
Flea Flicker 59893908e2 fix: resolve pre-existing TypeScript errors for CI compliance
CI / Lint & Typecheck (pull_request) Failing after 17s
CI / Test (pull_request) Failing after 24s
CI / Build (pull_request) Has been skipped
CI / Build & Push Docker Images (pull_request) Has been skipped
CI / Update Infra Image Tags (pull_request) Has been skipped
- petsExtendedFields.test.ts: import and/eq/exists/or from db/index.js
  (avoids mock scope collision with TypeScript closures)
- petsExtendedFields.test.ts: add non-null assertion on petRows[0]
  in makeDeleteChainable (petRows always has at least one element)
- factories.ts buildPet: add missing extended pet fields to defaults
  (coatType, temperamentScore, temperamentFlags, medicalAlerts,
  preferredCuts) so the inferred PetRow type is satisfied

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 02:23:05 +00:00
Flea Flicker 2b78fcf731 fix(ci): build all service images + upgrade Node 22 + pin packageManager (GRO-1522)
CI / Lint & Typecheck (pull_request) Failing after 18s
CI / Test (pull_request) Failing after 26s
CI / Build (pull_request) Has been skipped
CI / Build & Push Docker Images (pull_request) Has been skipped
CI / Update Infra Image Tags (pull_request) Has been skipped
- Upgrade CI jobs (lint-typecheck, test, build) to Node 22
- Dockerfile uses node:22-alpine for base and runner stages
- Root package.json gets packageManager field for corepack pin
- Docker build already targets all 4 stages (api/migrate/seed/reset)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 02:16:49 +00:00
Flea Flicker c9e176f08c Merge branch 'dev' of https://git.farh.net/groombook/api into dev
CI / Lint & Typecheck (push) Failing after 14s
CI / Test (push) Failing after 20s
CI / Build & Push Docker Image (push) Has been skipped
2026-05-21 22:54:47 +00:00
Flea Flicker 0cab1522cf fix(deps): update pnpm-lock.yaml for better-auth ^1.5.6
ERR_PNPM_OUTDATED_LOCKFILE — specifiers in lockfile did not match
packages/db/package.json after better-auth upgrade.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 22:54:01 +00:00
The Dogfather 2a27e8bee2 Merge pull request 'fix(auth): add accountLinking trustedProviders for authentik (GRO-1509)' (#42) from flea-flicker/gro-1509-better-auth-account-not-linked into dev
CI / Lint & Typecheck (push) Failing after 5s
CI / Test (push) Failing after 6s
CI / Build & Push Docker Image (push) Has been skipped
fix(auth): add accountLinking trustedProviders for authentik (GRO-1509)

Merged-by: The Dogfather (CTO)
QA-approved-by: Lint Roller (GRO-1510)
2026-05-21 22:47:25 +00:00
Flea Flicker d6f7ade7bd docs(UAT): add TC-API-1.16 for OIDC login Terraform-provisioned users
CI / Lint & Typecheck (pull_request) Failing after 6s
CI / Test (pull_request) Failing after 6s
CI / Build & Push Docker Image (pull_request) Has been skipped
Updated UAT_PLAYBOOK.md §4.1 — new TC-API-1.16 covering OIDC login
for Terraform-provisioned users (GRO-1509 fix, GRO-1511).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-21 22:44:04 +00:00
Flea Flicker 00dadac0a1 fix(auth): add accountLinking trustedProviders for authentik (GRO-1509)
CI / Test (pull_request) Failing after 44s
CI / Lint & Typecheck (pull_request) Failing after 52s
CI / Build & Push Docker Image (pull_request) Has been skipped
Betters Auth v1.5.6 link-account.mjs:22 rejects OAuth callbacks when the
genericOAuth provider is not in trustedProviders AND email_verified is
falsy. Adding authentik to trustedProviders bypasses this guard so OIDC
login works for TF-created users whose emails were never verified through
an authentik flow.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-21 22:24:48 +00:00
The Dogfather 9692476202 fix(GRO-1470): add portal PATCH /pets/:id + expand GET /pets response
CI / Lint & Typecheck (push) Failing after 7s
CI / Test (push) Failing after 7s
CI / Build & Push Docker Image (push) Has been skipped
2026-05-21 20:16:53 +00:00
9 changed files with 75 additions and 16 deletions
+44 -4
View File
@@ -25,7 +25,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: pnpm
- name: Install dependencies
@@ -49,7 +49,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: pnpm
- name: Install dependencies
@@ -59,7 +59,7 @@ jobs:
run: pnpm test
docker:
name: Build & Push Docker Image
name: Build & Push Docker Images
runs-on: ubuntu-latest
needs: [lint-typecheck, test]
steps:
@@ -91,9 +91,49 @@ jobs:
with:
context: .
file: Dockerfile
target: runner
push: true
tags: |
git.farh.net/groombook/api:${{ steps.version.outputs.tag }}
${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/api:latest' || '' }}
cache-from: type=registry,ref=git.farh.net/groombook/cache:api
cache-to: type=registry,ref=git.farh.net/groombook/cache:api,mode=max
cache-to: type=registry,ref=git.farh.net/groombook/cache:api,mode=max
- name: Build and push Migrate image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
target: migrate
push: true
tags: |
git.farh.net/groombook/migrate:${{ steps.version.outputs.tag }}
${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/migrate:latest' || '' }}
cache-from: type=registry,ref=git.farh.net/groombook/cache:migrate
cache-to: type=registry,ref=git.farh.net/groombook/cache:migrate,mode=max
- name: Build and push Seed image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
target: seed
push: true
tags: |
git.farh.net/groombook/seed:${{ steps.version.outputs.tag }}
${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/seed:latest' || '' }}
cache-from: type=registry,ref=git.farh.net/groombook/cache:seed
cache-to: type=registry,ref=git.farh.net/groombook/cache:seed,mode=max
- name: Build and push Reset image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
target: reset
push: true
tags: |
git.farh.net/groombook/reset:${{ steps.version.outputs.tag }}
${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/reset:latest' || '' }}
cache-from: type=registry,ref=git.farh.net/groombook/cache:reset
cache-to: type=registry,ref=git.farh.net/groombook/cache:reset,mode=max
+3 -3
View File
@@ -25,7 +25,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: pnpm
- name: Install dependencies
@@ -49,7 +49,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: pnpm
- name: Install dependencies
@@ -71,7 +71,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: pnpm
- name: Install dependencies
+2 -2
View File
@@ -1,4 +1,4 @@
FROM node:20-alpine AS base
FROM node:22-alpine AS base
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
WORKDIR /app
@@ -20,7 +20,7 @@ RUN pnpm --filter @groombook/types build && \
pnpm --filter @groombook/api build
# Runtime
FROM node:20-alpine AS runner
FROM node:22-alpine AS runner
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
WORKDIR /app
ENV NODE_ENV=production
+1
View File
@@ -38,6 +38,7 @@ GroomBook API is a Hono-based REST service (TypeScript/Node.js) powering the pet
| TC-API-1.13 | Name fallback — user.name present | Auto-provision where Better-Auth user has name set | Staff name = user.name value from user table |
| TC-API-1.14 | Name fallback — no name, email present | Auto-provision where Better-Auth user has name = null, email = "test@example.com" | Staff name = "test" (email prefix before @) |
| TC-API-1.15 | Name fallback — no name, no email | Auto-provision where Better-Auth user has name = null, email = null | Staff name = "Unknown" |
| TC-API-1.16 | OIDC login — Terraform-provisioned user | Initiate OIDC login as any UAT persona (uat-super, uat-groomer, uat-customer, uat-tester), complete authentik callback | 200 OK, session created — no account_not_linked error |
### 4.2 Client Management
@@ -135,7 +135,7 @@ function makeDeleteChainable(): unknown {
}
if (prop === "returning") {
return () => {
const row = petRows[0];
const row = petRows[0]!;
deletedId = row.id as string;
return [row];
};
@@ -165,10 +165,10 @@ vi.mock("../db", async (importOriginal) => {
}),
pets,
appointments,
and: db.and,
eq: db.eq,
exists: db.exists,
or: db.or,
and: vi.fn(),
eq: vi.fn(),
exists: vi.fn(),
or: vi.fn(),
};
});
+9
View File
@@ -67,6 +67,11 @@ vi.mock("../db", () => {
{ get: (t, p) => (p === "_name" ? "impersonationSessions" : { table: "impersonationSessions", column: p }) }
);
const impersonationAuditLogs = new Proxy(
{ _name: "impersonationAuditLogs" },
{ get: (t, p) => (p === "_name" ? "impersonationAuditLogs" : { table: "impersonationAuditLogs", column: p }) }
);
const appointments = new Proxy(
{ _name: "appointments" },
{ get: (t, p) => (p === "_name" ? "appointments" : { table: "appointments", column: p }) }
@@ -99,8 +104,12 @@ vi.mock("../db", () => {
}),
}),
}),
insert: () => ({
values: () => ({ returning: () => [{}] }),
}),
}),
impersonationSessions,
impersonationAuditLogs,
appointments,
eq: vi.fn(),
and: vi.fn(),
+1
View File
@@ -3,6 +3,7 @@
"version": "0.0.1",
"private": true,
"type": "module",
"packageManager": "pnpm@9.15.4",
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc --project .",
+6 -2
View File
@@ -28,7 +28,7 @@ importers:
version: 0.7.6(hono@4.12.18)(zod@4.4.3)
better-auth:
specifier: ^1.5.6
version: 1.6.10(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0))
version: 1.6.10(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0))
drizzle-orm:
specifier: ^0.38.4
version: 0.38.4(kysely@0.28.17)(postgres@3.4.9)
@@ -84,6 +84,9 @@ importers:
packages/db:
dependencies:
better-auth:
specifier: ^1.5.6
version: 1.6.10(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0))
drizzle-orm:
specifier: ^0.38.4
version: 0.38.4(kysely@0.28.17)(postgres@3.4.9)
@@ -3927,7 +3930,7 @@ snapshots:
balanced-match@4.0.4: {}
better-auth@1.6.10(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0)):
better-auth@1.6.10(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0)):
dependencies:
'@better-auth/core': 1.6.10(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.3))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/drizzle-adapter': 1.6.10(@better-auth/core@1.6.10(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.3))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))
@@ -3947,6 +3950,7 @@ snapshots:
nanostores: 1.3.0
zod: 4.4.3
optionalDependencies:
drizzle-kit: 0.30.6
drizzle-orm: 0.38.4(kysely@0.28.17)(postgres@3.4.9)
vitest: 3.2.4(@types/node@22.19.18)(tsx@4.21.0)
transitivePeerDependencies:
+4
View File
@@ -251,6 +251,10 @@ export async function initAuth(): Promise<void> {
},
},
account: {
accountLinking: {
enabled: true,
trustedProviders: ["authentik"],
},
storeStateStrategy: "cookie" as const,
},
emailAndPassword: {