History

Fix migration 0008 parser stack overflow on macOS bun:sqlite (#745)

* Fix migration 0008 parser stack overflow on macOS bun:sqlite Migration 0008 inlined a 41-deep nested replace() chain (8 dash-collapse replaces wrapping lower(33 single-char replaces wrapping the raw input)) to slugify header names into slot_keys. Bun's lemon SQL parser stack overflows at PREPARE time on the compiled CLI binary on macOS, so users upgrading on Mac couldn't start the CLI at all (the Linux test matrix in CI never exercised the failing path). Replace the deep chain with a temp __slug_norm table populated once at the top of the migration via a series of shallow UPDATE statements (one per replacement), then reference the precomputed slug via flat scalar subqueries everywhere. Semantics verified equivalent against 25 inputs covering case, punctuation, whitespace, dashes-only and unicode. Add structural lint that scans every drizzle migration file and rejects any nested-function call > 20 deep. Catches the regression class on Linux CI without needing macOS in the matrix. * Drop changeset, swap throw for typed expect to satisfy oxlint - Remove .changeset/fix-migration-0008-parser-overflow.md: the existing .changeset/executor-1.4.16.md (still in main, consumed when the open Version Packages PR merges) is enough to ship 1.4.16 with this fix included. - Replace throw new Error(...) in migration-nesting.test.ts with a shaped expect(...).toEqual({...}) that prints file/line/fn/depth in the diff. Satisfies oxlint's no-error-constructor / no-try-catch-or-throw rules without losing the diagnostic.

Rhys Sullivan committed 6 months ago

Commit baf3bd41 parent 69af8b82 files · +228 −34Browse files

Unified · Split

2 files
  1. apps/local/drizzle/0008_scoped_credentials_cutover.sql +120 −34
  2. apps/local/src/server/migration-nesting.test.ts +108 −0
apps/local/drizzle/0008_scoped_credentials_cutover.sql+120−34
@@ -1,3 +1,86 @@
1+--
2+-- Slug-normalization staging table.
3+--
4+-- 0008 originally inlined a 41-deep `replace(replace(... lower(...) ...))`
5+-- chain everywhere it derived a slot_key from a header / param / oauth
6+-- scheme name. bun:sqlite's lemon parser stack overflows on that depth on
7+-- platforms with smaller thread stacks (notably the compiled CLI binary on
8+-- macOS), so we precompute slugs once into a temp table and reference them
9+-- via flat scalar subqueries below.
10+--
11+CREATE TEMP TABLE `__slug_norm` (
12+ `raw` text PRIMARY KEY,
13+ `slug` text NOT NULL DEFAULT ''
14+);--> statement-breakpoint
15+
16+INSERT OR IGNORE INTO `__slug_norm` (`raw`)
17+SELECT DISTINCT `raw` FROM (
18+ SELECT h.`key` AS `raw` FROM `openapi_source` s, json_each(s.`headers`) h
19+ WHERE s.`headers` IS NOT NULL AND h.`type` = 'object'
20+ UNION
21+ SELECT json_extract(s.`oauth2`, '$.securitySchemeName') FROM `openapi_source` s
22+ WHERE s.`oauth2` IS NOT NULL
23+ UNION
24+ SELECT `name` FROM `openapi_source_query_param` WHERE `name` IS NOT NULL
25+ UNION
26+ SELECT `name` FROM `openapi_source_spec_fetch_header` WHERE `name` IS NOT NULL
27+ UNION
28+ SELECT `name` FROM `openapi_source_spec_fetch_query_param` WHERE `name` IS NOT NULL
29+ UNION
30+ SELECT `name` FROM `graphql_source_header` WHERE `name` IS NOT NULL
31+ UNION
32+ SELECT `name` FROM `graphql_source_query_param` WHERE `name` IS NOT NULL
33+ UNION
34+ SELECT `name` FROM `mcp_source_header` WHERE `name` IS NOT NULL
35+ UNION
36+ SELECT `name` FROM `mcp_source_query_param` WHERE `name` IS NOT NULL
37+) WHERE `raw` IS NOT NULL AND `raw` != '';--> statement-breakpoint
38+
39+UPDATE `__slug_norm` SET `slug` = lower(trim(`raw`));--> statement-breakpoint
40+UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(9), '-');--> statement-breakpoint
41+UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(10), '-');--> statement-breakpoint
42+UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(13), '-');--> statement-breakpoint
43+UPDATE `__slug_norm` SET `slug` = replace(`slug`, ' ', '-');--> statement-breakpoint
44+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '_', '-');--> statement-breakpoint
45+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '.', '-');--> statement-breakpoint
46+UPDATE `__slug_norm` SET `slug` = replace(`slug`, ':', '-');--> statement-breakpoint
47+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '/', '-');--> statement-breakpoint
48+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '@', '-');--> statement-breakpoint
49+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '+', '-');--> statement-breakpoint
50+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '&', '-');--> statement-breakpoint
51+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '?', '-');--> statement-breakpoint
52+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '#', '-');--> statement-breakpoint
53+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '%', '-');--> statement-breakpoint
54+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '$', '-');--> statement-breakpoint
55+UPDATE `__slug_norm` SET `slug` = replace(`slug`, ',', '-');--> statement-breakpoint
56+UPDATE `__slug_norm` SET `slug` = replace(`slug`, ';', '-');--> statement-breakpoint
57+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '(', '-');--> statement-breakpoint
58+UPDATE `__slug_norm` SET `slug` = replace(`slug`, ')', '-');--> statement-breakpoint
59+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '[', '-');--> statement-breakpoint
60+UPDATE `__slug_norm` SET `slug` = replace(`slug`, ']', '-');--> statement-breakpoint
61+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '{', '-');--> statement-breakpoint
62+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '}', '-');--> statement-breakpoint
63+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '=', '-');--> statement-breakpoint
64+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '~', '-');--> statement-breakpoint
65+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '!', '-');--> statement-breakpoint
66+UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(34), '-');--> statement-breakpoint
67+UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(39), '-');--> statement-breakpoint
68+UPDATE `__slug_norm` SET `slug` = replace(`slug`, char(92), '-');--> statement-breakpoint
69+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '|', '-');--> statement-breakpoint
70+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '*', '-');--> statement-breakpoint
71+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '<', '-');--> statement-breakpoint
72+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '>', '-');--> statement-breakpoint
73+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
74+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
75+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
76+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
77+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
78+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
79+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
80+UPDATE `__slug_norm` SET `slug` = replace(`slug`, '--', '-');--> statement-breakpoint
81+UPDATE `__slug_norm` SET `slug` = trim(`slug`, '-');--> statement-breakpoint
82+UPDATE `__slug_norm` SET `slug` = CASE WHEN `slug` = '' THEN 'default' ELSE `slug` END;--> statement-breakpoint
83+
184 -- local scoped credential/source-slot/OAuth cutover.
285 -- Squashes the PR-local migration chain into one runtime schema transition.
386 -- 0008_add_credential_binding.sql
@@ -101,7 +184,7 @@ INSERT INTO `__openapi_header_slot_preflight` (`scope_id`, `source_id`, `slot_ke · 97 unmodified lines
101184 SELECT
102185 s.`scope_id`,
103186 s.`id`,
104− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
187+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key`
105188 FROM `openapi_source` s, json_each(s.`headers`) h
106189 WHERE s.`headers` IS NOT NULL
107190 AND h.`type` = 'object'
@@ -115,7 +198,7 @@ WITH header_rows AS ( · 7 unmodified lines
115198 s.`scope_id`,
116199 s.`id` AS `source_id`,
117200 h.`key` AS `name`,
118− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
201+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key`,
119202 json_extract(h.`value`, '$.secretId') AS `secret_id`
120203 FROM `openapi_source` s, json_each(s.`headers`) h
121204 WHERE s.`headers` IS NOT NULL
@@ -161,7 +244,7 @@ SET `headers` = ( · 39 unmodified lines
161244 AND json_extract(h.`value`, '$.prefix') IS NOT NULL
162245 THEN json_object(
163246 'kind', 'binding',
164− 'slot', 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
247+ 'slot', 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default'),
165248 'prefix', json_extract(h.`value`, '$.prefix')
166249 )
167250 WHEN h.`type` = 'object'
@@ -169,7 +252,7 @@ SET `headers` = ( · 1 unmodified line
169252 AND json_extract(h.`value`, '$.secretId') IS NOT NULL
170253 THEN json_object(
171254 'kind', 'binding',
172− 'slot', 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default')
255+ 'slot', 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default')
173256 )
174257 WHEN h.`type` IN ('object', 'array') THEN json(h.`value`)
175258 ELSE h.`value`
@@ -186,7 +269,7 @@ WITH oauth_rows AS ( · 10 unmodified lines
186269 s.`scope_id`,
187270 s.`id` AS `source_id`,
188271 json_extract(s.`oauth2`, '$.securitySchemeName') AS `security_scheme_name`,
189− 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(s.`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-id' AS `client_id_slot`,
272+ 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(s.`oauth2`, '$.securitySchemeName')), 'default') || ':client-id' AS `client_id_slot`,
190273 json_extract(s.`oauth2`, '$.clientIdSecretId') AS `client_id_secret_id`,
191274 json_extract(s.`oauth2`, '$.connectionId') AS `connection_id`
192275 FROM `openapi_source` s
@@ -225,7 +308,7 @@ WITH oauth_rows AS ( · 32 unmodified lines
225308 SELECT
226309 s.`scope_id`,
227310 s.`id` AS `source_id`,
228− 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(s.`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-secret' AS `client_secret_slot`,
311+ 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(s.`oauth2`, '$.securitySchemeName')), 'default') || ':client-secret' AS `client_secret_slot`,
229312 json_extract(s.`oauth2`, '$.clientSecretSecretId') AS `client_secret_secret_id`
230313 FROM `openapi_source` s
231314 WHERE s.`oauth2` IS NOT NULL
@@ -263,7 +346,7 @@ WITH oauth_rows AS ( · 31 unmodified lines
263346 SELECT
264347 s.`scope_id`,
265348 s.`id` AS `source_id`,
266− 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(s.`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':connection' AS `connection_slot`,
349+ 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(s.`oauth2`, '$.securitySchemeName')), 'default') || ':connection' AS `connection_slot`,
267350 json_extract(s.`oauth2`, '$.connectionId') AS `connection_id`
268351 FROM `openapi_source` s
269352 WHERE s.`oauth2` IS NOT NULL
@@ -304,13 +387,13 @@ SET `oauth2` = json_object( · 34 unmodified lines
304387 'tokenUrl', json_extract(`oauth2`, '$.tokenUrl'),
305388 'authorizationUrl', json_extract(`oauth2`, '$.authorizationUrl'),
306389 'issuerUrl', json_extract(`oauth2`, '$.issuerUrl'),
307− 'clientIdSlot', 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-id',
390+ 'clientIdSlot', 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(`oauth2`, '$.securitySchemeName')), 'default') || ':client-id',
308391 'clientSecretSlot',
309392 CASE
310393 WHEN json_extract(`oauth2`, '$.clientSecretSecretId') IS NULL THEN NULL
311− ELSE 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':client-secret'
394+ ELSE 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(`oauth2`, '$.securitySchemeName')), 'default') || ':client-secret'
312395 END,
313− 'connectionSlot', 'oauth2:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(json_extract(`oauth2`, '$.securitySchemeName')), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') || ':connection',
396+ 'connectionSlot', 'oauth2:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = json_extract(`oauth2`, '$.securitySchemeName')), 'default') || ':connection',
314397 'scopes', json(COALESCE(json_extract(`oauth2`, '$.scopes'), '[]'))
315398 )
316399 WHERE `oauth2` IS NOT NULL
@@ -328,7 +411,7 @@ INSERT INTO `__openapi_query_param_slot_preflight` (`scope_id`, `source_id`, `sl · 11 unmodified lines
328411 SELECT
329412 r.`scope_id`,
330413 r.`source_id`,
331− 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
414+ 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`
332415 FROM `openapi_source_query_param` r
333416 WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL;--> statement-breakpoint
334417
@@ -338,7 +421,7 @@ WITH rows AS ( · 3 unmodified lines
338421 SELECT
339422 r.`scope_id`,
340423 r.`source_id`,
341− 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
424+ 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`,
342425 r.`secret_id`
343426 FROM `openapi_source_query_param` r
344427 WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL
@@ -374,7 +457,7 @@ ALTER TABLE `openapi_source_query_param` ADD `slot_key` text;--> statement-break · 29 unmodified lines
374457 ALTER TABLE `openapi_source_query_param` ADD `prefix` text;--> statement-breakpoint
375458 UPDATE `openapi_source_query_param`
376459 SET
377− `slot_key` = 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
460+ `slot_key` = 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'),
378461 `prefix` = `secret_prefix`,
379462 `kind` = 'binding'
380463 WHERE `kind` = 'secret';--> statement-breakpoint
@@ -393,7 +476,7 @@ INSERT INTO `__openapi_spec_fetch_header_slot_preflight` (`scope_id`, `source_id · 12 unmodified lines
393476 SELECT
394477 r.`scope_id`,
395478 r.`source_id`,
396− 'spec_fetch_header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
479+ 'spec_fetch_header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`
397480 FROM `openapi_source_spec_fetch_header` r
398481 WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL;--> statement-breakpoint
399482
@@ -403,7 +486,7 @@ WITH rows AS ( · 3 unmodified lines
403486 SELECT
404487 r.`scope_id`,
405488 r.`source_id`,
406− 'spec_fetch_header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
489+ 'spec_fetch_header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`,
407490 r.`secret_id`
408491 FROM `openapi_source_spec_fetch_header` r
409492 WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL
@@ -439,7 +522,7 @@ ALTER TABLE `openapi_source_spec_fetch_header` ADD `slot_key` text;--> statement · 29 unmodified lines
439522 ALTER TABLE `openapi_source_spec_fetch_header` ADD `prefix` text;--> statement-breakpoint
440523 UPDATE `openapi_source_spec_fetch_header`
441524 SET
442− `slot_key` = 'spec_fetch_header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
525+ `slot_key` = 'spec_fetch_header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'),
443526 `prefix` = `secret_prefix`,
444527 `kind` = 'binding'
445528 WHERE `kind` = 'secret';--> statement-breakpoint
@@ -458,7 +541,7 @@ INSERT INTO `__openapi_spec_fetch_query_param_slot_preflight` (`scope_id`, `sour · 12 unmodified lines
458541 SELECT
459542 r.`scope_id`,
460543 r.`source_id`,
461− 'spec_fetch_query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
544+ 'spec_fetch_query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`
462545 FROM `openapi_source_spec_fetch_query_param` r
463546 WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL;--> statement-breakpoint
464547
@@ -468,7 +551,7 @@ WITH rows AS ( · 3 unmodified lines
468551 SELECT
469552 r.`scope_id`,
470553 r.`source_id`,
471− 'spec_fetch_query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(r.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
554+ 'spec_fetch_query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = r.`name`), 'default') AS `slot_key`,
472555 r.`secret_id`
473556 FROM `openapi_source_spec_fetch_query_param` r
474557 WHERE r.`kind` = 'secret' AND r.`secret_id` IS NOT NULL
@@ -504,7 +587,7 @@ ALTER TABLE `openapi_source_spec_fetch_query_param` ADD `slot_key` text;--> stat · 29 unmodified lines
504587 ALTER TABLE `openapi_source_spec_fetch_query_param` ADD `prefix` text;--> statement-breakpoint
505588 UPDATE `openapi_source_spec_fetch_query_param`
506589 SET
507− `slot_key` = 'spec_fetch_query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
590+ `slot_key` = 'spec_fetch_query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'),
508591 `prefix` = `secret_prefix`,
509592 `kind` = 'binding'
510593 WHERE `kind` = 'secret';--> statement-breakpoint
@@ -562,7 +645,7 @@ INSERT INTO `__graphql_header_slot_preflight` (`scope_id`, `source_id`, `slot_ke · 51 unmodified lines
562645 SELECT
563646 h.`scope_id`,
564647 h.`source_id`,
565− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
648+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key`
566649 FROM `graphql_source_header` h
567650 WHERE h.`kind` = 'secret'
568651 AND h.`secret_id` IS NOT NULL;--> statement-breakpoint
@@ -574,7 +657,7 @@ WITH header_rows AS ( · 5 unmodified lines
574657 h.`scope_id`,
575658 h.`source_id`,
576659 h.`name`,
577− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
660+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key`,
578661 h.`secret_id`,
579662 h.`secret_prefix`
580663 FROM `graphql_source_header` h
@@ -603,7 +686,7 @@ FROM header_rows r;--> statement-breakpoint · 22 unmodified lines
603686 UPDATE `graphql_source_header`
604687 SET
605688 `kind` = 'binding',
606− `slot_key` = 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
689+ `slot_key` = 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'),
607690 `prefix` = `secret_prefix`,
608691 `text_value` = NULL
609692 WHERE `kind` = 'secret'
@@ -627,7 +710,7 @@ INSERT INTO `__graphql_query_param_slot_preflight` (`scope_id`, `source_id`, `sl · 17 unmodified lines
627710 SELECT
628711 q.`scope_id`,
629712 q.`source_id`,
630− 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
713+ 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key`
631714 FROM `graphql_source_query_param` q
632715 WHERE q.`kind` = 'secret'
633716 AND q.`secret_id` IS NOT NULL;--> statement-breakpoint
@@ -639,7 +722,7 @@ WITH query_param_rows AS ( · 5 unmodified lines
639722 q.`scope_id`,
640723 q.`source_id`,
641724 q.`name`,
642− 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
725+ 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key`,
643726 q.`secret_id`,
644727 q.`secret_prefix`
645728 FROM `graphql_source_query_param` q
@@ -668,7 +751,7 @@ FROM query_param_rows r;--> statement-breakpoint · 22 unmodified lines
668751 UPDATE `graphql_source_query_param`
669752 SET
670753 `kind` = 'binding',
671− `slot_key` = 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
754+ `slot_key` = 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'),
672755 `prefix` = `secret_prefix`,
673756 `text_value` = NULL
674757 WHERE `kind` = 'secret'
@@ -818,7 +901,7 @@ INSERT INTO `__mcp_header_slot_preflight` (`scope_id`, `source_id`, `slot_key`) · 143 unmodified lines
818901 SELECT
819902 h.`scope_id`,
820903 h.`source_id`,
821− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
904+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key`
822905 FROM `mcp_source_header` h
823906 WHERE h.`kind` = 'secret'
824907 AND h.`secret_id` IS NOT NULL;--> statement-breakpoint
@@ -830,7 +913,7 @@ WITH header_rows AS ( · 5 unmodified lines
830913 h.`scope_id`,
831914 h.`source_id`,
832915 h.`name`,
833− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
916+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`name`), 'default') AS `slot_key`,
834917 h.`secret_id`,
835918 h.`secret_prefix`
836919 FROM `mcp_source_header` h
@@ -859,7 +942,7 @@ FROM header_rows r;--> statement-breakpoint · 22 unmodified lines
859942 UPDATE `mcp_source_header`
860943 SET
861944 `kind` = 'binding',
862− `slot_key` = 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
945+ `slot_key` = 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'),
863946 `prefix` = `secret_prefix`,
864947 `text_value` = NULL
865948 WHERE `kind` = 'secret'
@@ -883,7 +966,7 @@ INSERT INTO `__mcp_query_param_slot_preflight` (`scope_id`, `source_id`, `slot_k · 17 unmodified lines
883966 SELECT
884967 q.`scope_id`,
885968 q.`source_id`,
886− 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
969+ 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key`
887970 FROM `mcp_source_query_param` q
888971 WHERE q.`kind` = 'secret'
889972 AND q.`secret_id` IS NOT NULL;--> statement-breakpoint
@@ -895,7 +978,7 @@ WITH query_param_rows AS ( · 5 unmodified lines
895978 q.`scope_id`,
896979 q.`source_id`,
897980 q.`name`,
898− 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(q.`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
981+ 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = q.`name`), 'default') AS `slot_key`,
899982 q.`secret_id`,
900983 q.`secret_prefix`
901984 FROM `mcp_source_query_param` q
@@ -924,7 +1007,7 @@ FROM query_param_rows r;--> statement-breakpoint · 22 unmodified lines
9241007 UPDATE `mcp_source_query_param`
9251008 SET
9261009 `kind` = 'binding',
927− `slot_key` = 'query_param:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(`name`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default'),
1010+ `slot_key` = 'query_param:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = `name`), 'default'),
9281011 `prefix` = `secret_prefix`,
9291012 `text_value` = NULL
9301013 WHERE `kind` = 'secret'
@@ -1038,7 +1121,7 @@ INSERT INTO `__openapi_header_row_slot_preflight` (`scope_id`, `source_id`, `slo · 107 unmodified lines
10381121 SELECT
10391122 s.`scope_id`,
10401123 s.`id`,
1041− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`
1124+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key`
10421125 FROM `openapi_source` s, json_each(s.`headers`) h
10431126 WHERE s.`headers` IS NOT NULL
10441127 AND h.`type` = 'object'
@@ -1052,7 +1135,7 @@ WITH header_rows AS ( · 7 unmodified lines
10521135 s.`scope_id`,
10531136 s.`id` AS `source_id`,
10541137 h.`key` AS `name`,
1055− 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default') AS `slot_key`,
1138+ 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default') AS `slot_key`,
10561139 json_extract(h.`value`, '$.secretId') AS `secret_id`
10571140 FROM `openapi_source` s, json_each(s.`headers`) h
10581141 WHERE s.`headers` IS NOT NULL
@@ -1110,7 +1193,7 @@ SELECT · 51 unmodified lines
11101193 WHEN h.`type` = 'object' AND json_extract(h.`value`, '$.kind') = 'binding'
11111194 THEN json_extract(h.`value`, '$.slot')
11121195 WHEN h.`type` = 'object' AND json_extract(h.`value`, '$.secretId') IS NOT NULL
1113− THEN 'header:' || COALESCE(NULLIF(trim(replace(replace(replace(replace(replace(replace(replace(replace(lower(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(trim(h.`key`), char(9), '-'), char(10), '-'), char(13), '-'), ' ', '-'), '_', '-'), '.', '-'), ':', '-'), '/', '-'), '@', '-'), '+', '-'), '&', '-'), '?', '-'), '#', '-'), '%', '-'), '$', '-'), ',', '-'), ';', '-'), '(', '-'), ')', '-'), '[', '-'), ']', '-'), '{', '-'), '}', '-'), '=', '-'), '~', '-'), '!', '-'), char(34), '-'), char(39), '-'), char(92), '-'), '|', '-'), '*', '-'), '<', '-'), '>', '-')), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '--', '-'), '-'), ''), 'default')
1196+ THEN 'header:' || COALESCE((SELECT `slug` FROM `__slug_norm` WHERE `raw` = h.`key`), 'default')
11141197 ELSE NULL
11151198 END,
11161199 CASE
@@ -1132,3 +1215,6 @@ WHERE s.`headers` IS NOT NULL · 15 unmodified lines
11321215 );--> statement-breakpoint
11331216
11341217 ALTER TABLE `openapi_source` DROP COLUMN `headers`;
1218+
1219+--> statement-breakpoint
1220+DROP TABLE `__slug_norm`;
apps/local/src/server/migration-nesting.test.ts+108−0
@@ -0,0 +1,108 @@
1+// Lint: reject migration SQL that nests a single function call too deeply.
2+//
3+// bun:sqlite's lemon parser stack overflows at PREPARE time when an
4+// expression nests too deep, and the limit is platform-dependent — the
5+// macOS-built compiled CLI binary trips around ~40 levels while Linux can
6+// go further. Our test matrix only runs on Linux today, so a regression
7+// won't surface in CI; this lint catches the class of bug structurally
8+// instead. Cap is 20 (well above any legitimate nested-function call we
9+// have today, well below the macOS bun:sqlite parser limit).
10+import { describe, expect, it } from "@effect/vitest";
11+import { readdirSync, readFileSync } from "node:fs";
12+import { join } from "node:path";
13+
14+const MIGRATIONS_FOLDER = join(import.meta.dirname, "../../drizzle");
15+const MAX_NESTING = 20;
16+
17+// Walk the SQL char-by-char tracking the call-stack of nested function
18+// names. A "function call" is any IDENT immediately followed by `(`.
19+// Returns { fn, depth } for the deepest single-name nest found, or null.
20+const findDeepestNest = (sql: string) => {
21+ const stack: string[] = [];
22+ let worst: { fn: string; depth: number; offset: number } | null = null;
23+ let i = 0;
24+ while (i < sql.length) {
25+ const ch = sql[i];
26+ // Skip line comments
27+ if (ch === "-" && sql[i + 1] === "-") {
28+ const eol = sql.indexOf("\n", i);
29+ i = eol < 0 ? sql.length : eol + 1;
30+ continue;
31+ }
32+ // Skip string literals (single- and double-quoted, backtick identifiers)
33+ if (ch === "'" || ch === '"' || ch === "`") {
34+ const quote = ch;
35+ i++;
36+ while (i < sql.length) {
37+ if (sql[i] === quote) {
38+ if (sql[i + 1] === quote) {
39+ i += 2;
40+ continue;
41+ }
42+ i++;
43+ break;
44+ }
45+ i++;
46+ }
47+ continue;
48+ }
49+ if (ch === "(") {
50+ // Walk back to find an IDENT immediately preceding this paren
51+ let j = i - 1;
52+ while (j >= 0 && /\s/u.test(sql[j])) j--;
53+ let end = j;
54+ while (j >= 0 && /[A-Za-z0-9_]/u.test(sql[j])) j--;
55+ const name = sql.slice(j + 1, end + 1).toLowerCase();
56+ stack.push(name || "(");
57+ // Count consecutive same-name frames in the stack
58+ let same = 0;
59+ for (let k = stack.length - 1; k >= 0; k--) {
60+ if (stack[k] === stack[stack.length - 1]) same++;
61+ else break;
62+ }
63+ if (name && (worst === null || same > worst.depth)) {
64+ worst = { fn: name, depth: same, offset: i };
65+ }
66+ i++;
67+ continue;
68+ }
69+ if (ch === ")") {
70+ stack.pop();
71+ i++;
72+ continue;
73+ }
74+ i++;
75+ }
76+ return worst;
77+};
78+
79+describe("drizzle migration SQL structural lint", () => {
80+ const files = readdirSync(MIGRATIONS_FOLDER)
81+ .filter((f) => f.endsWith(".sql"))
82+ .sort();
83+
84+ for (const f of files) {
85+ it(`${f} keeps nested-function depth under ${MAX_NESTING}`, () => {
86+ const sql = readFileSync(join(MIGRATIONS_FOLDER, f), "utf-8");
87+ const worst = findDeepestNest(sql);
88+ const summary =
89+ worst === null
90+ ? { ok: true as const }
91+ : {
92+ ok: worst.depth < MAX_NESTING,
93+ file: f,
94+ line: sql.slice(0, worst.offset).split("\n").length,
95+ fn: worst.fn,
96+ depth: worst.depth,
97+ };
98+ // The expectation is `summary.ok === true`. The full `summary` object is
99+ // matched (not just `.ok`) so the failure diff prints file/line/fn/depth
100+ // — bun:sqlite's lemon parser stack overflows on the compiled macOS CLI
101+ // binary around depth 40, and the project's test matrix is Linux-only,
102+ // so the diff is the breadcrumb that tells you which migration to
103+ // refactor (precompute into a temp table à la 0008's __slug_norm, or
104+ // split the expression into multiple shallow steps).
105+ expect(summary).toEqual({ ...summary, ok: true });
106+ });
107+ }
108+});