Skip to content

Deploy artifact and Turso operational hardening #117

Description

@alchemydc

Deferred from the PR #99 review. The Docker/compose artifact shipped in that release works, but is not production-shaped, and the Turso migration path lacks a written recovery procedure.

Container

  • Runs as root. Dockerfile has no USER node, and ships the full workspace including dev dependencies and the build toolchain.

compose

  • No TLS while cookies are secure: isProd. compose.yaml binds 3000:3000 over plain HTTP. A production-mode container therefore silently fails to set the session cookie, and login just appears to do nothing. The env example doesn't mention that a TLS terminator is required.
  • First boot lands on a site that redirects every page. SESSION_SECRET= ships blank and the only seeded league is required-gate. The env comment says it "500s without it"; checkLeagueAccess actually returns "redirect". Seeding a --gate optional starter league would make docker compose up work out of the box.
  • Two writers, one SQLite file, no coordination. web and the ingest sidecar share the DB over a volume, with || true swallowing failures, and apps/web/src/lib/prisma.ts configures no WAL mode or busy_timeout. A SQLITE_BUSY would be silent and simply retried 30 minutes later.

Long-running request handler

POST /api/admin/leagues/[slug]/ingest-now runs the whole scrape synchronously in a request handler: N × 1.5 s polite delay + download + pdftotext. With no proxy in front that's fine; behind anything else it hits a gateway timeout while the run continues in the background.

The mutex does release correctly in finally, so there is no lock leak — but this wants to be a background job with a status endpoint.

Turso migration recovery procedure (docs)

Dropping the wrapping transaction in migrate-turso.ts was the right call (see #93 — PRAGMA foreign_keys is a no-op inside a transaction), and PR #99 added structural enforcement of that invariant. The trade-off is that there is no local rollback: a failure part-way through a multi-statement migration leaves the DB in an intermediate state.

docs/ should carry the recovery procedure — how to establish a PITR restore point before migrating, and how to determine which statement actually landed — rather than leaving it to be worked out mid-incident.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions