doxa-maps/internal/check-no-repo-pb-hooks.mjs
Doxa Maps 7dc634275e Put the cloud Dockerfile at the repo root, so a platform pointed at the repo finds it
Railway, DigitalOcean and `docker build` use a root Dockerfile with no setting, and it is
Coolify's and Dokploy's default path. The file moves; nothing is copied.

- VOLUME /data is gone. Railway rejects the line, and a named volume is needed anyway
  (VOLUME alone gives each new container a fresh anonymous one). The platforms mount /data.
- The baked PocketBase gate's comment named the old path. It now says the repo-root
  Dockerfile, and the gate's SHA-256 pin moves with it (2987055b... -> 2eceef03...). The
  hook's code is unchanged: the exact RUN passes `sha256sum -c`, and the old block still
  passes its old pin.
- .dockerignore excludes everything: the Dockerfile copies nothing from the build context,
  so no platform sends the whole repository to the builder.
- compose.yaml: the same image with its /data volume and memory limit; settings from .env.
- deployment/cloud/README.md gains "Where it runs": Coolify, Dokploy, Railway, a server with
  Docker, Kubernetes, and why not DigitalOcean App Platform (no persistent volumes).
  DEPLOY.md and two comments follow the move.
2026-09-29 02:35:36 +00:00

32 lines
1.8 KiB
JavaScript

#!/usr/bin/env node
/**
* check-no-repo-pb-hooks.mjs — no PocketBase hooks (pb_hooks, *.pb.js) may live in the repo.
*
* WHY: the cloud container pulls this repo every few seconds. A PocketBase hook is server-side JS; one pushed
* by any plugin writer would run on the team backend within seconds, which is the rogue-writer hole the
* roundtable test closed. The container never points PocketBase at the repo (--hooksDir is outside the
* pulled tree; the one team sign-in hook is baked into the image and pinned, in the repo-root Dockerfile).
* This gate keeps anyone from adding a hooks folder that LOOKS like it would run, or that a later recipe
* change could start running.
*
* HOW: every tracked path; a self-test on every run (a poisoned list must fail), so the gate cannot go blind.
*/
import { execFileSync } from 'node:child_process'
import { join, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
const ROOT = process.env.DOXA_REPO || join(dirname(fileURLToPath(import.meta.url)), '..')
export const offending = (paths) => paths.filter((p) => /(^|\/)pb_hooks(\/|$)/.test(p) || /\.pb\.(js|ts)$/.test(p))
if (offending(['README.md', 'backend/pocketbase/pb_hooks/x.pb.js', 'a/b.pb.ts']).length !== 2) {
console.error('✗ check:no-repo-pb-hooks self-test failed: the matcher went blind'); process.exit(1)
}
const tracked = execFileSync('git', ['ls-files', '-z'], { cwd: ROOT }).toString().split('\0').filter(Boolean)
const bad = offending(tracked)
if (bad.length) {
console.error(`✗ PocketBase hooks in the repo (server-side JS must never ride the live pull):\n${bad.map((p) => ' ' + p).join('\n')}`)
console.error(' The team sign-in hook is baked into the image (the repo-root Dockerfile); anything else needs a design review.')
process.exit(1)
}
console.log(`✓ no PocketBase hooks among ${tracked.length} tracked files`)