( client: ReturnType<typeof getDbExec>, pg: boolean, )
| 111 | } |
| 112 | |
| 113 | async function ensureToolDataScope( |
| 114 | client: ReturnType<typeof getDbExec>, |
| 115 | pg: boolean, |
| 116 | ): Promise<void> { |
| 117 | const addCol = (name: string, def: string) => { |
| 118 | if (pg) { |
| 119 | return client.execute( |
| 120 | `ALTER TABLE tool_data ADD COLUMN IF NOT EXISTS ${name} ${def}`, |
| 121 | ); |
| 122 | } |
| 123 | return client |
| 124 | .execute(`ALTER TABLE tool_data ADD COLUMN ${name} ${def}`) |
| 125 | .catch((err: any) => { |
| 126 | if ( |
| 127 | !String(err?.message ?? err) |
| 128 | .toLowerCase() |
| 129 | .includes("duplicate") |
| 130 | ) |
| 131 | throw err; |
| 132 | }); |
| 133 | }; |
| 134 | await addCol("scope", "TEXT NOT NULL DEFAULT 'user'"); |
| 135 | await addCol("org_id", "TEXT"); |
| 136 | await addCol("scope_key", "TEXT NOT NULL DEFAULT 'local@localhost'"); |
| 137 | // One-time backfill migration: replaces the dev-mode DEFAULT scope_key |
| 138 | // with each row's real owner_email. Not a per-request fallback. |
| 139 | await client.execute( |
| 140 | // guard:allow-localhost-fallback — one-time backfill migration replacing dev-mode default scope_key with the row's real owner_email |
| 141 | `UPDATE tool_data SET scope_key = owner_email WHERE scope_key = 'local@localhost' AND owner_email != 'local@localhost'`, |
| 142 | ); |
| 143 | } |
| 144 | |
| 145 | export function registerToolsShareable() { |
| 146 | registerShareableResource({ |
no test coverage detected