Skip to content

Commit 87eaf37

Browse files
hsnice16claude
andcommitted
docs: align security & contributor guides with codebase reality
- README/AGENTS/skills now describe `dangerouslySetInnerHTML` accurately (allowed only for the existing JSON-LD scripts) and require `rel="noopener noreferrer"` on external links to match what the code already does. - README expands the agent list, refreshes the "Server-first; client islands" stack row, and drops `tmp-clones/` from Layout + Operational concerns. AGENTS fixes the "Adding a host" seed pointer (`scripts/seed-list.ts`) and the `dangerouslyInnerHTML` typo. - CONTRIBUTING aligns the PR-size guidance with the lefthook 300-line cap. - Removes remaining `tmp-clones/` mentions across docs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1bcc60c commit 87eaf37

7 files changed

Lines changed: 17 additions & 18 deletions

File tree

.claude/skills/code-review/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ Only `@phosphor-icons/react`. Block Lucide, Heroicons, React Icons, inline SVG,
5454
## Security
5555

5656
- Parameterised SQL only.
57-
- No `dangerouslySetInnerHTML`.
58-
- External links include `rel="noopener"`.
57+
- `dangerouslySetInnerHTML` is allowed only for the existing server-built JSON-LD scripts (`app/layout.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`) with the `<``<` escape preserved. Reject any new use.
58+
- External links include `rel="noopener noreferrer"`.
5959
- Never execute code from a cloned repo.
6060

6161
## Response format when reviewing

.claude/skills/post-change-check/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Invoke the `quality-check` skill on the diff. Four dimensions:
8282
- **Accessibility**: landmarks, aria, contrast, reduced-motion, keyboard reachability.
8383
- **Responsiveness**: 320 → 1080+, mobile nav, table overflow, line-length caps.
8484
- **Performance**: RSC default, `next/script` for third-party, bundle weight, prepared statements.
85-
- **Security**: parameterised SQL, no `dangerouslySetInnerHTML`, `rel="noopener"` on external links, clone safety.
85+
- **Security**: parameterised SQL, `dangerouslySetInnerHTML` only for the existing server-built JSON-LD scripts (with `<` escape preserved), `rel="noopener noreferrer"` on external links, clone safety.
8686

8787
Report Pass / Fail / Needs manual check per dimension.
8888

.claude/skills/quality-check/SKILL.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ Run the four checks below on any diff affecting UI or I/O. Report findings group
3939
## Security
4040

4141
- **SQL parameterisation**: every query uses `?` placeholders. No string concatenation.
42-
- **No `dangerouslySetInnerHTML`.**
43-
- **External URLs** in `<a target="_blank">` always include `rel="noopener"`.
42+
- **`dangerouslySetInnerHTML`** is allowed only for server-built JSON-LD (`app/layout.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`) and must keep the `<``<` escape. Any other use must be rejected.
43+
- **External URLs** in `<a target="_blank">` always include `rel="noopener noreferrer"`.
4444
- **User input at every boundary** is validated: `parseRepoUrl` for repo URLs, `Number.isFinite` for numeric params, length caps on search strings.
4545
- **Clone safety**: `git clone --depth 1 --single-branch`; never execute code from a clone (no `bun install`, no `npm install`, no post-clone scripts).
4646
- **Secrets never in code**. `.env.example` documents required vars; `.env.local` is gitignored.
4747
- **Operational concerns** (flag for ops review, not code):
48-
- Disk cap on `tmp-clones/`.
48+
- Disk cap on the clone workspace.
4949
- Rate limit on the public API before launch.
5050
- Sandbox the cloner in a container for production.
5151

AGENTS.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ Keep it that way when adding features. If a component needs data, fetch in the p
142142

143143
1. Extend `parseRepoUrl` in `lib/clients/github.ts`.
144144
2. Extend `fetchRepoMeta` with that host's API (use `process.env.<HOST>_TOKEN` if needed).
145-
3. Add a seed URL in `scripts/seed.ts`.
145+
3. Add a seed URL to the `SEEDS` list in `scripts/seed-list.ts`.
146146
4. Add the label to `lib/constants/hosts.ts`.
147147

148148
## Working from tasks/
@@ -165,7 +165,7 @@ The `Stop` guard exists because reminders alone weren't enough — agents would
165165
`.claude/skills/` holds project skills that are auto-selected based on task relevance or invoked manually (`/skill-name`). Skills **do not auto-fire on file edits** — that's what the Stop guard is for. The guard enforces `post-change-check`, which orchestrates the other two.
166166

