← all branches

feat/atlas-scan

needs attentionviewing older commit
3af4686 · incrementalpre-PRreviewed 2026-08-03 20:07 UTC3H · 5M · 5L · 4I
The branch
Purpose
Build and serve the Batu private atlas (Power Finder siting suite) behind platform authentication — spatial layers for gas, substations, industrial parks, and short-circuit data accessible only to logged-in users
Goal
Private atlas with full layer set at /atlas, gated by the platform session, served via a route handler in /api/atlas
Sub-goals
  • Move atlas handler from /atlas to /api/atlas (Vercel routing fix)
  • Use 307 redirect from proxy instead of edge rewrite
  • Extract serveAtlas utility shared by root + catch-all routes
  • Update outputFileTracingIncludes and tests for new paths
The changes (whole branch)
What
Route handlers moved from /atlas to /api/atlas; proxy now issues a 307 redirect for authenticated requests instead of passing through; serveAtlas extracted to lib/atlas/serve.ts; next.config.ts tracing keys updated; tests updated for new paths
Why
Top-level /atlas routes conflicted with Next.js [locale] routing tree and edge rewrites didn't apply in Vercel; /api namespace routes reliably (proven pattern: /api/v1/openapi.json)
Areas
apps/platform/src/lib/atlas/serve.ts+890apps/platform/src/app/api/atlas/+180apps/platform/src/lib/supabase/proxy.ts+151apps/platform/src/lib/supabase/__tests__/atlas-route-gate.test.ts+1250apps/platform/next.config.ts+150
Blast
6 files, +262/-1 in this increment; no domain logic, no data model, no API contract changes — atlas serving path only
security-critical-guard-untested potential-asset-404-on-atlas-root
ci· no PR — CI status not availablecoderabbit· no .coderabbit.yaml

Findings · 16

correctness3

high

Proxy redirect /atlas → /api/atlas omits trailing slash — may break relative URL resolution before <base> is parsed

apps/platform/src/lib/supabase/proxy.ts:183

pathname.slice('/atlas'.length) is '' for root /atlas, so redirect lands on /api/atlas (no slash). The injected <base href> is /api/atlas/ (with slash). Relative asset fetches that fire before the <base> tag is parsed resolve against /api/atlas → /api/<asset>. Fix: redirect /atlas → /api/atlas/ (add trailing slash).

medium

base href injection via string.replace fragile for malformed HTML (<!-- <head> --> before real head)

apps/platform/src/lib/atlas/serve.ts:38

If <head> appears in a comment before the real <head> element, the base tag injects into the comment and the real head gets no base href. Low probability on a controlled artifact.

low

MIME allowlist missing .js and .css — atlas script/style assets will 404

apps/platform/src/lib/atlas/serve.ts:9

Only .html .json .geojson .csv .png .svg allowed. Any SPA .js or .css asset will be extension-blocked. Verify atlas bundle extensions and extend TYPES.

security4

medium

Symlink inside atlas-private/ bypasses path-traversal guard

apps/platform/src/lib/atlas/serve.ts:40

fs.readFile follows symlinks. A symlink atlas-private/escape -> /etc/passwd passes the startsWith(BASE+sep) check. Fix: fs.realpath(abs) and re-check against fs.realpath(BASE).

low

SVG served same-origin can execute inline scripts

apps/platform/src/lib/atlas/serve.ts:26

SVG files loaded directly (not via <img>) execute scripts in the platform origin. Add Content-Security-Policy: script-src 'none' on SVG responses.

low

No explicit null-byte guard in path segments

apps/platform/src/lib/atlas/serve.ts:37

Node ≥ v7 throws on null bytes, but defense-in-depth: add segs.some(s => s.includes('\0')) guard.

info

Missing X-Content-Type-Options: nosniff

apps/platform/src/lib/atlas/serve.ts:56

Standard hardening for authenticated file-serving endpoints.

conventions2

low

JSDoc (/** */) style used for non-public-API function

apps/platform/src/lib/atlas/serve.ts:6

WHY content is correct per policy; use plain /* */ instead of JSDoc.

info

outputFileTracingIncludes second entry targets wrong source path

apps/platform/next.config.ts:18

'/api/atlas/**': ['./api/atlas/**'] should be './atlas-private/**/*'. Route handler source is bundled by Next.js — only atlas-private/ runtime files need explicit tracing. No-op but misleads editors.

tests5

high

Path-traversal guard has zero test coverage

apps/platform/src/lib/supabase/__tests__/atlas-route-gate.test.ts

Security-critical guard with no tests. Add cases for ../../../etc/passwd, ..%2F encoding, and null-byte, all asserting 404.

high

Extension allowlist has zero test coverage

apps/platform/src/lib/supabase/__tests__/atlas-route-gate.test.ts

No test asserting .env or .ts requests are rejected. Accidental allowlist removal would go undetected.

medium

Sub-path redirect not tested (/atlas/layer/data.json → /api/atlas/layer/data.json)

apps/platform/src/lib/supabase/__tests__/atlas-route-gate.test.ts

Only root /atlas path tested. Deep path redirect correctness is untested.

medium

404 for non-existent file not tested

apps/platform/src/lib/supabase/__tests__/atlas-route-gate.test.ts

A broken catch/ENOENT branch returning 500 instead of 404 would go undetected.

medium

Trailing-slash / empty-segments edge case not tested (/api/atlas/)

apps/platform/src/lib/supabase/__tests__/atlas-route-gate.test.ts

Verify segs derived from a trailing slash still resolve to index.html.

improvement2

low

Redundant Buffer→Uint8Array conversion

apps/platform/src/lib/atlas/serve.ts:47

Node Buffer IS a Uint8Array subclass — pass buf directly to NextResponse; the wrapping copy is unnecessary.

info

Likely redundant outputFileTracingIncludes glob pair

apps/platform/next.config.ts

Once the second entry is corrected to ./atlas-private/**/*, verify whether both /api/atlas and /api/atlas/** are needed or one covers both.

History · 16 commits

  1. 91aaedfsafeincremental0H · 1M · 1L2026-08-12 17:35
  2. cb8d915needs attentionincremental2H · 5M · 3L2026-08-12 17:29
  3. 4cbbe8aneeds attentionincremental0H · 3M · 8L2026-08-12 14:01
  4. 4aa3c02needs attentionincremental2H · 3M · 3L2026-08-12 02:35
  5. f5630b2needs attentionincremental0H · 4M · 5L2026-08-12 02:17
  6. 28fde5bneeds attentionincremental1H · 2M · 2L2026-08-12 01:53
  7. 0babe51needs attentionincremental1H · 2M · 5L2026-08-12 01:23
  8. 50e8a8cneeds attentionincremental3H · 5M · 7L2026-08-11 23:58
  9. 3af4686needs attentionincremental3H · 5M · 5L2026-08-03 20:07current
  10. f5d3266needs attentionincremental0H · 3M · 8L2026-08-03 19:40
  11. 9f8b61aneeds attentionincremental0H · 2M · 3L2026-08-03 19:15
  12. ea51fa0needs attentionincremental1H · 4M · 4L2026-08-03 19:02
  13. 2b33f2fneeds attentionincremental0H · 1M · 1L2026-07-18 05:09
  14. 2f8cf79needs attentionincremental1H · 3M · 4L2026-07-18 00:59
  15. 1616332safeincremental0H · 0M · 1L2026-07-18 00:22
  16. e997fd8needs attentionfull1H · 4M · 6L2026-07-17 23:53