[dashboards] open-brain-dashboard-next: type Thought.id as string for UUID#250
Conversation
… UUID
The upstream thoughts.id column is UUID, but the dashboard typed
Thought.id (and most thought-FK references) as number and routed
detail pages through parseInt(id, 10). Every Browse → Detail click
parsed to NaN, hit the isNaN guard, and 404'd — confirmed live.
Switches every thought-id surface from number to string and removes
the parseInt at app/thoughts/[id]/page.tsx:29 so the route param
flows straight through. The Cloudflare REST gateway has been
UUID-native the whole time (.eq("id", id) with a string param), so
no backend change is needed.
Touched:
- lib/types.ts: Thought.id, Reflection.thought_id, DuplicatePair
thought_id_a/_b, AddToBrainResult.thought_id
- lib/api.ts: fetchThought, updateThought, deleteThought,
fetchReflections signatures + CaptureResult.thought_id +
updateThought response shape
- app/thoughts/[id]/page.tsx: drop parseInt + isNaN, pass param
through as string
- components/ConnectionsPanel.tsx: Connection.id + thoughtId prop
- components/ReflectionComposer.tsx: thoughtId prop
- components/Kanban{Board,Card,CardModal,Column}.tsx: every
thoughtId in handler signatures, plus the active.id cast in
handleDragEnd
- app/audit/page.tsx: bulk-select Set<number> → Set<string>,
toggleSelect signature
- API proxy routes (audit/delete, duplicates/resolve,
kanban/{delete,update}): typeof checks and id array types
IngestionJob/IngestionItem ids stay number — those tables are
BIGSERIAL, not UUID. Reflection.id stays number too; if the
reflections-table schema ever lands it may need revisiting.
Vercel deploys benefit equally — purely a type-correctness fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@alanshurafa — wanted to flag something puzzling in case you have context that'd help, since you originally landed this dashboard: The dashboard's What I can't tell from the code alone is how it got that way — whether If you've got context on the original intent, I'd love to hear it before this lands — happy to revise the approach. If the change as-is is fine, no action needed. |
|
Thanks for flagging this carefully. No hidden intent the id: number + separate uuid?: string shape was a holdover from an earlier prototype against a different schema, not a deliberate two purpose design. By the time the dashboard landed, the canonical column was already UUID; the types just never got reconciled, and Detail navigation apparently never got clicked through on a real instance before merge. Your fix is the right shape id: string everywhere except the genuinely numeric BIGSERIAL ingestion fields, which matches what's actually in the DB. Please land it as is. |
Contribution Type
/dashboards)What does this do?
Fixes a navigation bug: every Browse → Detail click in the dashboard 404'd because
app/thoughts/[id]/page.tsx:29ranparseInt(id, 10)on the URL param, but the upstreamthoughts.idcolumn isUUID. UUIDs parse toNaN, theisNaNguard fired, and the page returned 404. Confirmed live before this change; confirmed fixed after.This is the dashboard-side counterpart to the type mismatch I documented as Known Limitation #1 in PR #239 (the REST gateway). The gateway has been UUID-native the whole time —
c.req.param("id")flows straight to.eq("id", id)and Supabase coerces it correctly. The dashboard'sThought.id: numberwas the side that needed fixing.Purely a type-correctness change. Vercel deploys benefit equally — no runtime behavior change beyond Detail navigation now working.
Changes
lib/types.ts—Thought.id,Reflection.thought_id,DuplicatePair.thought_id_a/_b,AddToBrainResult.thought_id→stringlib/api.ts—fetchThought,updateThought,deleteThought,fetchReflectionsparameter types;CaptureResult.thought_idandupdateThoughtresponse shapeapp/thoughts/[id]/page.tsx— dropparseInt/isNaN, pass route param straight throughcomponents/ConnectionsPanel.tsx,ReflectionComposer.tsx— prop typescomponents/Kanban{Board,Card,CardModal,Column}.tsx— everythoughtIdin handler signatures, plus theactive.id as stringcast inhandleDragEndapp/audit/page.tsx— bulk-selectSet<number>→Set<string>What stays as
numberIngestionJob.id,IngestionJob.job_id,IngestionItem.{id,job_id},AddToBrainResult.job_id— the ingestion tables are BIGSERIAL, not UUIDReflection.id— would be reflections-table PK; no schema for that table ships in the repo yet (Known Limitation Add non-dev contribution path, contributor ladder, and CONTRIBUTORS.md #3 from [integrations] open-brain-rest — Cloudflare Worker REST gateway for the Next.js dashboard #239)Tested end-to-end
Live deploy on Cloudflare Workers (REST gateway from #239 backed by my Open Brain Supabase):
NaNconsole errors, no type-coercion runtime errorsRequirements
None — pure TypeScript / control-flow change. No new dependencies.
tsc --noEmitpasses; OpenNext build passes.Checklist