{"owner":"qazbnm456","repo":"awesome-web-security","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nGuidance for Claude Code working in this repository.\n\n## What this repo is\n\nA curated knowledge base of web security learning resources. Data lives in\n`data/categories.yml` and `data/entries/*.yml`; the three language READMEs\n(`README.md`, `README-zh.md`, `README-jp.md`) and `data/index.json` are\n**generated** from that data by `scripts/generate.py`. The same data backs a\nClaude Skill at `skills/awesome-web-security/` so AI agents can query the\nlist at runtime.\n\nNo build, no test suite, no application runtime. Every change is either\nYAML data, Python tooling, or Markdown docs.\n\n## Files of note\n\n- `data/categories.yml` — section tree, anchors, ToC. Edit carefully.\n- `data/entries/*.yml` — one file per section. Source of truth for entries.\n- `data/templates/preamble.md` / `postamble.md` — verbatim header/footer in\n  the generated READMEs.\n- `scripts/generate.py` — YAML → README.md / README-zh.md / README-jp.md /\n  data/index.json.\n- `scripts/migrate.py` — one-shot importer that originally produced the YAML\n  from the old hand-edited READMEs. Kept for reference; do not re-run on a\n  populated `data/`.\n- `scripts/verify_schema.py` — entry schema validation; CI gate.\n- `scripts/verify_anchors.py` — ensures no anchor used by external links is\n  removed; CI gate.\n- `scripts/verify_skill.sh` — lints `marketplace.json` and `SKILL.md`.\n- `scripts/ci/pr_review.py` — auto-review bot. Default LLM is\n  `openai/gpt-4.1-mini` via GitHub Models; override via the `REVIEW_MODEL`\n  env var in the workflow. Contributor language is detected\n  deterministically (Han / Kana regex on PR body) and passed to the LLM\n  as a directive; the LLM never owns language detection.\n- `scripts/ci/templates/comment.{en,zh,jp}.md` — localized review comments.\n- `.github/workflows/pr-review.yml` — runs the bot on every PR.\n- `.github/workflows/pr-review-backlog.yml` — dry-run over open PRs (manual,\n  workflow_dispatch). Stashes trusted scripts to `/tmp/awsec-trusted/` before\n  iterating PR refs, so `pr_review.py` always runs from the base branch even\n  when an attacker-controlled PR is checked out.\n- `.github/workflows/health-link-check.yml` — daily lychee scan over the\n  generated READMEs and `data/index.json`; surfaces broken links via a single\n  rolling issue labelled `health/link-check`. Replaces the previous\n  `validate.yml`.\n- `.github/workflows/post-merge-archive.yml` — after merges that touch\n  `data/entries/**`, submits eligible entries (active, no `archive_url` yet,\n  not opted out) to Wayback Machine and commits the resulting `archive_url`\n  back to the YAML with `[skip ci]`. Driven by `scripts/ci/archive.py`.\n- `.github/ISSUE_TEMPLATE/propose-resource.yml` — GitHub Form for proposals.\n- `.github/PULL_REQUEST_TEMPLATE.md` — self-checklist mirroring RUBRIC.md.\n- `.claude-plugin/marketplace.json` — declares the Claude plugin / Skill\n  package distributed via this repo.\n- `skills/awesome-web-security/SKILL.md` — the Skill body. Lives here so the\n  same repo serves humans and AI agents.\n- `RUBRIC.md` — the five-dimension scoring rubric the bot applies; also the\n  contributor self-check reference.\n- `CONTRIBUTING.md` — contributor flow. Treat as authoritative for PR\n  procedure; do not duplicate its contents here.\n\n## Editing rules\n\n- **Never edit `README.md`, `README-zh.md`, or `README-jp.md` directly.**\n  They are regenerated from `data/` by `scripts/generate.py`. Edits will be\n  blown away on the next regeneration.\n- To add or modify an entry, edit `data/entries/<category>.yml`.\n- To add a new category, edit `data/categories.yml` first, then add a new\n  `data/entries/<category-key>.yml`. Run `scripts/verify_anchors.py`\n  afterwards to confirm no external-facing anchor was lost.\n- After any data change, run `python3 scripts/generate.py` to refresh the\n  generated files locally before committing. CI will reject divergence.\n\n## Entry schema\n\n```yaml\n- id: xss-google-app-security                   # kebab-case, unique\n  url: https://www.google.com/...               # required, https preferred\n  title: Cross-Site Scripting – Application Security – Google\n  author:\n    name: Google                                # required if author exists\n    url: https://www.google.com/                # optional\n  category: xss                                 # must exist in categories.yml\n  type: article                                 # article|tool|cheatsheet|video|book|community|payload-list\n  languages: [en]                               # subset of: en|zh|jp|tr|universal\n  difficulty: intro                             # intro|intermediate|advanced\n  date_added: 2017-01-29                        # ISO date\n  archive_url: null                             # filled by post-merge-archive workflow\n  last_checked: null                            # filled by weekly-health workflow\n  fingerprint: null                             # content fingerprint, filled by health\n  status: active                                # active|dead|archived-only|quarantined\n```\n\nOptional fields:\n\n- `raw_rest` is the README description text that follows the title link\n  (the generator emits `- [Title](url) - {raw_rest}.`). It is **public-facing,\n  third-party-readable** content; treat it like user-facing copy.\n  - DO include: a one-sentence factual description of what the resource is,\n    optionally followed by a `Written by [Author](url)` byline.\n  - DO NOT include: references to this project, issue/PR numbers, phrases\n    like \"originally proposed by\", or any internal metadata. Git history\n    already preserves attribution; a third-party reader of the README must\n    not infer that the entry has any historical relationship to this repo.\n  - Leave migrator-written values as-is; only rewrite when the original is\n    wrong or stale.\n- `archive_opt_out: true` skips Wayback Machine archiving for this entry.\n  Set this only when the original author has explicitly asked not to be\n  archived (paywalled content, takedown requests). Defaults to false.\n- `languages: [universal]` is a wildcard meaning \"render this entry in\n  every language README\". Use sparingly; prefer explicit `[en, zh, jp]` when\n  you know the audience exactly.\n\n## Anchor preservation\n\nExternal sites and the ToC both link to `#some-anchor` targets. Renaming or\nremoving an existing anchor silently breaks those links. The CI guard\n`scripts/verify_anchors.py` compares the working tree's anchor set against\nmaster and fails the build if any baseline anchor is missing. Never rename\nan existing anchor; always add new ones for new sections.\n\n## Language policy\n\nProject-authored content is English. Exceptions, where multi-language is\nintrinsic to the artifact:\n\n- `README-zh.md`, `README-jp.md` — translated versions of `README.md`.\n- `data/categories.yml` `title_zh` / `title_jp` overrides, if any are added\n  later (currently the section titles are uniform across languages).\n- `data/entries/*.yml` `title` and `notes` fields preserve the resource's\n  original language (e.g. a Chinese article keeps its Chinese title).\n- `skills/awesome-web-security/SKILL.md` `when_to_use` trigger phrases use\n  multi-lingual keywords so the skill activates on non-English prompts.\n  The SKILL.md body itself remains English.\n- `scripts/ci/templates/comment.{en,zh,jp}.md` — the auto-review bot replies\n  in the contributor's language when detected with high confidence, falling\n  back to English otherwise. Dimension names (`Reachability`, `Format`,\n  `Depth`, `Fit`, `Dedup`) stay in English; they are keys into RUBRIC.md.\n\nEverything else — code, comments, schema field names, templates, CI output,\nlabels, commit messages — is English.\n\n## Multi-language entry routing\n\nA single entry can appear in multiple READMEs. The `languages` field\ncontrols where it shows up:\n\n- New entry, no language hint from the contributor → put it in `[en]` only;\n  ask the contributor if they want it in `zh` / `jp` too.\n- Locale-specific resource (Chinese-language article, Japanese-only forum) →\n  use `[zh]` / `[jp]` only.\n- Truly cross-cultural canonical resource → `[en, zh, jp]` or `[universal]`.\n- Do not force-translate or force-mirror an entry across languages to\n  \"match\" the structure. Each README is allowed to have entries the others\n  don't.\n\n## Handling new resource requests\n\nTwo kinds of inbound requests, both ported into the YAML data model\nthe same way the 2026 backlog was cleared:\n\n**Issue Form submission** (`.github/ISSUE_TEMPLATE/propose-resource.yml`)\n— the contributor filed an issue, not a PR. Port it directly: add the\nentry to `data/entries/<category>.yml`, run `python3\nscripts/generate.py` and the verify scripts, commit to `master` with\n`Closes #<n>` and a `Co-authored-by:` trailer crediting the submitter.\nThey never had a branch, so the co-author trailer is their credit.\n\n**Direct pull request** (contributor edited `README.md` or the YAML\ndirectly) — port on *their* branch so their PR merges with full\nattribution. See CONTRIBUTING.md \"Maintainer notes\" for the six-step\nPath B playbook. Never route a direct PR through Copilot: Copilot\nopens its own PR and closes the contributor's unmerged, destroying\ntheir merged-PR credit.\n\n### Copilot as async fallback\n\nCopilot is the fallback for **Issue Form submissions only**, when the\nmaintainer is unavailable for an extended period and the queue needs\nto keep moving. It is not the standard workflow — the manual port\nabove is. The maintainer still reviews the resulting Copilot PR before\nmerge; Copilot saves the typing, not the judgment. Prompt shape:\n\n```\n@copilot please port this resource into the new YAML data model.\n\nAdd it to `data/entries/<TARGET>.yml` with:\n- url, title, author.name, author.url (from the issue fields)\n- type: <article|tool|cheatsheet|video|book|community|payload-list>\n- difficulty: <intro|intermediate|advanced>\n- languages: [en, zh, jp] unless the resource is locale-specific\n  (then [zh] or [jp]); never [universal] as the sole value without\n  confirming with the maintainer\n- status: active\n\nSet `raw_rest` to a one-sentence factual description of the resource\nitself, optionally followed by a `Written by [Author](url)` byline. Do\nNOT mention this project, the issue number, the PR number, or any\ninternal metadata in `raw_rest`.\n\nEnd the PR body with both:\n  Closes #<n>\n  Co-authored-by: <issue-author> <ID+login@users.noreply.github.com>\n\nRun `python3 scripts/generate.py` and `python3 scripts/verify_schema.py`\nbefore opening the PR.\n```\n\nAdjust `<TARGET>`, `type`, `difficulty`, `languages`, the issue\nnumber, and the co-author identity per case.\n\n## Things not to do\n\n- Do not edit the generated `README*.md` files directly.\n- Do not rename or remove existing anchors in `data/categories.yml`.\n- Do not introduce HTML tags in `data/templates/*.md` beyond `a, b, br, p,\n  img` (the project's markdownlint config).\n- Do not bulk-reorder existing entries — the generator sorts by\n  `date_added`, then by title. To move an entry up, change its\n  `date_added`.\n- Do not commit `data/index.json` edits by hand. It is fully regenerated by\n  `scripts/generate.py`.\n- Do not edit `CONTRIBUTING.md`, `code-of-conduct.md`, or workflow files\n  unless the user explicitly asks.\n- Do not create commits or push unless explicitly asked.\n\n## CI behavior\n\nOn every PR touching `data/**` or generator scripts, the workflow:\n\n1. Runs `verify_schema.py` and `verify_anchors.py`.\n2. Re-runs `generate.py` and warns if the working tree diverges from the\n   generated output (contributor forgot to regenerate).\n3. Invokes the auto-review bot, which grades each new entry against\n   RUBRIC.md using GitHub Models, posts a single structured comment, and\n   applies advisory labels. LLM failure falls back to deterministic\n   reachability + format checks; labelled `auto/review-failed`.\n\nThe bot never auto-merges and never auto-rejects.\n\n## When in doubt\n\nMatch the spirit of CONTRIBUTING.md and RUBRIC.md. Ask the user if a change\ncrosses into territory not described here (new language version, new entry\nschema field, new section taxonomy).\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nGuidance for Claude Code working in this repository.\n\n## What this repo is\n\nA curated knowledge base of web security learning resources. Data lives in\n`data/categories.yml` and `data/entries/*.yml`; the three language READMEs\n(`README.md`, `README-zh.md`, `README-jp.md`) and `data/index.json` are\n**generated** from that data by `scripts/generate.py`. The same data backs a\nClaude Skill at `skills/awesome-web-security/` so AI agents can query the\nlist at runtime.\n\nNo build, no test suite, no application runtime. Every change is either\nYAML data, Python tooling, or Markdown docs.\n\n## Files of note\n\n- `data/categories.yml` — section tree, anchors, ToC. Edit carefully.\n- `data/entries/*.yml` — one file per section. Source of truth for entries.\n- `data/templates/preamble.md` / `postamble.md` — verbatim header/footer in\n  the generated READMEs.\n- `scripts/generate.py` — YAML → README.md / README-zh.md / README-jp.md /\n  data/index.json.\n- `scripts/migrate.py` — one-shot importer that originally produced the YAML\n  from the old hand-edited READMEs. Kept for reference; do not re-run on a\n  populated `data/`.\n- `scripts/verify_schema.py` — entry schema validation; CI gate.\n- `scripts/verify_anchors.py` — ensures no anchor used by external links is\n  removed; CI gate.\n- `scripts/verify_skill.sh` — lints `marketplace.json` and `SKILL.md`.\n- `scripts/ci/pr_review.py` — auto-review bot. Default LLM is\n  `openai/gpt-4.1-mini` via GitHub Models; override via the `REVIEW_MODEL`\n  env var in the workflow. Contributor language is detected\n  deterministically (Han / Kana regex on PR body) and passed to the LLM\n  as a directive; the LLM never owns language detection.\n- `scripts/ci/templates/comment.{en,zh,jp}.md` — localized review comments.\n- `.github/workflows/pr-review.yml` — runs the bot on every PR.\n- `.github/workflows/pr-review-backlog.yml` — dry-run over open PRs (manual,\n  workflow_dispatch). Stashes trusted scripts to `/tmp/awsec-trusted/` before\n  iterating PR refs, so `pr_review.py` always runs from the base branch even\n  when an attacker-controlled PR is checked out.\n- `.github/workflows/health-link-check.yml` — daily lychee scan over the\n  generated READMEs and `data/index.json`; surfaces broken links via a single\n  rolling issue labelled `health/link-check`. Replaces the previous\n  `validate.yml`.\n- `.github/workflows/post-merge-archive.yml` — after merges that touch\n  `data/entries/**`, submits eligible entries (active, no `archive_url` yet,\n  not opted out) to Wayback Machine and commits the resulting `archive_url`\n  back to the YAML with `[skip ci]`. Driven by `scripts/ci/archive.py`.\n- `.github/ISSUE_TEMPLATE/propose-resource.yml` — GitHub Form for proposals.\n- `.github/PULL_REQUEST_TEMPLATE.md` — self-checklist mirroring RUBRIC.md.\n- `.claude-plugin/marketplace.json` — declares the Claude plugin / Skill\n  package distributed via this repo.\n- `skills/awesome-web-security/SKILL.md` — the Skill body. Lives here so the\n  same repo serves humans and AI agents.\n- `RUBRIC.md` — the five-dimension scoring rubric the bot applies; also the\n  contributor self-check reference.\n- `CONTRIBUTING.md` — contributor flow. Treat as authoritative for PR\n  procedure; do not duplicate its contents here.\n\n## Editing rules\n\n- **Never edit `README.md`, `README-zh.md`, or `README-jp.md` directly.**\n  They are regenerated from `data/` by `scripts/generate.py`. Edits will be\n  blown away on the next regeneration.\n- To add or modify an entry, edit `data/entries/<category>.yml`.\n- To add a new category, edit `data/categories.yml` first, then add a new\n  `data/entries/<category-key>.yml`. Run `scripts/verify_anchors.py`\n  afterwards to confirm no external-facing anchor was lost.\n- After any data change, run `python3 scripts/generate.py` to refresh the\n  generated files locally before committing. CI will reject divergence.\n\n## Entry schema\n\n```yaml\n- id: xss-google-app-security                   # kebab-case, unique\n  url: https://www.google.com/...               # required, https preferred\n  title: Cross-Site Scripting – Application Security – Google\n  author:\n    name: Google                                # required if author exists\n    url: https://www.google.com/                # optional\n  category: xss                                 # must exist in categories.yml\n  type: article                                 # article|tool|cheatsheet|video|book|community|payload-list\n  languages: [en]                               # subset of: en|zh|jp|tr|universal\n  difficulty: intro                             # intro|intermediate|advanced\n  date_added: 2017-01-29                        # ISO date\n  archive_url: null                             # filled by post-merge-archive workflow\n  last_checked: null                            # filled by weekly-health workflow\n  fingerprint: null                             # content fingerprint, filled by health\n  status: active                                # active|dead|archived-only|quarantined\n```\n\nOptional fields:\n\n- `raw_rest` is the README description text that follows the title link\n  (the generator emits `- [Title](url) - {raw_rest}.`). It is **public-facing,\n  third-party-readable** content; treat it like user-facing copy.\n  - DO include: a one-sentence factual description of what the resource is,\n    optionally followed by a `Written by [Author](url)` byline.\n  - DO NOT include: references to this project, issue/PR numbers, phrases\n    like \"originally proposed by\", or any internal metadata. Git history\n    already preserves attribution; a third-party reader of the README must\n    not infer that the entry has any historical relationship to this repo.\n  - Leave migrator-written values as-is; only rewrite when the original is\n    wrong or stale.\n- `archive_opt_out: true` skips Wayback Machine archiving for this entry.\n  Set this only when the original author has explicitly asked not to be\n  archived (paywalled content, takedown requests). Defaults to false.\n- `languages: [universal]` is a wildcard meaning \"render this entry in\n  every language README\". Use sparingly; prefer explicit `[en, zh, jp]` when\n  you know the audience exactly.\n\n## Anchor preservation\n\nExternal sites and the ToC both link to `#some-anchor` targets. Renaming or\nremoving an existing anchor silently breaks those links. The CI guard\n`scripts/verify_anchors.py` compares the working tree's anchor set against\nmaster and fails the build if any baseline anchor is missing. Never rename\nan existing anchor; always add new ones for new sections.\n\n## Language policy\n\nProject-authored content is English. Exceptions, where multi-language is\nintrinsic to the artifact:\n\n- `README-zh.md`, `README-jp.md` — translated versions of `README.md`.\n- `data/categories.yml` `title_zh` / `title_jp` overrides, if any are added\n  later (currently the section titles are uniform across languages).\n- `data/entries/*.yml` `title` and `notes` fields preserve the resource's\n  original language (e.g. a Chinese article keeps its Chinese title).\n- `skills/awesome-web-security/SKILL.md` `when_to_use` trigger phrases use\n  multi-lingual keywords so the skill activates on non-English prompts.\n  The SKILL.md body itself remains English.\n- `scripts/ci/templates/comment.{en,zh,jp}.md` — the auto-review bot replies\n  in the contributor's language when detected with high confidence, falling\n  back to English otherwise. Dimension names (`Reachability`, `Format`,\n  `Depth`, `Fit`, `Dedup`) stay in English; they are keys into RUBRIC.md.\n\nEverything else — code, comments, schema field names, templates, CI output,\nlabels, commit messages — is English.\n\n## Multi-language entry routing\n\nA single entry can appear in multiple READMEs. The `languages` field\ncontrols where it shows up:\n\n- New entry, no language hint from the contributor → put it in `[en]` only;\n  ask the contributor if they want it in `zh` / `jp` too.\n- Locale-specific resource (Chinese-language article, Japanese-only forum) →\n  use `[zh]` / `[jp]` only.\n- Truly cross-cultural canonical resource → `[en, zh, jp]` or `[universal]`.\n- Do not force-translate or force-mirror an entry across languages to\n  \"match\" the structure. Each README is allowed to have entries the others\n  don't.\n\n## Handling new resource requests\n\nTwo kinds of inbound requests, both ported into the YAML data model\nthe same way the 2026 backlog was cleared:\n\n**Issue Form submission** (`.github/ISSUE_TEMPLATE/propose-resource.yml`)\n— the contributor filed an issue, not a PR. Port it directly: add the\nentry to `data/entries/<category>.yml`, run `python3\nscripts/generate.py` and the verify scripts, commit to `master` with\n`Closes #<n>` and a `Co-authored-by:` trailer crediting the submitter.\nThey never had a branch, so the co-author trailer is their credit.\n\n**Direct pull request** (contributor edited `README.md` or the YAML\ndirectly) — port on *their* branch so their PR merges with full\nattribution. See CONTRIBUTING.md \"Maintainer notes\" for the six-step\nPath B playbook. Never route a direct PR through Copilot: Copilot\nopens its own PR and closes the contributor's unmerged, destroying\ntheir merged-PR credit.\n\n### Copilot as async fallback\n\nCopilot is the fallback for **Issue Form submissions only**, when the\nmaintainer is unavailable for an extended period and the queue needs\nto keep moving. It is not the standard workflow — the manual port\nabove is. The maintainer still reviews the resulting Copilot PR before\nmerge; Copilot saves the typing, not the judgment. Prompt shape:\n\n```\n@copilot please port this resource into the new YAML data model.\n\nAdd it to `data/entries/<TARGET>.yml` with:\n- url, title, author.name, author.url (from the issue fields)\n- type: <article|tool|cheatsheet|video|book|community|payload-list>\n- difficulty: <intro|intermediate|advanced>\n- languages: [en, zh, jp] unless the resource is locale-specific\n  (then [zh] or [jp]); never [universal] as the sole value without\n  confirming with the maintainer\n- status: active\n\nSet `raw_rest` to a one-sentence factual description of the resource\nitself, optionally followed by a `Written by [Author](url)` byline. Do\nNOT mention this project, the issue number, the PR number, or any\ninternal metadata in `raw_rest`.\n\nEnd the PR body with both:\n  Closes #<n>\n  Co-authored-by: <issue-author> <ID+login@users.noreply.github.com>\n\nRun `python3 scripts/generate.py` and `python3 scripts/verify_schema.py`\nbefore opening the PR.\n```\n\nAdjust `<TARGET>`, `type`, `difficulty`, `languages`, the issue\nnumber, and the co-author identity per case.\n\n## Things not to do\n\n- Do not edit the generated `README*.md` files directly.\n- Do not rename or remove existing anchors in `data/categories.yml`.\n- Do not introduce HTML tags in `data/templates/*.md` beyond `a, b, br, p,\n  img` (the project's markdownlint config).\n- Do not bulk-reorder existing entries — the generator sorts by\n  `date_added`, then by title. To move an entry up, change its\n  `date_added`.\n- Do not commit `data/index.json` edits by hand. It is fully regenerated by\n  `scripts/generate.py`.\n- Do not edit `CONTRIBUTING.md`, `code-of-conduct.md`, or workflow files\n  unless the user explicitly asks.\n- Do not create commits or push unless explicitly asked.\n\n## CI behavior\n\nOn every PR touching `data/**` or generator scripts, the workflow:\n\n1. Runs `verify_schema.py` and `verify_anchors.py`.\n2. Re-runs `generate.py` and warns if the working tree diverges from the\n   generated output (contributor forgot to regenerate).\n3. Invokes the auto-review bot, which grades each new entry against\n   RUBRIC.md using GitHub Models, posts a single structured comment, and\n   applies advisory labels. LLM failure falls back to deterministic\n   reachability + format checks; labelled `auto/review-failed`.\n\nThe bot never auto-merges and never auto-rejects.\n\n## When in doubt\n\nMatch the spirit of CONTRIBUTING.md and RUBRIC.md. Ask the user if a change\ncrosses into territory not described here (new language version, new entry\nschema field, new section taxonomy).\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nGuidance for Claude Code working in this repository.\n\n## What this repo is\n\nA curated knowledge base of web security learning resources. Data lives in\n`data/categories.yml` and `data/entries/*.yml`; the three language READMEs\n(`README.md`, `README-zh.md`, `README-jp.md`) and `data/index.json` are\n**generated** from that data by `scripts/generate.py`. The same data backs a\nClaude Skill at `skills/awesome-web-security/` so AI agents can query the\nlist at runtime.\n\nNo build, no test suite, no application runtime. Every change is either\nYAML data, Python tooling, or Markdown docs.\n\n## Files of note\n\n- `data/categories.yml` — section tree, anchors, ToC. Edit carefully.\n- `data/entries/*.yml` — one file per section. Source of truth for entries.\n- `data/templates/preamble.md` / `postamble.md` — verbatim header/footer in\n  the generated READMEs.\n- `scripts/generate.py` — YAML → README.md / README-zh.md / README-jp.md /\n  data/index.json.\n- `scripts/migrate.py` — one-shot importer that originally produced the YAML\n  from the old hand-edited READMEs. Kept for reference; do not re-run on a\n  populated `data/`.\n- `scripts/verify_schema.py` — entry schema validation; CI gate.\n- `scripts/verify_anchors.py` — ensures no anchor used by external links is\n  removed; CI gate.\n- `scripts/verify_skill.sh` — lints `marketplace.json` and `SKILL.md`.\n- `scripts/ci/pr_review.py` — auto-review bot. Default LLM is\n  `openai/gpt-4.1-mini` via GitHub Models; override via the `REVIEW_MODEL`\n  env var in the workflow. Contributor language is detected\n  deterministically (Han / Kana regex on PR body) and passed to the LLM\n  as a directive; the LLM never owns language detection.\n- `scripts/ci/templates/comment.{en,zh,jp}.md` — localized review comments.\n- `.github/workflows/pr-review.yml` — runs the bot on every PR.\n- `.github/workflows/pr-review-backlog.yml` — dry-run over open PRs (manual,\n  workflow_dispatch). Stashes trusted scripts to `/tmp/awsec-trusted/` before\n  iterating PR refs, so `pr_review.py` always runs from the base branch even\n  when an attacker-controlled PR is checked out.\n- `.github/workflows/health-link-check.yml` — daily lychee scan over the\n  generated READMEs and `data/index.json`; surfaces broken links via a single\n  rolling issue labelled `health/link-check`. Replaces the previous\n  `validate.yml`.\n- `.github/workflows/post-merge-archive.yml` — after merges that touch\n  `data/entries/**`, submits eligible entries (active, no `archive_url` yet,\n  not opted out) to Wayback Machine and commits the resulting `archive_url`\n  back to the YAML with `[skip ci]`. Driven by `scripts/ci/archive.py`.\n- `.github/ISSUE_TEMPLATE/propose-resource.yml` — GitHub Form for proposals.\n- `.github/PULL_REQUEST_TEMPLATE.md` — self-checklist mirroring RUBRIC.md.\n- `.claude-plugin/marketplace.json` — declares the Claude plugin / Skill\n  package distributed via this repo.\n- `skills/awesome-web-security/SKILL.md` — the Skill body. Lives here so the\n  same repo serves humans and AI agents.\n- `RUBRIC.md` — the five-dimension scoring rubric the bot applies; also the\n  contributor self-check reference.\n- `CONTRIBUTING.md` — contributor flow. Treat as authoritative for PR\n  procedure; do not duplicate its contents here.\n\n## Editing rules\n\n- **Never edit `README.md`, `README-zh.md`, or `README-jp.md` directly.**\n  They are regenerated from `data/` by `scripts/generate.py`. Edits will be\n  blown away on the next regeneration.\n- To add or modify an entry, edit `data/entries/<category>.yml`.\n- To add a new category, edit `data/categories.yml` first, then add a new\n  `data/entries/<category-key>.yml`. Run `scripts/verify_anchors.py`\n  afterwards to confirm no external-facing anchor was lost.\n- After any data change, run `python3 scripts/generate.py` to refresh the\n  generated files locally before committing. CI will reject divergence.\n\n## Entry schema\n\n```yaml\n- id: xss-google-app-security                   # kebab-case, unique\n  url: https://www.google.com/...               # required, https preferred\n  title: Cross-Site Scripting – Application Security – Google\n  author:\n    name: Google                                # required if author exists\n    url: https://www.google.com/                # optional\n  category: xss                                 # must exist in categories.yml\n  type: article                                 # article|tool|cheatsheet|video|book|community|payload-list\n  languages: [en]                               # subset of: en|zh|jp|tr|universal\n  difficulty: intro                             # intro|intermediate|advanced\n  date_added: 2017-01-29                        # ISO date\n  archive_url: null                             # filled by post-merge-archive workflow\n  last_checked: null                            # filled by weekly-health workflow\n  fingerprint: null                             # content fingerprint, filled by health\n  status: active                                # active|dead|archived-only|quarantined\n```\n\nOptional fields:\n\n- `raw_rest` is the README description text that follows the title link\n  (the generator emits `- [Title](url) - {raw_rest}.`). It is **public-facing,\n  third-party-readable** content; treat it like user-facing copy.\n  - DO include: a one-sentence factual description of what the resource is,\n    optionally followed by a `Written by [Author](url)` byline.\n  - DO NOT include: references to this project, issue/PR numbers, phrases\n    like \"originally proposed by\", or any internal metadata. Git history\n    already preserves attribution; a third-party reader of the README must\n    not infer that the entry has any historical relationship to this repo.\n  - Leave migrator-written values as-is; only rewrite when the original is\n    wrong or stale.\n- `archive_opt_out: true` skips Wayback Machine archiving for this entry.\n  Set this only when the original author has explicitly asked not to be\n  archived (paywalled content, takedown requests). Defaults to false.\n- `languages: [universal]` is a wildcard meaning \"render this entry in\n  every language README\". Use sparingly; prefer explicit `[en, zh, jp]` when\n  you know the audience exactly.\n\n## Anchor preservation\n\nExternal sites and the ToC both link to `#some-anchor` targets. Renaming or\nremoving an existing anchor silently breaks those links. The CI guard\n`scripts/verify_anchors.py` compares the working tree's anchor set against\nmaster and fails the build if any baseline anchor is missing. Never rename\nan existing anchor; always add new ones for new sections.\n\n## Language policy\n\nProject-authored content is English. Exceptions, where multi-language is\nintrinsic to the artifact:\n\n- `README-zh.md`, `README-jp.md` — translated versions of `README.md`.\n- `data/categories.yml` `title_zh` / `title_jp` overrides, if any are added\n  later (currently the section titles are uniform across languages).\n- `data/entries/*.yml` `title` and `notes` fields preserve the resource's\n  original language (e.g. a Chinese article keeps its Chinese title).\n- `skills/awesome-web-security/SKILL.md` `when_to_use` trigger phrases use\n  multi-lingual keywords so the skill activates on non-English prompts.\n  The SKILL.md body itself remains English.\n- `scripts/ci/templates/comment.{en,zh,jp}.md` — the auto-review bot replies\n  in the contributor's language when detected with high confidence, falling\n  back to English otherwise. Dimension names (`Reachability`, `Format`,\n  `Depth`, `Fit`, `Dedup`) stay in English; they are keys into RUBRIC.md.\n\nEverything else — code, comments, schema field names, templates, CI output,\nlabels, commit messages — is English.\n\n## Multi-language entry routing\n\nA single entry can appear in multiple READMEs. The `languages` field\ncontrols where it shows up:\n\n- New entry, no language hint from the contributor → put it in `[en]` only;\n  ask the contributor if they want it in `zh` / `jp` too.\n- Locale-specific resource (Chinese-language article, Japanese-only forum) →\n  use `[zh]` / `[jp]` only.\n- Truly cross-cultural canonical resource → `[en, zh, jp]` or `[universal]`.\n- Do not force-translate or force-mirror an entry across languages to\n  \"match\" the structure. Each README is allowed to have entries the others\n  don't.\n\n## Handling new resource requests\n\nTwo kinds of inbound requests, both ported into the YAML data model\nthe same way the 2026 backlog was cleared:\n\n**Issue Form submission** (`.github/ISSUE_TEMPLATE/propose-resource.yml`)\n— the contributor filed an issue, not a PR. Port it directly: add the\nentry to `data/entries/<category>.yml`, run `python3\nscripts/generate.py` and the verify scripts, commit to `master` with\n`Closes #<n>` and a `Co-authored-by:` trailer crediting the submitter.\nThey never had a branch, so the co-author trailer is their credit.\n\n**Direct pull request** (contributor edited `README.md` or the YAML\ndirectly) — port on *their* branch so their PR merges with full\nattribution. See CONTRIBUTING.md \"Maintainer notes\" for the six-step\nPath B playbook. Never route a direct PR through Copilot: Copilot\nopens its own PR and closes the contributor's unmerged, destroying\ntheir merged-PR credit.\n\n### Copilot as async fallback\n\nCopilot is the fallback for **Issue Form submissions only**, when the\nmaintainer is unavailable for an extended period and the queue needs\nto keep moving. It is not the standard workflow — the manual port\nabove is. The maintainer still reviews the resulting Copilot PR before\nmerge; Copilot saves the typing, not the judgment. Prompt shape:\n\n```\n@copilot please port this resource into the new YAML data model.\n\nAdd it to `data/entries/<TARGET>.yml` with:\n- url, title, author.name, author.url (from the issue fields)\n- type: <article|tool|cheatsheet|video|book|community|payload-list>\n- difficulty: <intro|intermediate|advanced>\n- languages: [en, zh, jp] unless the resource is locale-specific\n  (then [zh] or [jp]); never [universal] as the sole value without\n  confirming with the maintainer\n- status: active\n\nSet `raw_rest` to a one-sentence factual description of the resource\nitself, optionally followed by a `Written by [Author](url)` byline. Do\nNOT mention this project, the issue number, the PR number, or any\ninternal metadata in `raw_rest`.\n\nEnd the PR body with both:\n  Closes #<n>\n  Co-authored-by: <issue-author> <ID+login@users.noreply.github.com>\n\nRun `python3 scripts/generate.py` and `python3 scripts/verify_schema.py`\nbefore opening the PR.\n```\n\nAdjust `<TARGET>`, `type`, `difficulty`, `languages`, the issue\nnumber, and the co-author identity per case.\n\n## Things not to do\n\n- Do not edit the generated `README*.md` files directly.\n- Do not rename or remove existing anchors in `data/categories.yml`.\n- Do not introduce HTML tags in `data/templates/*.md` beyond `a, b, br, p,\n  img` (the project's markdownlint config).\n- Do not bulk-reorder existing entries — the generator sorts by\n  `date_added`, then by title. To move an entry up, change its\n  `date_added`.\n- Do not commit `data/index.json` edits by hand. It is fully regenerated by\n  `scripts/generate.py`.\n- Do not edit `CONTRIBUTING.md`, `code-of-conduct.md`, or workflow files\n  unless the user explicitly asks.\n- Do not create commits or push unless explicitly asked.\n\n## CI behavior\n\nOn every PR touching `data/**` or generator scripts, the workflow:\n\n1. Runs `verify_schema.py` and `verify_anchors.py`.\n2. Re-runs `generate.py` and warns if the working tree diverges from the\n   generated output (contributor forgot to regenerate).\n3. Invokes the auto-review bot, which grades each new entry against\n   RUBRIC.md using GitHub Models, posts a single structured comment, and\n   applies advisory labels. LLM failure falls back to deterministic\n   reachability + format checks; labelled `auto/review-failed`.\n\nThe bot never auto-merges and never auto-rejects.\n\n## When in doubt\n\nMatch the spirit of CONTRIBUTING.md and RUBRIC.md. Ask the user if a change\ncrosses into territory not described here (new language version, new entry\nschema field, new section taxonomy).\n","category":"root","tokens":3009}]}