SPB Git

spb/autoscholar

Public
4.1 KB

# UI notes — needs outside the UI scope (for the control-plane owner)

getPaperBySlug builds sql\${paperVersions.keywords} && ${row.v.keywords}`. Drizzle expands the JS array as a tuple (&& ($4,$5,$6)), so PostgreSQL rejects the query and **every paper page returns 500/404** (/research/[slug]and/api/public/papers/[slug]). Verified fix (one line, import arrayOverlapsfromdrizzle-orm`):

ts
or(eq(papers.discipline, row.p.discipline), arrayOverlaps(paperVersions.keywords, row.v.keywords));

The e2e suite was run with this fix applied temporarily (25/25 pass); the original file was restored afterwards and packages/core rebuilt from it, so the paper page is broken again until the fix lands.

# Tooling

  • biome.json: add "css": { "parser": { "tailwindDirectives": true } } so apps/web/src/app/globals.css (@import "tailwindcss", @theme, @apply, @custom-variant) parses; today pnpm lint reports parse errors there. Also biome migrate (schema 2.4.0 vs CLI 2.6.4; recommended deprecated).
  • pnpm 11 "deps status check" aborted pnpm start / pnpm exec playwright after dependencies changed (ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY → it tried pnpm install --production). Workaround used: run binaries directly (apps/web/node_modules/.bin/next, node_modules/.bin/playwright). Consider verify-deps-before-run=false in .npmrc for non-interactive hosts (pm2).
  • next start warns that output: "standalone" expects node .next/standalone/server.js (copy .next/static and public into the standalone dir on deploy). It still serves correctly; the pm2 manifest should pick one of the two.
  • Rebuilding .next while a next start process is still serving leaves it with a stale client manifest ("Could not find the module …link.js in the React Client Manifest" → 500 on every page with next/link). Always stop the server before next build (or build to a fresh dir and swap).
  • packages/db/package.json: added pdf-lib (used only by src/seed.ts to generate the staging PDF).

# Server helpers / API observations (not changed)

  • clientIp() returns null when TRUST_PROXY=0 and no proxy header is present (Next does not expose the socket address), so locally all visitors share the limiter keys "unknown"/"public", and for /api/internal/* the CIDR allow-list is skipped (only the bearer token protects it). In production the worker reaches the control plane directly on the LAN (no proxy headers) → same situation. If a LAN-only guard is wanted, bind the internal API to a separate port/listener or set the socket address via a custom server.
  • Internal worker routes answer 403 (viaPublicProxy) to Playwright's request context because it sends x-forwarded-*-free requests… actually they return 403 for any request whose headers include forwarded hints; the e2e asserts 401 or 403 for those routes.
  • The in-memory login limiter (10 logins / 15 min per username) is easy to hit while developing/testing; the e2e suite reuses one signed-in storage state to stay below it. A restart of the web process resets it.
  • listEvents() returns Date objects; redact() turns a Date into {} (it walks it as a plain object). The run page converts dates before redacting; the /api/admin/runs/[id]/events route passes rows straight through redact() → at becomes {} in the JSON. Suggest redact() to pass Date/Buffer instances through unchanged, or serialise before redacting in that route.
  • Public artifact route sets accept-ranges: none; the browser PDF viewer works but cannot seek by byte range on large PDFs.

# Seed

pnpm db:seed → seedTopicsAndSeries() always (17 disciplines + 10 subfields + series as-wp), seedStagingPaper() only with STAGING_MODE=1 (one synthetic paper AS-WP-2026-0000, papers.synthetic=true, 6-page PDF written under ARTIFACT_ROOT/public/AS-WP-2026-0000/v1/manuscript/main.pdf with a .sha256 sidecar). Production (STAGING_MODE=0) never lists, serves or indexes it. Remove it before launch with delete from papers where public_id='AS-WP-2026-0000' (cascades) + delete the public object.

Files · 87b4e55c3b9fbcc2cd191a1e469b33de0a24ccc8
Menu

Theme