167167
- **`code-review`** — writing-time conventions. Covers Tailwind-first (utilities > custom classes; `@theme` tokens > hex), **Phosphor Icons only** (blocks Lucide / Heroicons / React Icons / inline SVG / emoji-as-icon), the I/O boundary (`lib/scoring/` pure, all SQL in `lib/db.ts`), RSC preference, and when to extract into `components/` / `lib/constants/` / `lib/utils/`.
168-
- **`quality-check`** — review-time sweep. Four dimensions: accessibility (landmarks, aria, contrast, reduced motion, keyboard reachability), responsiveness (320 → 1080+ viewports, mobile nav, tables), performance (RSC default, `next/script` for third-party, bundle size), security (parameterised SQL, no innerHTML, `rel=noopener`, clone safety).
168+
- **`quality-check`** — review-time sweep. Four dimensions: accessibility (landmarks, aria, contrast, reduced motion, keyboard reachability), responsiveness (320 → 1080+ viewports, mobile nav, tables), performance (RSC default, `next/script` for third-party, bundle size), security (parameterised SQL, `dangerouslySetInnerHTML` only for the existing server-built JSON-LD scripts, `rel="noopener noreferrer"` on external links, clone safety).
169169
- **`post-change-check`** — end-of-turn orchestrator. Runs a four-phase report: diff collection, docs-sync audit (changelog / tasks / AGENTS / README / .env.example / skills), then delegates to `code-review` and `quality-check`. The Stop guard blocks turn-close until this has run when watched paths changed.
170170

171171
Skill granularity rule of thumb: one skill per _phase_ of work (writing, reviewing, wrapping-up), not one skill per _rule_. Narrow skills fragment context; broad skills stay coherent.
@@ -176,13 +176,13 @@ Hooks docs: <https://docs.claude.com/en/docs/claude-code/hooks.html>.
176176

177177
- We `git clone --depth 1 --single-branch` arbitrary URLs — safe by default. We never run post-clone scripts, never `npm install`, never execute code from the clone.
178178
- SQL: all queries parameterised. No interpolation.
179-
- HTML: React auto-escapes; no `dangerouslyInnerHTML` anywhere.
180-
- Local-path mode reads files; never writes outside `data/` and `tmp-clones/`.
179+
- HTML: React auto-escapes. The only `dangerouslySetInnerHTML` is server-built JSON-LD with `<` escaped to `<` (`app/layout.tsx`, `app/repo/[id]/page.tsx`, `app/package/[registry]/[name]/page.tsx`); never feed user-controlled strings into it.
180+
- Local-path mode reads files; never writes outside `data/` and the clone workspace passed to `shallowClone`.
181181
- No auth yet (read-only dashboard). When auth lands (`tasks/0.6.0/01-opt-out-claim-flow.md`), do it via OAuth and gate DB writes per user.
182182

183183
**Operational concerns** (not code-level security) worth flagging before public launch:
184184

185-
- `tmp-clones/` can fill disk — add a cron/cap.
185+
- The clone workspace can fill disk — add a cron/cap.
186186
- Unauthenticated API → add rate limits before going public.
187187
- Sandbox the cloner in a container when running on remote infra, just in case of future git CVEs.
188188

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ When the PR qualifies, move the item atomically: append a one-line capability bu
102102

103103
### Size
104104

105-
PRs under ~400 lines of diff review fastest. If your change is larger, split by feature or by layer (scoring → DB → UI) so each PR is independently reviewable.
105+
PRs under ~300 lines of diff review fastest — the same cap the `file-length` pre-commit job enforces per file. If your change is larger, split by feature or by layer (scoring → DB → UI) so each PR is independently reviewable.
106106

107107
## Review bar
108108

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Follows `prefers-color-scheme` automatically — same tokens, different values.
2626

2727
## The idea
2828

29-
AI coding agents — Claude Code, Cursor, Devin, GPT-5 Codex — succeed dramatically more often on some repos than others. The difference is rarely the agent; it's the repo. A codebase with fast tests, a clear `AGENTS.md`, a Makefile, and CI is a massively different environment than one without.
29+
AI coding agents — Claude Code, Cursor, Devin, GPT-5 Codex, Gemini CLI, Aider, OpenHands, Pi — succeed dramatically more often on some repos than others. The difference is rarely the agent; it's the repo. A codebase with fast tests, a clear `AGENTS.md`, a Makefile, and CI is a massively different environment than one without.
3030

