CodeVetter · Repo Unpack · Risk map
Chalarangelo/30-seconds-of-code
Top risks: production code imports test factories (spec/ is on the live path of bin/console and any Loader user); the model layer is global mutable state; the markdown pipeline passes through raw HTML (allowDangerousHtml) so content is trusted input; watch mode has no debounce; omnisearch injects index data into innerHTML; and several identifiers are derived by brittle string slicing/naming conventions. Deploy security hinges on a single secret webhook URL, and CI is thin (tests only, old action versions, no build check).
- src/lib/loader.js imports '#spec/factories/factories.js' — test-only factory code is imported by a production module, coupling any Loader user (bin/prepare, bin/console) to the spec tree.
- Model state is process-global and append-only: Model.instances accumulates every constructed instance with no reset API, so double importData calls or tests that create factories leak records into all/where/scope results for the process lifetime.
- The markdown pipeline runs remark-rehype and rehype-stringify with allowDangerousHtml:true — raw HTML embedded in snippet markdown passes through unescaped into shipped pages; safe only because all content is author-trusted.
- omnisearch renders result rows via innerHTML template literals interpolating result.url, result.title, result.tag without escaping (createResultHTML), while only the not-found path escapes the query — a crafted search-data.json title could inject markup, though the index is build-generated.
- Watch mode exec()s a full 'bin/prepare dev' on every fs.watch event with no debounce or in-flight guard — rapid saves can spawn overlapping full re-extractions (Shiki highlighting is the expensive step).
- Snippet id derivation is positional: filePath.replace(snippetPrefix,'').slice(0,-3) assumes the 'content/snippets/…/*.md' shape; a stray file matched by the glob with a different extension would silently corrupt the id.
- A missing/typo'd front-matter 'language' degrades silently: languageData.get(languageKey) returns undefined and every downstream use is optional-chained, so recTokens/docTokens lose language terms and the snippet renders without a language rather than failing.
- Naming-convention coupling is load-bearing: Page.from resolves `${object.constructor.name}Page`, serializeAs resolves `${name}Serializer`, and the JSON reviver resolves models[value.model] — renaming a class or key breaks page generation, and the 'serializer not found' guard in serializeAs is dead code because `new undefined()` throws TypeError first.
- Publishing correctness depends on wall-clock time: dateModified compared to new Date() decides scheduled vs published, so the daily 18:20 UTC deploy cron determines when scheduled articles go live — a missed/failed deploy silently delays publication. (inferred)
- Astro routes hard-fail without generated content: getStaticPaths does fs.readFile on .content JSONs with no fallback, so 'astro dev'/'astro build' without the prepare step (or a cleaned .content dir) crashes — the coupling is enforced only by npm pre-hooks, which bare 'astro' or 'vitest' invocations bypass.
- Known-fragile code is flagged in TODO comments: Snippet.hasCollection returns true even when the only membership is the main collection, and Collection.matchesTag relies on id.endsWith(`/${tag}`).
- CI uses dated action versions (actions/checkout@v1 in deploy-production, actions/setup-node@v1 in test) and the deploy job's only secret is CF_BUILD_HOOK_URL — a leaked or misconfigured hook URL is the entire deployment control surface.
- Shiki vs Prism output differs subtly: Prism mode appends a '<script type=module …/prism-code-highlights.mjs>' tag into parsed HTML, meaning dev-mode rendered markup is not identical to production markup.