docs: adopt project template, retire the markdown backlog
This repository is the one the template's README describes: 205 issues, zero
milestones, and severity labels spelled "P0 Critical" / "P1 High" / "P2 Medium",
which privacyllc.dev reports as NOT ADOPTED rather than as 87% complete.
Six markdown records described the same work and none pointed at the tracker.
Two of them said the project was in "Phase 5" while the code was at 0.9.3.
Migrated, then deleted in this commit:
FUTURE.md -> docs/history/BATCH_LEDGER.md (Archived). Its open
items were all already filed as issues, so nothing
needed migrating into the tracker
HISTORY.md -> docs/history/DEVELOPMENT_LOG.md, verbatim, 0 lines lost
DEVELOPMENT_LOG.md -> the same file, as a second labelled block. Not
interleaved: the changelog has three duplicated version
headings, so one date order would have implied more
than the record supports
PROJECT.md -> docs/planning/PROJECT_PLAN.md
STRUCTURE.md -> the agent pipeline into README.md; its versioning rules
retired
BUILD_SUMMARY.md -> BATCH_LEDGER.md. Its embedded SQL schema deliberately
NOT carried: it predated the UNIQUE constraint on
leads.email, and server/index.js owns the schema
SCRIPTS.md -> docs/TOOLS.md, corrected for the SSR + prerender build
Moved with history (git detects all four as renames):
OVERHAUL_PLAN.md, review.md, project-requirements.md, docs/zoho-setup.md
Kept because this project earned them: the five-agent pipeline, the design
system in OVERHAUL_PLAN.md (Status: Current, with a front-note saying which half
is history), the positioning argument in REDESIGN_REVIEW.md, and REQUIREMENTS.md
whole, including its change policy.
Deleted from the template because they do not apply, each said out loud in
DOC_TRUST_MAP.md: QA pass I (no money moves), the authorisation checklist group
and the session-token row (no accounts, no sessions), and one PRECAUTIONARY
paragraph in SECURITY.md about holding credentials on behalf of users — there
are none, and PROJECT_PLAN.md records accounts as out of scope. Pass H was kept
and rewritten: its authorisation half does not apply, its what-a-stranger-can-
reach half is the most exposed surface here.
Also removed: main.js, the old static site's hash router, referenced by nothing
and preserved in .drop/; and test-results/.last-run.json, a May Playwright
artifact reading {"status":"failed"} for a suite that does not exist.
The repository was made private on Forgejo before this commit. That is what let
the internal history be committed rather than exempted — null/fruit-fall is
already private and reports normally.
Two defects found on the way in and fixed here: zoho-setup.md told admins to
edit `server/zoho/`, a directory that has never existed in any commit (the
mapping is in server/index.js), and README.md's route list still advertised
/8x8, removed at 0.6.6, while omitting /privacy-policy.
Branding: icon.webp and logo.webp converted from this project's own marks in
assets/. banner.webp is absent and is filed as an issue rather than faked.
Verified: verify.sh 3/3, doc-claims 71 claimed paths all present, backup and a
first-ever restore of the live leads database (2 tables, 3 rows, under 1s).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:19:02 -05:00
# Claude QA Report — Queue North Website
```
Status: Current
Owner: _null
Last reviewed: 2026-08-18
Governs: the QA verdict — build SHAs, round summaries, the overall judgment
Review trigger: Any QA round run
```
> The QA verdict. Companion to `ClaudeQACoverage.md` (what each pass reached)
> and `ClaudeQAPlan.md` (the playbook).
>
> **Defects are issues, not entries here.** A defect found in a round is filed
> in the tracker with a severity label, where it can be assigned, closed by a
> commit, and counted. This file keeps the part a tracker is bad at: a human's
> judgment about whether the thing is fit to ship.
## Current run-state
2026-08-18 02:35:45 -05:00
- **Last QA round:** Round 0 — 2026-08-18, baseline plus a static accessibility audit
docs: adopt project template, retire the markdown backlog
This repository is the one the template's README describes: 205 issues, zero
milestones, and severity labels spelled "P0 Critical" / "P1 High" / "P2 Medium",
which privacyllc.dev reports as NOT ADOPTED rather than as 87% complete.
Six markdown records described the same work and none pointed at the tracker.
Two of them said the project was in "Phase 5" while the code was at 0.9.3.
Migrated, then deleted in this commit:
FUTURE.md -> docs/history/BATCH_LEDGER.md (Archived). Its open
items were all already filed as issues, so nothing
needed migrating into the tracker
HISTORY.md -> docs/history/DEVELOPMENT_LOG.md, verbatim, 0 lines lost
DEVELOPMENT_LOG.md -> the same file, as a second labelled block. Not
interleaved: the changelog has three duplicated version
headings, so one date order would have implied more
than the record supports
PROJECT.md -> docs/planning/PROJECT_PLAN.md
STRUCTURE.md -> the agent pipeline into README.md; its versioning rules
retired
BUILD_SUMMARY.md -> BATCH_LEDGER.md. Its embedded SQL schema deliberately
NOT carried: it predated the UNIQUE constraint on
leads.email, and server/index.js owns the schema
SCRIPTS.md -> docs/TOOLS.md, corrected for the SSR + prerender build
Moved with history (git detects all four as renames):
OVERHAUL_PLAN.md, review.md, project-requirements.md, docs/zoho-setup.md
Kept because this project earned them: the five-agent pipeline, the design
system in OVERHAUL_PLAN.md (Status: Current, with a front-note saying which half
is history), the positioning argument in REDESIGN_REVIEW.md, and REQUIREMENTS.md
whole, including its change policy.
Deleted from the template because they do not apply, each said out loud in
DOC_TRUST_MAP.md: QA pass I (no money moves), the authorisation checklist group
and the session-token row (no accounts, no sessions), and one PRECAUTIONARY
paragraph in SECURITY.md about holding credentials on behalf of users — there
are none, and PROJECT_PLAN.md records accounts as out of scope. Pass H was kept
and rewritten: its authorisation half does not apply, its what-a-stranger-can-
reach half is the most exposed surface here.
Also removed: main.js, the old static site's hash router, referenced by nothing
and preserved in .drop/; and test-results/.last-run.json, a May Playwright
artifact reading {"status":"failed"} for a suite that does not exist.
The repository was made private on Forgejo before this commit. That is what let
the internal history be committed rather than exempted — null/fruit-fall is
already private and reports normally.
Two defects found on the way in and fixed here: zoho-setup.md told admins to
edit `server/zoho/`, a directory that has never existed in any commit (the
mapping is in server/index.js), and README.md's route list still advertised
/8x8, removed at 0.6.6, while omitting /privacy-policy.
Branding: icon.webp and logo.webp converted from this project's own marks in
assets/. banner.webp is absent and is filed as an issue rather than faked.
Verified: verify.sh 3/3, doc-claims 71 claimed paths all present, backup and a
first-ever restore of the live leads database (2 tables, 3 rows, under 1s).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:19:02 -05:00
- **Last verified build SHA:** `ac6f5d1` on dev, deployed to nebula as `queue-north-website:dev`
- **Last tested device / environment:** none under this plan. The container's own
fix(infra): queuenorth.com is the production origin, and it is this deployment
_null confirmed queuenorth.com as the permanent public origin, which settles
#212 and exposed a wrong claim written earlier the same day.
docs/OPERATIONS.md said queuenorth.com "is not this deployment ... do not
diagnose against it". That came from a DNS lookup and an assumption. It is this
deployment: both hostnames serve the identical bundle and this server's own
/api/health shape, 24.41.108.95 is this network's own public IP, and both reach
qn-website-dev on nebula — queuenorth.com through nginx-proxy-manager on
thor/exodus, qn.isnull.dev through Cloudflare. Two front doors, one container,
no non-production environment.
That is the worst direction for a runbook to be wrong in, so the correction
quotes the wrong sentence rather than replacing it silently. The QA Round 0
table likewise gained the production observations as extra rows instead of
having its originals rewritten.
Dockerfile: the CORS_ORIGIN fallback was '*'. The server sets credentials:true
and browsers reject '*' with credentials outright, so that fallback would have
broken every form rather than over-permitting. Now the real origin.
healthcheck.sh and preflight.sh now watch production by default, with the
second front door reachable through their env overrides — the two ingresses
terminate TLS in different places and can rot independently.
Also fills a gap adoption left explicitly undone: the deploy path is a Portainer
stack, id 58 on nebula, found from the container's own compose labels.
OPERATIONS.md documents it, including that the stack file is a separate copy
from this repository's docker-compose.yml and the two have already drifted.
That drift is all that remains of #212 — one trailing slash on line 21 of the
stack file. Left in place: nothing is broken today, and fixing it recreates the
container and takes both front doors down together.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:08:12 -05:00
healthcheck and manual `curl` s against both public origins are the only
automated observations of the running site
docs: adopt project template, retire the markdown backlog
This repository is the one the template's README describes: 205 issues, zero
milestones, and severity labels spelled "P0 Critical" / "P1 High" / "P2 Medium",
which privacyllc.dev reports as NOT ADOPTED rather than as 87% complete.
Six markdown records described the same work and none pointed at the tracker.
Two of them said the project was in "Phase 5" while the code was at 0.9.3.
Migrated, then deleted in this commit:
FUTURE.md -> docs/history/BATCH_LEDGER.md (Archived). Its open
items were all already filed as issues, so nothing
needed migrating into the tracker
HISTORY.md -> docs/history/DEVELOPMENT_LOG.md, verbatim, 0 lines lost
DEVELOPMENT_LOG.md -> the same file, as a second labelled block. Not
interleaved: the changelog has three duplicated version
headings, so one date order would have implied more
than the record supports
PROJECT.md -> docs/planning/PROJECT_PLAN.md
STRUCTURE.md -> the agent pipeline into README.md; its versioning rules
retired
BUILD_SUMMARY.md -> BATCH_LEDGER.md. Its embedded SQL schema deliberately
NOT carried: it predated the UNIQUE constraint on
leads.email, and server/index.js owns the schema
SCRIPTS.md -> docs/TOOLS.md, corrected for the SSR + prerender build
Moved with history (git detects all four as renames):
OVERHAUL_PLAN.md, review.md, project-requirements.md, docs/zoho-setup.md
Kept because this project earned them: the five-agent pipeline, the design
system in OVERHAUL_PLAN.md (Status: Current, with a front-note saying which half
is history), the positioning argument in REDESIGN_REVIEW.md, and REQUIREMENTS.md
whole, including its change policy.
Deleted from the template because they do not apply, each said out loud in
DOC_TRUST_MAP.md: QA pass I (no money moves), the authorisation checklist group
and the session-token row (no accounts, no sessions), and one PRECAUTIONARY
paragraph in SECURITY.md about holding credentials on behalf of users — there
are none, and PROJECT_PLAN.md records accounts as out of scope. Pass H was kept
and rewritten: its authorisation half does not apply, its what-a-stranger-can-
reach half is the most exposed surface here.
Also removed: main.js, the old static site's hash router, referenced by nothing
and preserved in .drop/; and test-results/.last-run.json, a May Playwright
artifact reading {"status":"failed"} for a suite that does not exist.
The repository was made private on Forgejo before this commit. That is what let
the internal history be committed rather than exempted — null/fruit-fall is
already private and reports normally.
Two defects found on the way in and fixed here: zoho-setup.md told admins to
edit `server/zoho/`, a directory that has never existed in any commit (the
mapping is in server/index.js), and README.md's route list still advertised
/8x8, removed at 0.6.6, while omitting /privacy-policy.
Branding: icon.webp and logo.webp converted from this project's own marks in
assets/. banner.webp is absent and is filed as an issue rather than faked.
Verified: verify.sh 3/3, doc-claims 71 claimed paths all present, backup and a
first-ever restore of the live leads database (2 tables, 3 rows, under 1s).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:19:02 -05:00
- **Overall status:** No QA round has been run against this site under any
written plan, and there is no automated test suite to fall back on — the only
gate is that the build compiles. The site is up, healthy and taking real form
submissions, and 178 issues have been found and fixed by review rather than by
testing, which is a real record but a different one. What is untested is
everything a round would actually look at: the two form paths end to end into
Zoho, the failure behaviour when the CRM is unreachable, accessibility, and
what happens to the lead database if the volume is lost.
## Open defects
**Do not list them here, and do not read a defect count out of this file.** The
Command Center's docs report parses this document for open `P0` / `P1` / `P2`
counts, and under this convention they are always zero — the defects are in the
tracker, which is the whole point. A repository with seventeen open P1s reports
`openP1: 0` in that block and the real figure in its tracker counts. Anything
summarising defects reads the tracker's label counts; the zeros here mean *this
file does not hold them*, never *there are none* .
Filed as issues in this repository's tracker, labelled by what they cost:
- **P0** — ships broken, or loses data
- **P1** — materially wrong, but shippable
- **P2** — cosmetic or low impact
- **release-blocker** — a release built today would be *wrong* , not merely
incomplete
Severity is what it costs, not how annoying it is to fix. Every defect needs
the build SHA it was found at — a finding that cannot be re-tested cannot be
closed — so put it in the issue body.
**A note on `P3` .** This repository carries a fifth label, `P3` , on 21 closed
issues from before it adopted the convention. It is frozen: nothing new gets it.
It is not one of the four names the Command Center queries, so a defect filed
`P3` today would be counted by nothing.
## Round notes
### Round 0 — 2026-08-18 — baseline, no testing performed
Recorded on the day the project adopted the template, so that the run-state above
is a measurement rather than a blank. Nothing was tested. What is known about the
running system on this date, and how:
| Observation | How it is known |
| --- | --- |
fix(infra): queuenorth.com is the production origin, and it is this deployment
_null confirmed queuenorth.com as the permanent public origin, which settles
#212 and exposed a wrong claim written earlier the same day.
docs/OPERATIONS.md said queuenorth.com "is not this deployment ... do not
diagnose against it". That came from a DNS lookup and an assumption. It is this
deployment: both hostnames serve the identical bundle and this server's own
/api/health shape, 24.41.108.95 is this network's own public IP, and both reach
qn-website-dev on nebula — queuenorth.com through nginx-proxy-manager on
thor/exodus, qn.isnull.dev through Cloudflare. Two front doors, one container,
no non-production environment.
That is the worst direction for a runbook to be wrong in, so the correction
quotes the wrong sentence rather than replacing it silently. The QA Round 0
table likewise gained the production observations as extra rows instead of
having its originals rewritten.
Dockerfile: the CORS_ORIGIN fallback was '*'. The server sets credentials:true
and browsers reject '*' with credentials outright, so that fallback would have
broken every form rather than over-permitting. Now the real origin.
healthcheck.sh and preflight.sh now watch production by default, with the
second front door reachable through their env overrides — the two ingresses
terminate TLS in different places and can rot independently.
Also fills a gap adoption left explicitly undone: the deploy path is a Portainer
stack, id 58 on nebula, found from the container's own compose labels.
OPERATIONS.md documents it, including that the stack file is a separate copy
from this repository's docker-compose.yml and the two have already drifted.
That drift is all that remains of #212 — one trailing slash on line 21 of the
stack file. Left in place: nothing is broken today, and fixing it recreates the
container and takes both front doors down together.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:08:12 -05:00
| `https://queuenorth.com/` returns 200 | `curl` , once |
docs: adopt project template, retire the markdown backlog
This repository is the one the template's README describes: 205 issues, zero
milestones, and severity labels spelled "P0 Critical" / "P1 High" / "P2 Medium",
which privacyllc.dev reports as NOT ADOPTED rather than as 87% complete.
Six markdown records described the same work and none pointed at the tracker.
Two of them said the project was in "Phase 5" while the code was at 0.9.3.
Migrated, then deleted in this commit:
FUTURE.md -> docs/history/BATCH_LEDGER.md (Archived). Its open
items were all already filed as issues, so nothing
needed migrating into the tracker
HISTORY.md -> docs/history/DEVELOPMENT_LOG.md, verbatim, 0 lines lost
DEVELOPMENT_LOG.md -> the same file, as a second labelled block. Not
interleaved: the changelog has three duplicated version
headings, so one date order would have implied more
than the record supports
PROJECT.md -> docs/planning/PROJECT_PLAN.md
STRUCTURE.md -> the agent pipeline into README.md; its versioning rules
retired
BUILD_SUMMARY.md -> BATCH_LEDGER.md. Its embedded SQL schema deliberately
NOT carried: it predated the UNIQUE constraint on
leads.email, and server/index.js owns the schema
SCRIPTS.md -> docs/TOOLS.md, corrected for the SSR + prerender build
Moved with history (git detects all four as renames):
OVERHAUL_PLAN.md, review.md, project-requirements.md, docs/zoho-setup.md
Kept because this project earned them: the five-agent pipeline, the design
system in OVERHAUL_PLAN.md (Status: Current, with a front-note saying which half
is history), the positioning argument in REDESIGN_REVIEW.md, and REQUIREMENTS.md
whole, including its change policy.
Deleted from the template because they do not apply, each said out loud in
DOC_TRUST_MAP.md: QA pass I (no money moves), the authorisation checklist group
and the session-token row (no accounts, no sessions), and one PRECAUTIONARY
paragraph in SECURITY.md about holding credentials on behalf of users — there
are none, and PROJECT_PLAN.md records accounts as out of scope. Pass H was kept
and rewritten: its authorisation half does not apply, its what-a-stranger-can-
reach half is the most exposed surface here.
Also removed: main.js, the old static site's hash router, referenced by nothing
and preserved in .drop/; and test-results/.last-run.json, a May Playwright
artifact reading {"status":"failed"} for a suite that does not exist.
The repository was made private on Forgejo before this commit. That is what let
the internal history be committed rather than exempted — null/fruit-fall is
already private and reports normally.
Two defects found on the way in and fixed here: zoho-setup.md told admins to
edit `server/zoho/`, a directory that has never existed in any commit (the
mapping is in server/index.js), and README.md's route list still advertised
/8x8, removed at 0.6.6, while omitting /privacy-policy.
Branding: icon.webp and logo.webp converted from this project's own marks in
assets/. banner.webp is absent and is filed as an issue rather than faked.
Verified: verify.sh 3/3, doc-claims 71 claimed paths all present, backup and a
first-ever restore of the live leads database (2 tables, 3 rows, under 1s).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:19:02 -05:00
| `https://qn.isnull.dev/` returns 200 | `curl` , once |
fix(infra): queuenorth.com is the production origin, and it is this deployment
_null confirmed queuenorth.com as the permanent public origin, which settles
#212 and exposed a wrong claim written earlier the same day.
docs/OPERATIONS.md said queuenorth.com "is not this deployment ... do not
diagnose against it". That came from a DNS lookup and an assumption. It is this
deployment: both hostnames serve the identical bundle and this server's own
/api/health shape, 24.41.108.95 is this network's own public IP, and both reach
qn-website-dev on nebula — queuenorth.com through nginx-proxy-manager on
thor/exodus, qn.isnull.dev through Cloudflare. Two front doors, one container,
no non-production environment.
That is the worst direction for a runbook to be wrong in, so the correction
quotes the wrong sentence rather than replacing it silently. The QA Round 0
table likewise gained the production observations as extra rows instead of
having its originals rewritten.
Dockerfile: the CORS_ORIGIN fallback was '*'. The server sets credentials:true
and browsers reject '*' with credentials outright, so that fallback would have
broken every form rather than over-permitting. Now the real origin.
healthcheck.sh and preflight.sh now watch production by default, with the
second front door reachable through their env overrides — the two ingresses
terminate TLS in different places and can rot independently.
Also fills a gap adoption left explicitly undone: the deploy path is a Portainer
stack, id 58 on nebula, found from the container's own compose labels.
OPERATIONS.md documents it, including that the stack file is a separate copy
from this repository's docker-compose.yml and the two have already drifted.
That drift is all that remains of #212 — one trailing slash on line 21 of the
stack file. Left in place: nothing is broken today, and fixing it recreates the
container and takes both front doors down together.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:08:12 -05:00
| `/api/health` returns `{"status":"ok","db":"ok"}` on **both** origins | `curl` , once each |
feat(release): adapt PrivacyLLC-Web's release.sh, and add the deploy half it deliberately omits
scripts/release.sh — publish. Bump, guards, build, verify the image's own
version label, push :vX.Y.Z and move :dev, commit last, tag.
Adapted, not copied. The arguments are PrivacyLLC's and were paid for there; the
mechanism is this project's, because almost none of it transferred. Three
differences, each a fact about this repository rather than a preference:
- It gates on verify.sh, not a test suite, because there is not one. The
original refuses to release on a half-run 1,600-test run. This one says out
loud that a build, a secret scan and a doc-header check are not tests and that
nothing in the gate touched a route, a form or an API response.
- It moves :dev as well as publishing :vX.Y.Z, because Portainer stack 58
follows :dev. That makes :dev a pointer and never evidence.
- It checks the public origin in three files, not one. The original passes its
origin in as a build arg; here https://queuenorth.com is written out in
src/lib/seo.js, src/components/SEO.jsx and scripts/prerender.js and is baked
into every canonical URL, og:url, sitemap.xml and robots.txt. The guard asks
whether the three still agree.
Why this was needed: publishing was `npm run docker:push` with the bump as a
separate thing to remember, and it was not remembered. package.json said 0.8.3
while four commits announced "batch 0.9.0" through "0.9.3", and NO image was
ever published for any of them — the registry's newest tag is v0.8.3.
No prune. The original has one; this project has published thirteen tags in its
life, deleting a published image is irreversible, and the one that matters is
whichever the container was created from — exactly what a newest-N rule gets
wrong.
scripts/deploy.sh — deploy, and do not build. The template's deploy.py builds,
pushes AND deploys; adopting it beside release.sh would mean two commands that
both build, a second image for the same code, and two answers to "what is
running". This does only the missing half: point stack 58 at an already
published tag, having taken a verified backup first.
Its most important guard is not the obvious one. Portainer treats a stack PUT as
the whole desired state, so sending it without the stack's Env array would strip
twelve variables — the reCAPTCHA secret and the Zoho form tokens among them —
and the container would come back HEALTHY while quietly capturing no leads. It
reads them, counts them, sends them back, and refuses outright if none.
Guards proven to refuse, not assumed: already-published tag, http origin,
trailing-slash origin, the three origin constants drifted, dirty tree, bad flag,
unpublished deploy tag, missing Portainer key, wrong stack id.
One real bug found and fixed while testing: the image-line rewrite used
`python3 -` with a heredoc while also piping the stack file to stdin, so python
tried to execute the YAML.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:49:03 -05:00
| Both origins serve an identical bundle filename — index-pTFwovIx.js on this date, unbackticked because a content-hashed artefact is not a repository path | `curl` , once each — this is what established they are one container, not two |
fix(infra): queuenorth.com is the production origin, and it is this deployment
_null confirmed queuenorth.com as the permanent public origin, which settles
#212 and exposed a wrong claim written earlier the same day.
docs/OPERATIONS.md said queuenorth.com "is not this deployment ... do not
diagnose against it". That came from a DNS lookup and an assumption. It is this
deployment: both hostnames serve the identical bundle and this server's own
/api/health shape, 24.41.108.95 is this network's own public IP, and both reach
qn-website-dev on nebula — queuenorth.com through nginx-proxy-manager on
thor/exodus, qn.isnull.dev through Cloudflare. Two front doors, one container,
no non-production environment.
That is the worst direction for a runbook to be wrong in, so the correction
quotes the wrong sentence rather than replacing it silently. The QA Round 0
table likewise gained the production observations as extra rows instead of
having its originals rewritten.
Dockerfile: the CORS_ORIGIN fallback was '*'. The server sets credentials:true
and browsers reject '*' with credentials outright, so that fallback would have
broken every form rather than over-permitting. Now the real origin.
healthcheck.sh and preflight.sh now watch production by default, with the
second front door reachable through their env overrides — the two ingresses
terminate TLS in different places and can rot independently.
Also fills a gap adoption left explicitly undone: the deploy path is a Portainer
stack, id 58 on nebula, found from the container's own compose labels.
OPERATIONS.md documents it, including that the stack file is a separate copy
from this repository's docker-compose.yml and the two have already drifted.
That drift is all that remains of #212 — one trailing slash on line 21 of the
stack file. Left in place: nothing is broken today, and fixing it recreates the
container and takes both front doors down together.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:08:12 -05:00
| `www.queuenorth.com` 301s to the apex; both origins 301 plain HTTP and carry HSTS | `curl -I` , and `scripts/preflight.sh` clean against each |
docs: adopt project template, retire the markdown backlog
This repository is the one the template's README describes: 205 issues, zero
milestones, and severity labels spelled "P0 Critical" / "P1 High" / "P2 Medium",
which privacyllc.dev reports as NOT ADOPTED rather than as 87% complete.
Six markdown records described the same work and none pointed at the tracker.
Two of them said the project was in "Phase 5" while the code was at 0.9.3.
Migrated, then deleted in this commit:
FUTURE.md -> docs/history/BATCH_LEDGER.md (Archived). Its open
items were all already filed as issues, so nothing
needed migrating into the tracker
HISTORY.md -> docs/history/DEVELOPMENT_LOG.md, verbatim, 0 lines lost
DEVELOPMENT_LOG.md -> the same file, as a second labelled block. Not
interleaved: the changelog has three duplicated version
headings, so one date order would have implied more
than the record supports
PROJECT.md -> docs/planning/PROJECT_PLAN.md
STRUCTURE.md -> the agent pipeline into README.md; its versioning rules
retired
BUILD_SUMMARY.md -> BATCH_LEDGER.md. Its embedded SQL schema deliberately
NOT carried: it predated the UNIQUE constraint on
leads.email, and server/index.js owns the schema
SCRIPTS.md -> docs/TOOLS.md, corrected for the SSR + prerender build
Moved with history (git detects all four as renames):
OVERHAUL_PLAN.md, review.md, project-requirements.md, docs/zoho-setup.md
Kept because this project earned them: the five-agent pipeline, the design
system in OVERHAUL_PLAN.md (Status: Current, with a front-note saying which half
is history), the positioning argument in REDESIGN_REVIEW.md, and REQUIREMENTS.md
whole, including its change policy.
Deleted from the template because they do not apply, each said out loud in
DOC_TRUST_MAP.md: QA pass I (no money moves), the authorisation checklist group
and the session-token row (no accounts, no sessions), and one PRECAUTIONARY
paragraph in SECURITY.md about holding credentials on behalf of users — there
are none, and PROJECT_PLAN.md records accounts as out of scope. Pass H was kept
and rewritten: its authorisation half does not apply, its what-a-stranger-can-
reach half is the most exposed surface here.
Also removed: main.js, the old static site's hash router, referenced by nothing
and preserved in .drop/; and test-results/.last-run.json, a May Playwright
artifact reading {"status":"failed"} for a suite that does not exist.
The repository was made private on Forgejo before this commit. That is what let
the internal history be committed rather than exempted — null/fruit-fall is
already private and reports normally.
Two defects found on the way in and fixed here: zoho-setup.md told admins to
edit `server/zoho/`, a directory that has never existed in any commit (the
mapping is in server/index.js), and README.md's route list still advertised
/8x8, removed at 0.6.6, while omitting /privacy-policy.
Branding: icon.webp and logo.webp converted from this project's own marks in
assets/. banner.webp is absent and is filed as an issue rather than faked.
Verified: verify.sh 3/3, doc-claims 71 claimed paths all present, backup and a
first-ever restore of the live leads database (2 tables, 3 rows, under 1s).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:19:02 -05:00
| Container `qn-website-dev` on nebula is healthy, restart count 0 | `docker inspect` |
| The lead database holds 3 tables and took writes on 2026-08-18 | `sqlite_master` count and the file mtime |
| Security headers, CSP and HSTS are present on the live origin | response headers |
None of that is a QA pass. It is evidence that the thing is running.
fix(infra): queuenorth.com is the production origin, and it is this deployment
_null confirmed queuenorth.com as the permanent public origin, which settles
#212 and exposed a wrong claim written earlier the same day.
docs/OPERATIONS.md said queuenorth.com "is not this deployment ... do not
diagnose against it". That came from a DNS lookup and an assumption. It is this
deployment: both hostnames serve the identical bundle and this server's own
/api/health shape, 24.41.108.95 is this network's own public IP, and both reach
qn-website-dev on nebula — queuenorth.com through nginx-proxy-manager on
thor/exodus, qn.isnull.dev through Cloudflare. Two front doors, one container,
no non-production environment.
That is the worst direction for a runbook to be wrong in, so the correction
quotes the wrong sentence rather than replacing it silently. The QA Round 0
table likewise gained the production observations as extra rows instead of
having its originals rewritten.
Dockerfile: the CORS_ORIGIN fallback was '*'. The server sets credentials:true
and browsers reject '*' with credentials outright, so that fallback would have
broken every form rather than over-permitting. Now the real origin.
healthcheck.sh and preflight.sh now watch production by default, with the
second front door reachable through their env overrides — the two ingresses
terminate TLS in different places and can rot independently.
Also fills a gap adoption left explicitly undone: the deploy path is a Portainer
stack, id 58 on nebula, found from the container's own compose labels.
OPERATIONS.md documents it, including that the stack file is a separate copy
from this repository's docker-compose.yml and the two have already drifted.
That drift is all that remains of #212 — one trailing slash on line 21 of the
stack file. Left in place: nothing is broken today, and fixing it recreates the
container and takes both front doors down together.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:08:12 -05:00
**Added later the same day.** The table above originally recorded only
`qn.isnull.dev` , because this session had not yet established that
`queuenorth.com` is the production front door for the same container — an
earlier draft of `docs/OPERATIONS.md` asserted the opposite. The extra rows are
what was actually checked once that was known, and they are added rather than
substituted so the record shows the correction happening.
docs: adopt project template, retire the markdown backlog
This repository is the one the template's README describes: 205 issues, zero
milestones, and severity labels spelled "P0 Critical" / "P1 High" / "P2 Medium",
which privacyllc.dev reports as NOT ADOPTED rather than as 87% complete.
Six markdown records described the same work and none pointed at the tracker.
Two of them said the project was in "Phase 5" while the code was at 0.9.3.
Migrated, then deleted in this commit:
FUTURE.md -> docs/history/BATCH_LEDGER.md (Archived). Its open
items were all already filed as issues, so nothing
needed migrating into the tracker
HISTORY.md -> docs/history/DEVELOPMENT_LOG.md, verbatim, 0 lines lost
DEVELOPMENT_LOG.md -> the same file, as a second labelled block. Not
interleaved: the changelog has three duplicated version
headings, so one date order would have implied more
than the record supports
PROJECT.md -> docs/planning/PROJECT_PLAN.md
STRUCTURE.md -> the agent pipeline into README.md; its versioning rules
retired
BUILD_SUMMARY.md -> BATCH_LEDGER.md. Its embedded SQL schema deliberately
NOT carried: it predated the UNIQUE constraint on
leads.email, and server/index.js owns the schema
SCRIPTS.md -> docs/TOOLS.md, corrected for the SSR + prerender build
Moved with history (git detects all four as renames):
OVERHAUL_PLAN.md, review.md, project-requirements.md, docs/zoho-setup.md
Kept because this project earned them: the five-agent pipeline, the design
system in OVERHAUL_PLAN.md (Status: Current, with a front-note saying which half
is history), the positioning argument in REDESIGN_REVIEW.md, and REQUIREMENTS.md
whole, including its change policy.
Deleted from the template because they do not apply, each said out loud in
DOC_TRUST_MAP.md: QA pass I (no money moves), the authorisation checklist group
and the session-token row (no accounts, no sessions), and one PRECAUTIONARY
paragraph in SECURITY.md about holding credentials on behalf of users — there
are none, and PROJECT_PLAN.md records accounts as out of scope. Pass H was kept
and rewritten: its authorisation half does not apply, its what-a-stranger-can-
reach half is the most exposed surface here.
Also removed: main.js, the old static site's hash router, referenced by nothing
and preserved in .drop/; and test-results/.last-run.json, a May Playwright
artifact reading {"status":"failed"} for a suite that does not exist.
The repository was made private on Forgejo before this commit. That is what let
the internal history be committed rather than exempted — null/fruit-fall is
already private and reports normally.
Two defects found on the way in and fixed here: zoho-setup.md told admins to
edit `server/zoho/`, a directory that has never existed in any commit (the
mapping is in server/index.js), and README.md's route list still advertised
/8x8, removed at 0.6.6, while omitting /privacy-policy.
Branding: icon.webp and logo.webp converted from this project's own marks in
assets/. banner.webp is absent and is filed as an issue rather than faked.
Verified: verify.sh 3/3, doc-claims 71 claimed paths all present, backup and a
first-ever restore of the live leads database (2 tables, 3 rows, under 1s).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:19:02 -05:00
The first real round should start with pass B — the two form paths end to end,
including whether a lead actually lands in Zoho — because that is the product's
entire purpose and nothing has ever verified it end to end from outside.