-
Notifications
You must be signed in to change notification settings - Fork 828
refactor(config): extract provider-name leaf; break config<->profile cycle #2036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,62 @@ | ||||||||||||||||||||||||||||||||
| # WP2a-1 — config provider-name leaf (cycle breaker; parallel PR off dev) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Branch codex/split-wp2a-config-names on dev@aaf04690e. NOT stacked on the | ||||||||||||||||||||||||||||||||
| types stack (disjoint files, DEV-STACK-01 'independent parts -> parallel PRs'). | ||||||||||||||||||||||||||||||||
| Class C2 pure move + 2 consumer retargets. Risk basis 000_risk_assessment.md | ||||||||||||||||||||||||||||||||
| WP2a; highest-leverage low-risk config extraction: breaks the existing | ||||||||||||||||||||||||||||||||
| config <-> routing/profile import cycle. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Loop spec | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - Goal: isValidProviderName/hasOwnProvider live in a leaf with no heavy deps; | ||||||||||||||||||||||||||||||||
| routing/profile.ts and router.ts stop importing them through the 3900-line | ||||||||||||||||||||||||||||||||
| config barrel (which loads Zod + bun:sqlite + registry transitively). | ||||||||||||||||||||||||||||||||
| - Non-goals: no other config extraction this PR; management write-path | ||||||||||||||||||||||||||||||||
| callers keep importing from ./config (barrel re-export). | ||||||||||||||||||||||||||||||||
| - Verifier: typecheck + lidge full suite + core-lab-boundary. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## File change map | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - ADD src/config/provider-name.ts: RESERVED_PROVIDER_NAMES, | ||||||||||||||||||||||||||||||||
| PROVIDER_NAME_PATTERN (both module-private consts, config.ts 738-750), | ||||||||||||||||||||||||||||||||
| isValidProviderName (762), hasOwnProvider (769). Zero imports. | ||||||||||||||||||||||||||||||||
| - EDIT src/config.ts: delete moved bodies; add | ||||||||||||||||||||||||||||||||
| `export { isValidProviderName, hasOwnProvider } from "./config/provider-name"`; | ||||||||||||||||||||||||||||||||
| internal call sites (1150, 1390, 1597 + others) need a local | ||||||||||||||||||||||||||||||||
| `import { ... } from "./config/provider-name"` since re-export binds nothing | ||||||||||||||||||||||||||||||||
| (WP1 lesson). | ||||||||||||||||||||||||||||||||
| - EDIT src/routing/profile.ts:16: import hasOwnProvider from | ||||||||||||||||||||||||||||||||
| ../config/provider-name (cycle edge profile->config removed). | ||||||||||||||||||||||||||||||||
| - EDIT src/router.ts:11: split import — hasOwnProvider from | ||||||||||||||||||||||||||||||||
| ./config/provider-name, resolveEnvValue stays from ./config. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Accept criteria | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| 1. typecheck exit 0. 2. lidge full suite 0 fail (baseline 13201 pass). | ||||||||||||||||||||||||||||||||
| 3. core-lab-boundary green (router edge now reaches a leaf with no imports — | ||||||||||||||||||||||||||||||||
| protected graph shrinks). | ||||||||||||||||||||||||||||||||
| 4. rg 'from "../config"' src/routing/profile.ts -> no hasOwnProvider import | ||||||||||||||||||||||||||||||||
| through the barrel (cycle gone; remaining profile imports from config: none | ||||||||||||||||||||||||||||||||
| expected — verify, else keep others intact). | ||||||||||||||||||||||||||||||||
| 5. Source diff: exactly 4 files under src/. | ||||||||||||||||||||||||||||||||
|
Comment on lines
+35
to
+41
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Split the first two acceptance criteria into separate list items. Line 35 contains Proposed fix-1. typecheck exit 0. 2. lidge full suite 0 fail (baseline 13201 pass).
-3. core-lab-boundary green (router edge now reaches a leaf with no imports —
+1. typecheck exit 0.
+2. lidge full suite 0 fail (baseline 13201 pass).
+3. core-lab-boundary green (router edge now reaches a leaf with no imports —📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.23.2)[warning] 36-36: Ordered list item prefix (MD029, ol-prefix) [warning] 38-38: Ordered list item prefix (MD029, ol-prefix) [warning] 41-41: Ordered list item prefix (MD029, ol-prefix) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Risks | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - config.ts superRefine calls isValidProviderName internally — the local | ||||||||||||||||||||||||||||||||
| import must land before schema evaluation (top of file, hoisted; ESM fine). | ||||||||||||||||||||||||||||||||
| - routing/profile.ts may import more than hasOwnProvider from ../config — | ||||||||||||||||||||||||||||||||
| verify and leave other names on the barrel. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Audit amendments (grok PASS / sol NEAR-PASS) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - Internal call sites are EXACTLY 3 (1150, 1390 isValidProviderName; 1597 | ||||||||||||||||||||||||||||||||
| hasOwnProvider), all inside superRefine callbacks — no TDZ risk. | ||||||||||||||||||||||||||||||||
| - AC3 claim corrected: the protected graph does NOT shrink (router keeps the | ||||||||||||||||||||||||||||||||
| barrel edge for resolveEnvValue; the leaf adds one dead-end module). The | ||||||||||||||||||||||||||||||||
| real win is the config<->profile cycle break. core-lab-boundary stays | ||||||||||||||||||||||||||||||||
| green either way. | ||||||||||||||||||||||||||||||||
| - profile.ts imports nothing else from ../config — cycle fully gone. | ||||||||||||||||||||||||||||||||
| - Tests importing isValidProviderName via barrel: config.test.ts:13, | ||||||||||||||||||||||||||||||||
| policy-execution.test.ts:6 — barrel re-export preserves both. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| const RESERVED_PROVIDER_NAMES = new Set([ | ||
| // JavaScript prototype-pollution guards. | ||
| "__proto__", | ||
| "prototype", | ||
| "constructor", | ||
| // System-reserved routing namespace (resolved before provider/account | ||
| // namespaces in routeModelInternal). "combo" is intentionally NOT reserved: | ||
| // a physical provider named `combo` is a supported pattern (combo aliases | ||
| // hosted on the combo provider), and the combo selector only wins when an | ||
| // actual combo id matches. | ||
| "policy", | ||
| ]); | ||
| const PROVIDER_NAME_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,62}[A-Za-z0-9])?$/; | ||
|
|
||
| export function isValidProviderName(name: string): boolean { | ||
| const trimmed = name.trim(); | ||
| return trimmed === name | ||
| && PROVIDER_NAME_PATTERN.test(name) | ||
| && !RESERVED_PROVIDER_NAMES.has(name.toLowerCase()); | ||
| } | ||
|
|
||
| export function hasOwnProvider(providers: Record<string, unknown>, name: string): boolean { | ||
| return Object.prototype.hasOwnProperty.call(providers, name); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove the stale protected-graph claim.
Lines 36-37 say that the protected graph shrinks. Lines 55-57 correctly state that it does not shrink because
src/router.tsstill importsresolveEnvValuefromsrc/config.ts. Replace this text with the actual acceptance condition: verify that theconfig–routing/profilecycle is removed.🧰 Tools
🪛 markdownlint-cli2 (0.23.2)
[warning] 36-36: Ordered list item prefix
Expected: 2; Actual: 3; Style: 1/2/3
(MD029, ol-prefix)
🤖 Prompt for AI Agents