Skip to content

Commit 292d146

Browse files
authored
Merge pull request #47 from alanshurafa/contrib/alanshurafa/thoughts-uuid-dashboard
[dashboards] pro dashboard: handle UUID thought ids
2 parents 94e02de + b2d7685 commit 292d146

8 files changed

Lines changed: 46 additions & 37 deletions

File tree

dashboards/open-brain-dashboard-pro/app/api/audit/delete/route.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,17 @@ export async function POST(request: NextRequest) {
3737
{ status: 400 }
3838
);
3939
}
40-
const sanitized: number[] = [];
40+
const UUID_RE =
41+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
42+
const sanitized: string[] = [];
4143
for (const raw of ids) {
42-
if (!Number.isInteger(raw) || (raw as number) <= 0) {
44+
if (typeof raw !== "string" || !UUID_RE.test(raw)) {
4345
return NextResponse.json(
44-
{ error: "All IDs must be positive integers" },
46+
{ error: "All IDs must be valid UUIDs" },
4547
{ status: 400 }
4648
);
4749
}
48-
sanitized.push(raw as number);
50+
sanitized.push(raw);
4951
}
5052

5153
// BL-03: Re-verify each thought actually has quality_score < 30 before deleting
@@ -57,7 +59,7 @@ export async function POST(request: NextRequest) {
5759
sanitized.map((id) => fetchThought(apiKey, id, excludeRestricted))
5860
);
5961

60-
const verifiedIds: number[] = [];
62+
const verifiedIds: string[] = [];
6163
let rejected = 0;
6264
for (let i = 0; i < verifyResults.length; i++) {
6365
const r = verifyResults[i];

dashboards/open-brain-dashboard-pro/app/api/duplicates/resolve/route.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,23 @@ export async function POST(request: NextRequest) {
2929
thought_id_b: unknown;
3030
};
3131

32-
// BL-03: Validate IDs are positive integers, not truthy-but-wrong values
32+
// BL-03: Validate IDs are UUIDs, not truthy-but-wrong values. OB1 thought
33+
// ids are UUIDs, not integers.
34+
const UUID_RE =
35+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3336
if (
34-
!Number.isInteger(thought_id_a) ||
35-
(thought_id_a as number) <= 0 ||
36-
!Number.isInteger(thought_id_b) ||
37-
(thought_id_b as number) <= 0
37+
typeof thought_id_a !== "string" ||
38+
!UUID_RE.test(thought_id_a) ||
39+
typeof thought_id_b !== "string" ||
40+
!UUID_RE.test(thought_id_b)
3841
) {
3942
return NextResponse.json(
40-
{ error: "Both thought_id_a and thought_id_b must be positive integers" },
43+
{ error: "Both thought_id_a and thought_id_b must be valid UUIDs" },
4144
{ status: 400 }
4245
);
4346
}
44-
const idA = thought_id_a as number;
45-
const idB = thought_id_b as number;
47+
const idA = thought_id_a;
48+
const idB = thought_id_b;
4649

4750
if (idA === idB) {
4851
return NextResponse.json(

dashboards/open-brain-dashboard-pro/app/api/thoughts/[id]/connections/route.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ export async function GET(
1616

1717
const { id } = await params;
1818

19-
// WR-04: Validate id is a positive integer before forwarding
20-
const idNum = Number(id);
21-
if (!Number.isInteger(idNum) || idNum <= 0) {
19+
// WR-04: Validate id is a UUID before forwarding. OB1 thought ids are UUIDs,
20+
// not integers — the old positive-integer check rejected them.
21+
const UUID_RE =
22+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
23+
if (!UUID_RE.test(id)) {
2224
return NextResponse.json({ error: "Invalid id" }, { status: 400 });
2325
}
2426

@@ -36,7 +38,7 @@ export async function GET(
3638

3739
try {
3840
const res = await fetch(
39-
`${API_URL}/thought/${idNum}/connections?exclude_restricted=${excludeRestricted}&limit=20`,
41+
`${API_URL}/thought/${id}/connections?exclude_restricted=${excludeRestricted}&limit=20`,
4042
{
4143
headers: {
4244
"x-brain-key": apiKey,

dashboards/open-brain-dashboard-pro/app/audit/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { Thought, BrowseResponse } from "@/lib/types";
88

99
export default function AuditPage() {
1010
const [data, setData] = useState<BrowseResponse | null>(null);
11-
const [selected, setSelected] = useState<Set<number>>(new Set());
11+
const [selected, setSelected] = useState<Set<string>>(new Set());
1212
const [page, setPage] = useState(1);
1313
const [loading, setLoading] = useState(true);
1414
const [showDelete, setShowDelete] = useState(false);
@@ -56,7 +56,7 @@ export default function AuditPage() {
5656
setPage(next);
5757
};
5858

59-
const toggleSelect = (id: number) => {
59+
const toggleSelect = (id: string) => {
6060
setSelected((prev) => {
6161
const next = new Set(prev);
6262
if (next.has(id)) next.delete(id);

dashboards/open-brain-dashboard-pro/app/thoughts/[id]/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ export default async function ThoughtDetailPage({
2424
const session = await getSession();
2525
const excludeRestricted = !session.restrictedUnlocked;
2626
const { id } = await params;
27-
const thoughtId = parseInt(id, 10);
28-
if (isNaN(thoughtId)) notFound();
27+
const UUID_RE =
28+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
29+
const thoughtId = id;
30+
if (!UUID_RE.test(thoughtId)) notFound();
2931

3032
let thought;
3133
try {

dashboards/open-brain-dashboard-pro/components/ConnectionsPanel.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { TypeBadge } from "./ThoughtCard";
66
import { FormattedDate } from "./FormattedDate";
77

88
interface Connection {
9-
id: number;
9+
id: string;
1010
type: string;
1111
importance: number;
1212
preview: string;
@@ -20,7 +20,7 @@ export function ConnectionsPanel({
2020
thoughtId,
2121
hasMetadata,
2222
}: {
23-
thoughtId: number;
23+
thoughtId: string;
2424
hasMetadata: boolean;
2525
}) {
2626
const [connections, setConnections] = useState<Connection[] | null>(

dashboards/open-brain-dashboard-pro/lib/api.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export async function fetchThoughts(
131131

132132
export async function fetchThought(
133133
apiKey: string,
134-
id: number,
134+
id: string,
135135
excludeRestricted: boolean = true
136136
): Promise<Thought> {
137137
const qs = excludeRestricted ? "" : "?exclude_restricted=false";
@@ -140,10 +140,10 @@ export async function fetchThought(
140140

141141
export async function updateThought(
142142
apiKey: string,
143-
id: number,
143+
id: string,
144144
data: { content?: string; type?: string; importance?: number }
145-
): Promise<{ id: number; action: string; message: string }> {
146-
return apiFetch<{ id: number; action: string; message: string }>(
145+
): Promise<{ id: string; action: string; message: string }> {
146+
return apiFetch<{ id: string; action: string; message: string }>(
147147
apiKey,
148148
`/thought/${id}`,
149149
{
@@ -169,8 +169,8 @@ export async function fetchDuplicates(
169169

170170
export interface DuplicateResolveResult {
171171
action: string;
172-
survivor_id: number | null;
173-
loser_id: number | null;
172+
survivor_id: string | null;
173+
loser_id: string | null;
174174
reattached: {
175175
reflections: number;
176176
thought_entities: number;
@@ -180,8 +180,8 @@ export interface DuplicateResolveResult {
180180
export async function resolveDuplicate(
181181
apiKey: string,
182182
params: {
183-
thought_id_a: number;
184-
thought_id_b: number;
183+
thought_id_a: string;
184+
thought_id_b: string;
185185
action: "keep_a" | "keep_b" | "keep_both";
186186
}
187187
): Promise<DuplicateResolveResult> {
@@ -193,7 +193,7 @@ export async function resolveDuplicate(
193193

194194
export async function deleteThought(
195195
apiKey: string,
196-
id: number
196+
id: string
197197
): Promise<void> {
198198
await apiFetch<unknown>(apiKey, `/thought/${id}`, { method: "DELETE" });
199199
}
@@ -236,7 +236,7 @@ export async function fetchStats(
236236
}
237237

238238
export interface CaptureResult {
239-
thought_id: number;
239+
thought_id: string;
240240
action: string;
241241
type: string;
242242
sensitivity_tier: string;

dashboards/open-brain-dashboard-pro/lib/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export interface Thought {
2-
id: number;
2+
id: string;
33
uuid?: string;
44
content: string;
55
type: string;
@@ -40,8 +40,8 @@ export interface StatsResponse {
4040
}
4141

4242
export interface DuplicatePair {
43-
thought_id_a: number;
44-
thought_id_b: number;
43+
thought_id_a: string;
44+
thought_id_b: string;
4545
similarity: number;
4646
content_a: string;
4747
content_b: string;
@@ -316,7 +316,7 @@ export type AddToBrainMode = "auto" | "single" | "extract";
316316

317317
export interface AddToBrainResult {
318318
path: "single" | "extract";
319-
thought_id?: number;
319+
thought_id?: string;
320320
job_id?: string;
321321
type?: string;
322322
status?: string;

0 commit comments

Comments
 (0)