From 44927b245cec779630b66fcb8d4cfdcf19f6891d Mon Sep 17 00:00:00 2001 From: CarterPerez-dev Date: Sun, 17 May 2026 17:58:13 -0400 Subject: [PATCH] fix(canary): accept null events from manage response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend serializes `Events []Event` as JSON `null` when the slice is nil (Go's zero value for slices). Spec §8.4 shows it as an array — stale spec, verified actual behavior with `curl http://localhost:22784/api/m/` returning `"events": null` on a freshly-created token with no triggers. Zod schema was `events: z.array(eventResponseSchema)` — failed to parse the null, threw PARSE_ERROR, manage page rendered "CANNOT REACH ARCHIVE" instead of the empty dossier. Fixed: `.nullish().transform(v => v ?? [])` — accepts null/undefined and normalizes to []. Manage page's `events.length === 0` empty-state check ("No events recorded yet") now reachable; consumers always see an array. Caught by memory rule feedback_verify_data_shapes.md: trust reality > spec. I trusted §8.4's example object during Phase 14 schema design instead of hitting the live endpoint. Same kind of drift as the four Phase-14 spec-vs-code divergences cleared at the time — this one slipped through because TokenManagePage was never end-to-end exercised pre-UI. --- .../canary-token-generator/frontend/src/api/types/event.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PROJECTS/beginner/canary-token-generator/frontend/src/api/types/event.ts b/PROJECTS/beginner/canary-token-generator/frontend/src/api/types/event.ts index dc767b7f..22b18c45 100644 --- a/PROJECTS/beginner/canary-token-generator/frontend/src/api/types/event.ts +++ b/PROJECTS/beginner/canary-token-generator/frontend/src/api/types/event.ts @@ -47,7 +47,10 @@ export type ManagePage = z.infer export const manageResponseSchema = z.object({ token: manageTokenViewSchema, - events: z.array(eventResponseSchema), + events: z + .array(eventResponseSchema) + .nullish() + .transform((v) => v ?? []), events_total: z.number().int().nonnegative(), events_silenced_active: z.number().int().nonnegative(), page: managePageSchema,