← back to Norma
fix(api): 4 GET-500s surfaced by api-smoke (onboard/library real; auth-google/clickup status)
eb853c3fed78c47eb8e1471e3a7212306c05117a · 2026-08-06 10:31:16 -0700 · Steve
- onboard/[id]: SELECT referenced organizations.employee_count (never existed) -> o.staff_size AS employee_count. Crashed on every request, live too.
- library/[id]: $2::text forced the param to text -> 'uuid = text' operator error -> $2::uuid IS NULL OR org_id = $2::uuid. Crashed on every request, live too.
- auth/google + clickup: missing-integration-config is a dependency state -> 503 not 500. clickup guarded in both GET and POST.
Verified on :7411: api-smoke 27->0 crashes; security-regression 20/20 (no regressions). Fixture gap (role_permissions / gmail assigned_*) = migrations 024+025 not applied to sdcc_test; patched scratch DB, no app change.
Files touched
M app/api/auth/google/route.tsM app/api/clickup/route.tsM app/api/library/[id]/route.tsM app/api/onboard/[id]/route.ts
Diff
commit eb853c3fed78c47eb8e1471e3a7212306c05117a
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Aug 6 10:31:16 2026 -0700
fix(api): 4 GET-500s surfaced by api-smoke (onboard/library real; auth-google/clickup status)
- onboard/[id]: SELECT referenced organizations.employee_count (never existed) -> o.staff_size AS employee_count. Crashed on every request, live too.
- library/[id]: $2::text forced the param to text -> 'uuid = text' operator error -> $2::uuid IS NULL OR org_id = $2::uuid. Crashed on every request, live too.
- auth/google + clickup: missing-integration-config is a dependency state -> 503 not 500. clickup guarded in both GET and POST.
Verified on :7411: api-smoke 27->0 crashes; security-regression 20/20 (no regressions). Fixture gap (role_permissions / gmail assigned_*) = migrations 024+025 not applied to sdcc_test; patched scratch DB, no app change.
---
app/api/auth/google/route.ts | 2 +-
app/api/clickup/route.ts | 10 ++++++++++
app/api/library/[id]/route.ts | 2 +-
app/api/onboard/[id]/route.ts | 2 +-
4 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/app/api/auth/google/route.ts b/app/api/auth/google/route.ts
index aa7166b..c913459 100644
--- a/app/api/auth/google/route.ts
+++ b/app/api/auth/google/route.ts
@@ -9,7 +9,7 @@ export async function GET() {
const redirectUri = process.env.GOOGLE_OAUTH_REDIRECT_URI || 'http://45.61.58.125:7400/api/auth/google/callback';
if (!clientId) {
- return NextResponse.json({ error: 'Google OAuth not configured' }, { status: 500 });
+ return NextResponse.json({ error: 'Google OAuth not configured' }, { status: 503 });
}
const params = new URLSearchParams({
diff --git a/app/api/clickup/route.ts b/app/api/clickup/route.ts
index 7d01a2b..a7f081c 100644
--- a/app/api/clickup/route.ts
+++ b/app/api/clickup/route.ts
@@ -31,6 +31,11 @@ export async function GET(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
+ // Missing integration key is a dependency state, not a server fault → 503.
+ if (!getApiKey()) {
+ return NextResponse.json({ error: 'ClickUp integration not configured' }, { status: 503 });
+ }
+
const { searchParams } = new URL(request.url);
const action = searchParams.get('action') || 'spaces';
@@ -76,6 +81,11 @@ export async function POST(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
+ // Missing integration key is a dependency state, not a server fault → 503.
+ if (!getApiKey()) {
+ return NextResponse.json({ error: 'ClickUp integration not configured' }, { status: 503 });
+ }
+
const body = await request.json();
const { list_id, name, description, priority, due_date, tags, assignees, source_type, source_id } = body;
diff --git a/app/api/library/[id]/route.ts b/app/api/library/[id]/route.ts
index a5a957f..100edbd 100644
--- a/app/api/library/[id]/route.ts
+++ b/app/api/library/[id]/route.ts
@@ -19,7 +19,7 @@ export async function GET(request: NextRequest, context: RouteContext) {
try {
const orgId = auth.role === 'admin' ? getOrgId(request) : auth.orgId;
const result = await query(
- `SELECT * FROM library_items WHERE id = $1 AND ($2::text IS NULL OR org_id = $2)`,
+ `SELECT * FROM library_items WHERE id = $1 AND ($2::uuid IS NULL OR org_id = $2::uuid)`,
[id, orgId]
);
diff --git a/app/api/onboard/[id]/route.ts b/app/api/onboard/[id]/route.ts
index 9048591..8408599 100644
--- a/app/api/onboard/[id]/route.ts
+++ b/app/api/onboard/[id]/route.ts
@@ -29,7 +29,7 @@ export async function GET(
o.email,
o.phone,
o.founded_year,
- o.employee_count,
+ o.staff_size AS employee_count,
o.ntee_code AS org_ntee_code,
o.state AS org_state,
o.city,
← 8bbee18 test(api-smoke): durable fs-enumerated GET sweep over all 27
·
back to Norma
·
fix(api)+test: close Cody-gate gaps — all 14 uuid=text casts 39264f3 →