Skip to content

Commit a64ef3c

Browse files
os-zhuangclaude
andcommitted
fix(runtime): accept integer ai_access (Turso) in the AI-seat synthesis
sys_user.ai_access reads back as integer 1 on Turso/libSQL (sqlite booleans), but the seat synthesis checked `=== true` (boolean) — so `1 !== true` and a SEATED user got no `ai_seat` -> /ai/agents=[] under enforce. The memory driver returns a JS boolean, which masked it in local testing. Caught on a real Turso-backed staging env (the env creator was seated yet denied). Accept `true | 1 | '1'` in both synthesis points: resolveExecutionContext (the gate) and plugin-hono-server data-route resolveCtx. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent e24ee8b commit a64ef3c

2 files changed

Lines changed: 8 additions & 2 deletions

File tree

packages/plugins/plugin-hono-server/src/hono-plugin.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,9 @@ export class HonoServerPlugin implements Plugin {
509509
'sys_user',
510510
{ where: { id: userId }, limit: 1, ...sysCtx } as any,
511511
).catch(() => []);
512-
if ((uRows?.[0] as any)?.ai_access === true) permissions.push('ai_seat');
512+
// Turso returns sqlite booleans as 1/0; memory driver as boolean.
513+
const aiAccess = (uRows?.[0] as any)?.ai_access;
514+
if (aiAccess === true || aiAccess === 1 || aiAccess === '1') permissions.push('ai_seat');
513515
} catch {
514516
/* no ai_access column / query failed → no seat (safe) */
515517
}

packages/runtime/src/security/resolve-execution-context.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,11 @@ export async function resolveExecutionContext(opts: ResolveOptions): Promise<Exe
414414
// Guarded (tryFind swallows errors) → can only ever ADD access, never break auth.
415415
if (userId && !ctx.permissions!.includes('ai_seat')) {
416416
const seatRows = await tryFind(ql, 'sys_user', { id: userId }, 1);
417-
if ((seatRows?.[0] as { ai_access?: unknown } | undefined)?.ai_access === true) {
417+
// Turso/libSQL returns sqlite booleans as integer 1/0; the memory driver
418+
// returns a JS boolean. Accept both (+ the stringified form) so the seat
419+
// resolves regardless of the env's data driver.
420+
const aiAccess = (seatRows?.[0] as { ai_access?: unknown } | undefined)?.ai_access;
421+
if (aiAccess === true || aiAccess === 1 || aiAccess === '1') {
418422
ctx.permissions!.push('ai_seat');
419423
}
420424
}

0 commit comments

Comments
 (0)