Putting the feedback board on feedback.hallpass.cc
Superseded 2026-09-10. Public feedback moved to Canny: https://hallpass.canny.io/field-reports (board
field-reports, categories Bug / Balance & Difficulty / Controls & Feel / Art, Sound & Music / Ideas & Features / Store, Ads & Purchases; free tier, default statuses)._redirectssends /feedback and /feedback.html there with302!. The static render below still builds but is unreachable; remove the publish-board step from build.mjs when convenient, and point the in-game FIELD REPORT form at the Canny API (or keep Netlify Forms and import by hand).
Putting the feedback board on feedback.hallpass.cc
The board runs today as a Node server with SQLite on Chris's machine. Going
public is not a DNS change — it is a hosting change, because
hallpass.cc is static on Netlify and this thing needs a running process
and a database that survives restarts.
Nothing here is done yet. This is the decision written down, so the choice is made once with the tradeoffs visible rather than improvised at deploy time.
What must be true before it is public
The current server is explicitly not safe to expose. From its own header:
- No authentication on writes.
OWNER_KEYis a shared secret in a query string. It hides the approve and move-queue buttons; it does not defend them. Anyone who sees the URL has it, and it lands in browser history, referrer headers and server logs. - No rate limiting, no spam filtering, no captcha. A public unauthenticated POST endpoint on a game's domain gets found.
- Votes are unauthenticated and repeatable. Vote counts order the loops' queue, so a trivially stuffed ballot steers what the robots work on.
- No moderation. Text goes straight onto a page. It is escaped, so this is not an XSS risk, but it is an abuse risk.
The approval gate limits the blast radius nicely: an unapproved item is inert, so the worst a spammer achieves is noise on a page. That is the reason this can ship without solving every problem above — but rate limiting and real owner auth are not optional.
Option A — Netlify Functions + hosted Postgres (recommended)
Keeps everything on the existing Netlify site and DNS.
- The board becomes a serverless function; the page can stay server-rendered.
- SQLite does not survive on serverless (no persistent disk), so the database moves to hosted Postgres. Supabase or Neon both have a free tier that comfortably fits this.
- Owner auth becomes Netlify Identity, or a signed cookie — not a query string.
- Rate limit by IP in the function; add a honeypot field.
Cost: a rewrite of feedback-db.mjs onto pg, and of the server onto the
Functions handler signature. The schema, the queue model and the page markup
all carry over unchanged. Half a day.
DNS: add feedback as a Netlify domain alias, same as www. Set
custom_domain first, then the alias — adding an alias for a domain family
that is not yet the site's custom domain returns 422. That gotcha already bit
this project once when hallpass.cc was set up.
Option B — a small always-on host
Fly.io, Railway, or a VPS. Keeps SQLite and the current code almost as-is; point a CNAME at the host.
Cheaper in effort, more in attention: it is a server to patch, back up and monitor, for a page that gets a handful of posts a day.
Option C — stay local, publish read-only (cheapest useful step)
Keep writes local. Export the board to a static page on every sweep and publish
it to hallpass.cc/feedback.html, so the community can read the queues, the
verdicts and the tuning log. Collect submissions through the existing Netlify
Forms setup — already wired for field reports, already spam-filtered by
Netlify — and import them into the database.
This gets the public-facing value with none of the security work, and it composes with Option A later.
Recommendation
C now, A when the community is real. The board's value today is Chris's own queue plus a visible record; a public write path is a liability until there are people to write. Option C also proves the page design in front of real readers before any of it is load-bearing.
Regardless of option
- Keep
feedback.dbout of git.playtest/feedback-export.jsonis the tracked snapshot and is what a static publish should render from. - The approval gate stays. It is what makes community input safe: unapproved items are visible but inert, and no loop spends a single run on one.