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
|
|
|
# Guards — how to write a check that actually checks
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Status: Current
|
|
|
|
|
Owner: _null
|
|
|
|
|
Last reviewed: 2026-08-18
|
|
|
|
|
Governs: scripts/verify.d/**, .githooks/** — structural tests, source-grep
|
|
|
|
|
assertions, probes, and any check whose passing is taken as evidence
|
|
|
|
|
Review trigger: A guard is found to have been passing while the thing it guards
|
|
|
|
|
was broken; a new class of check is added to the suite.
|
|
|
|
|
```
|
|
|
|
|
|
fix(security): stop secrets.sh flagging every prerendered page, and clear the dangling doc claims
secrets.sh --built reported ten credentials in dist/ and all ten were the same
false positive: the template's user:pass@host pattern reads the schema.org
JSON-LD on every prerendered page — //queuenorth.com"},"areaServed":{"@ — as a
host, a password and an @. One more finding for every page added, which is the
noise that turns a scanner into something people mute.
Quotes, braces, commas and angle brackets cannot occur in a real userinfo
component. Checked against a database URL with an inline password, one
percent-encoded, and a git remote carrying a token — all three still caught, all
ten false positives gone, and the historical Zoho leak from 033bdf6 still caught
when replayed.
The first version of that fix wrote its three test cases out literally in the
header, and --tracked then reported two credentials in the scanner itself. The
placeholders now use angle brackets, which are in the exclusion class the
comment is describing — so the examples cannot match the pattern they
illustrate. Same shape as the trap DOC_TRUST_MAP.md records about Exempt: lines.
doc-claims: 240 claimed paths, all present, up from 5 dangling. DOC_TRUST_MAP
was claiming banner.webp exists while saying it does not; GUARDS.md pointed at
prove-guard.sh, which this project declined. docs/history/ is excluded rather
than corrected — its entries name files that existed when they were written, and
editing an append-only log to satisfy a present-tense check is a category error.
TOOLS.md records the exclusion and why.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:40:46 -05:00
|
|
|
> **prove-guard.sh is not in this repository.** It lives in the template at
|
|
|
|
|
> `~/.openclaw/Projects/Template/docs/architecture/scripts/`, and this project
|
|
|
|
|
> declined it on adoption — its guards are three shell scripts in
|
|
|
|
|
> `scripts/verify.d/` that fail visibly on their own. It is named without
|
|
|
|
|
> backticks throughout for that reason. §1 below still applies and was performed
|
|
|
|
|
> by hand on every guard here; `docs/history/DEVELOPMENT_LOG.md` for 2026-08-18
|
|
|
|
|
> records how each was broken and what it did.
|
|
|
|
|
|
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
|
|
|
A guard that cannot fail is worse than no guard, because it is trusted. Every
|
|
|
|
|
rule here was learned by finding one that had been green for months over
|
|
|
|
|
something broken.
|
|
|
|
|
|
|
|
|
|
## 1. Prove the guard fails before you believe it passes
|
|
|
|
|
|
|
|
|
|
The one discipline that matters most, and it takes thirty seconds:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cp src/lib/thing.ts /tmp/thing.bak
|
|
|
|
|
# break exactly the thing the test protects
|
|
|
|
|
sed -i 's/if (body.error)/if (false)/' src/lib/thing.ts
|
|
|
|
|
npx vitest run tests/thing.test.ts # expect: exactly one failure
|
|
|
|
|
cp /tmp/thing.bak src/lib/thing.ts
|
|
|
|
|
npx vitest run tests/thing.test.ts # expect: green again
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Exactly one** is the part people skip. If breaking the guard's target fails
|
|
|
|
|
three tests, two of them are coincidental and will mask a real regression later.
|
|
|
|
|
If it fails none, the guard is decoration — and you have just learned that for
|
|
|
|
|
the price of one `sed`.
|
|
|
|
|
|
fix(security): stop secrets.sh flagging every prerendered page, and clear the dangling doc claims
secrets.sh --built reported ten credentials in dist/ and all ten were the same
false positive: the template's user:pass@host pattern reads the schema.org
JSON-LD on every prerendered page — //queuenorth.com"},"areaServed":{"@ — as a
host, a password and an @. One more finding for every page added, which is the
noise that turns a scanner into something people mute.
Quotes, braces, commas and angle brackets cannot occur in a real userinfo
component. Checked against a database URL with an inline password, one
percent-encoded, and a git remote carrying a token — all three still caught, all
ten false positives gone, and the historical Zoho leak from 033bdf6 still caught
when replayed.
The first version of that fix wrote its three test cases out literally in the
header, and --tracked then reported two credentials in the scanner itself. The
placeholders now use angle brackets, which are in the exclusion class the
comment is describing — so the examples cannot match the pattern they
illustrate. Same shape as the trap DOC_TRUST_MAP.md records about Exempt: lines.
doc-claims: 240 claimed paths, all present, up from 5 dangling. DOC_TRUST_MAP
was claiming banner.webp exists while saying it does not; GUARDS.md pointed at
prove-guard.sh, which this project declined. docs/history/ is excluded rather
than corrected — its entries name files that existed when they were written, and
editing an append-only log to satisfy a present-tense check is a category error.
TOOLS.md records the exclusion and why.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:40:46 -05:00
|
|
|
prove-guard.sh performs exactly this, which removes the two ways it
|
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
|
|
|
gets skipped: the restore is a `trap`, so an interrupted run cannot leave the
|
|
|
|
|
code broken, and the failure count comes from the runner's own summary rather
|
|
|
|
|
than from eyeballing red — one failing test is routinely reported on half a
|
|
|
|
|
dozen lines, and counting those calls a clean result six coincidental
|
|
|
|
|
failures.
|
|
|
|
|
|
|
|
|
|
Do this when you write a guard, and again when you change what it guards. A
|
|
|
|
|
test written alongside the code it tests has never been observed failing.
|
|
|
|
|
|
|
|
|
|
## 2. A source-grep guard must tell code from the comment about code
|
|
|
|
|
|
|
|
|
|
Structural tests that assert a file does *not* contain some pattern will match
|
|
|
|
|
the docblock explaining why that pattern is forbidden. So the clearest possible
|
|
|
|
|
comment breaks the test, and the obvious fix is to delete the explanation.
|
|
|
|
|
|
|
|
|
|
Strip comments first:
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
const codeOf = (path: string) =>
|
|
|
|
|
readFileSync(path, "utf8")
|
|
|
|
|
.split("\n")
|
|
|
|
|
.filter((line) => !/^\s*(\*|\/\/|\{\/\*)/.test(line))
|
|
|
|
|
.join("\n");
|
|
|
|
|
|
|
|
|
|
expect(codeOf("src/lib/thing.ts")).not.toContain("dangerouslySetInnerHTML");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Otherwise the guard quietly punishes documenting the rule it exists to enforce —
|
|
|
|
|
which is exactly backwards, because the comment is how the next person learns
|
|
|
|
|
the rule at all.
|
|
|
|
|
|
|
|
|
|
## 3. Pin the behaviour, not the spelling
|
|
|
|
|
|
|
|
|
|
A guard should fail when the protected behaviour breaks and stay quiet
|
|
|
|
|
otherwise. One that asserts on a variable name fails on a rename that changed
|
|
|
|
|
nothing.
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
// Brittle: breaks when the variable is renamed, while the fallback it protects
|
|
|
|
|
// is untouched.
|
|
|
|
|
expect(route).toContain("readAsset(project.forgejoRepo");
|
|
|
|
|
|
|
|
|
|
// Pins the behaviour: the route fetches through the wrapper that tries both
|
|
|
|
|
// spellings, and never through the raw reader.
|
|
|
|
|
expect(route).toMatch(/readAsset\(\s*\w+,\s*ASSETS\[which\]\s*\)/);
|
|
|
|
|
expect(body).not.toContain("readFileBytes(");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
A guard that fails on changes it does not care about is one people learn to edit
|
|
|
|
|
rather than heed, and the edit is usually deletion.
|
|
|
|
|
|
|
|
|
|
## 4. A negative result is only as good as the probe that produced it
|
|
|
|
|
|
|
|
|
|
"The check found nothing" and "the check did not run" are different facts, and
|
|
|
|
|
they look identical from the outside. Before reporting an absence, prove the
|
|
|
|
|
instrument worked:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Not this alone — an unreadable file produces the same silence as an unset key
|
|
|
|
|
grep -c '^WANTED=' /proc/$PID/environ
|
|
|
|
|
|
|
|
|
|
# Establish the read succeeded first
|
|
|
|
|
tr '\0' '\n' < /proc/$PID/environ | grep -c . # 0 here means "could not read"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This is the confident-absence failure one level up: the same trap as a screen
|
|
|
|
|
rendering a failed query as a count of zero, applied to your own diagnosis.
|
|
|
|
|
|
|
|
|
|
## 5. A guard that is often wrong is worse than none
|
|
|
|
|
|
|
|
|
|
A check with a high false-positive rate trains everybody to skip its output,
|
|
|
|
|
including on the day it is right.
|
|
|
|
|
|
|
|
|
|
One written for this template flagged **684 of 1142** candidates on its first
|
|
|
|
|
run. That was not 684 findings, it was a broken heuristic — and shipping it
|
|
|
|
|
would have taught its readers that the check is noise. Two rounds of narrowing
|
|
|
|
|
brought it to 17 of 363, all of them real.
|
|
|
|
|
|
|
|
|
|
If a new guard's first run is loud, tune it until it is quiet before anybody
|
|
|
|
|
relies on it. Report the false-positive rate you settled at, so the next person
|
|
|
|
|
knows what silence is worth.
|
|
|
|
|
|
|
|
|
|
## 6. Guards belong before the artifact exists
|
|
|
|
|
|
|
|
|
|
A check that runs after publication catches the problem once it is somewhere it
|
|
|
|
|
cannot be taken back from: the tag is in the registry, and refusing the commit
|
|
|
|
|
afterwards leaves git with no record of it.
|
|
|
|
|
|
|
|
|
|
Order the gates so the expensive, irreversible step is last — preconditions,
|
|
|
|
|
guards, build, verify the built thing is what was asked for, publish, and record
|
|
|
|
|
it last of all.
|
|
|
|
|
|
|
|
|
|
## 7. When the gate finds something that invalidates the operation, stop
|
|
|
|
|
|
|
|
|
|
Printing a warning and continuing produces the worst outcome available: the bad
|
|
|
|
|
thing happens *and* a reassuring summary appears above it.
|
|
|
|
|
|
|
|
|
|
The question is not how bad the finding is. It is **whether it invalidates what
|
|
|
|
|
the operation claims**:
|
|
|
|
|
|
|
|
|
|
- A release whose test gate skipped half the suite — a release claims to be
|
|
|
|
|
tested. **Refuse.**
|
|
|
|
|
- A backup written to a group-readable directory — the backup is still a
|
|
|
|
|
backup. **Warn.**
|
|
|
|
|
|
|
|
|
|
Escape hatches are fine, and they have to be asked for by name, never be the
|
|
|
|
|
default, and say plainly what is being given up.
|