3131
**Goal**: a public leaderboard where anyone can look up a repo and see:
3232

@@ -75,12 +75,12 @@ Short answer: **low risk**. The app:
7575
- Only **reads** files after a shallow clone; never executes anything from the cloned tree (no `npm install`, no post-clone hooks).
7676
- Uses `--depth 1 --single-branch` and never clones submodules.
7777
- Runs all SQL via prepared statements.
78-
- Renders through React (auto-escaping); no `dangerouslySetInnerHTML`.
78+
- Renders through React (auto-escaping); the only `dangerouslySetInnerHTML` use is server-built JSON-LD with `<` escaped to `<`.
7979
- Has no auth and no writable API endpoints — read-only dashboard.
8080

8181
**Operational concerns** for a public launch (not code-level security):
8282

83-
- Disk quotas for `tmp-clones/`.
83+
- Disk quotas for the clone workspace.
8484
- Rate limiting the public API.
8585
- Sandbox the cloner in a container (future-proofing against hypothetical git CVEs).
8686

@@ -120,7 +120,7 @@ Run the unit tests with `bun run test` (uses `node --test` + `tsx`; requires Nod
120120
| **Node runtime (with `tsx` for CLI scripts)** | Matches Vercel's serverless runtime — no Bun-only imports in prod. Bun still works locally as a fast package manager. | Unlikely — only if the deployment target changes. |
121121
| **Tailwind CSS 4** | Zero-config via `@theme` tokens, no `tailwind.config.*` needed. Tight bundle output. | Would only leave for something with a stronger design-system story. |
122122
| **`better-sqlite3`** | Single file, inspectable, zero ops overhead. Node-native so Vercel's serverless runtime can load it directly. | Postgres when concurrent writers / access control arrive (`tasks/1.0.0/01-postgres-migration.md`). |
123-
| **Server components + links, no client JS** | Cheap, fast, SEO-friendly. | When a feature genuinely needs interactivity — e.g. live filter combinators. |
123+
| **Server-first; client islands where needed** | Cheap, fast, SEO-friendly. Client components only where interactivity demands — mobile nav, search, selects, copy, back-to-top. | When client islands grow past presentational interactivity → reach for client state mgmt. |
124124
| **Shallow git clones** (`--depth 1 --single-branch`) | Bandwidth + speed. Current signals don't need history. | History-aware signals → host APIs or `--filter=blob:none` partial clones. |
125125
| **Exact-pinned deps** | Deterministic scoring across environments. | Never. |
126126
| **One file per signal** | Each signal is a small, independent concern — keeps `git log` and code review focused. | When we bundle signals into dynamic checks (then the unit becomes the bundle). |
@@ -160,7 +160,6 @@ tasks/ Per-version task breakdown (agent-readable)
160160
public/ Static assets — demo/ screenshots used by the README + OG image
161161
.claude/ settings.json, hooks/ (Stop guard), skills/
162162
data/ rank.db (committed — shipped as a build artifact; rescoring runs locally)
163-
tmp-clones/ Shallow clones (gitignored)
164163
AGENTS.md Agent instructions (source of truth)
165164
CONTRIBUTING.md Human-contributor guide — PR workflow, review bar
166165
CLAUDE.md Pointer → AGENTS.md

tasks/0.2.0/02-self-score.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ Confirm this repo hits ≥ 90 overall on its own rubric once `tasks/0.2.0/01-tes
2121

2222
- Scored via local-path mode (`bun run score .`) so the score reflects the tree _with_ the new `tests/` suite rather than the yet-to-be-pushed GitHub state:
2323
- Overall **90.6**. Per-model: Claude Code 90.0, Cursor 92.7, Devin 89.0, GPT-5 Codex 90.7 — every model within 2.7 pts of overall.
24-
- `tests` flipped from 0 → 1. `dev_env` still partial at 0.6 (package.json scripts only). `size` drops to 0.2 locally because the `tmp-clones/` workspace directory pollutes the count — not a signal bug (remote scoring clones into `tmp-clones/<slug>/` and scans the inner dir, so the sibling never shows up); called out here rather than patched.
24+
- `tests` flipped from 0 → 1. `dev_env` still partial at 0.6 (package.json scripts only). `size` drops to 0.2 locally because the local clone workspace pollutes the count — not a signal bug (remote scoring clones into a per-repo subdirectory and scans the inner dir, so the sibling never shows up); called out here rather than patched.

0 commit comments

Comments
 (0)