{
 "schema_version": 5,
 "concerns": [
  "correctness",
  "security",
  "performance",
  "reliability",
  "compatibility",
  "testing",
  "maintainability",
  "accessibility",
  "usability",
  "observability",
  "process"
 ],
 "levels": [
  "change",
  "function",
  "module",
  "service",
  "system",
  "codebase",
  "production",
  "incident"
 ],
 "cards": [
  {
   "id": "code-a11y-check-in-ci",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "testing"
   ],
   "topics": [
    "frontend",
    "ci"
   ],
   "rule": "Run an automated accessibility check, such as axe on rendered pages, in the automated tests, and fail the test on a violation.",
   "url": "https://goodcodereview.com/codebase#code-a11y-check-in-ci"
  },
  {
   "id": "code-adr",
   "level": "codebase",
   "severity": "discuss",
   "concerns": [
    "maintainability",
    "process"
   ],
   "topics": [
    "documentation",
    "decisions"
   ],
   "rule": "Keep a short written record for each significant design choice (datastore, framework, deviation from a pattern) that states the context, the decision, and its consequences.",
   "url": "https://goodcodereview.com/codebase#code-adr"
  },
  {
   "id": "code-build-hermetic",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "process"
   ],
   "topics": [
    "build",
    "reproducibility"
   ],
   "rule": "Build from declared inputs only, so that the same source revision gives the same artifact.",
   "url": "https://goodcodereview.com/codebase#code-build-hermetic"
  },
  {
   "id": "code-ci-gates",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "process"
   ],
   "topics": [
    "ci",
    "quality-gates"
   ],
   "rule": "Require review and passing build, tests, lint, and type checks on the default branch before merge, and leave nothing mechanical to reviewer vigilance.",
   "url": "https://goodcodereview.com/codebase#code-ci-gates"
  },
  {
   "id": "code-consistency-drift",
   "level": "codebase",
   "severity": "discuss",
   "concerns": [
    "correctness",
    "maintainability"
   ],
   "topics": [
    "consistency",
    "architecture"
   ],
   "rule": "For each recurring concern (errors, config, HTTP clients, logging), make one pattern the standard instead of leaving several as equal peers.",
   "url": "https://goodcodereview.com/codebase#code-consistency-drift"
  },
  {
   "id": "code-dead-code",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "cleanup",
    "deletion"
   ],
   "rule": "Delete unreferenced functions and variables, and the branches of expired feature flags.",
   "url": "https://goodcodereview.com/codebase#code-dead-code"
  },
  {
   "id": "code-dependency-licence-sbom",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "supply-chain",
    "licences",
    "sbom"
   ],
   "rule": "Generate an SBOM, and scan dependencies for known vulnerabilities on every change or on a schedule. Each ask is judged separately: name which one failed on the FAIL line.",
   "url": "https://goodcodereview.com/codebase#code-dependency-licence-sbom"
  },
  {
   "id": "code-dependency-pinning",
   "level": "codebase",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "supply-chain",
    "dependencies"
   ],
   "rule": "Commit a lockfile with hashes and install from it in CI.",
   "url": "https://goodcodereview.com/codebase#code-dependency-pinning"
  },
  {
   "id": "code-docs-refs-resolve",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "docs",
    "ci"
   ],
   "rule": "Run a link check in CI over the docs, so that every relative link and anchor they cite resolves.",
   "url": "https://goodcodereview.com/codebase#code-docs-refs-resolve"
  },
  {
   "id": "code-file-lines-ceiling",
   "level": "codebase",
   "severity": "discuss",
   "concerns": [
    "maintainability",
    "process"
   ],
   "topics": [
    "structure",
    "size"
   ],
   "rule": "Set a file-length limit in the linter (Pylint and SonarSource default to 1,000 lines), keep hand-written files under it unless a listed exception says otherwise, and split larger files by knowledge owned, not by execution order.",
   "url": "https://goodcodereview.com/codebase#code-file-lines-ceiling"
  },
  {
   "id": "code-flaky-test-quarantine",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "process"
   ],
   "topics": [
    "ci",
    "flaky-tests"
   ],
   "rule": "Report every test that passes only on retry, move it to a quarantine with a named owner and a ticket, and return it to the merge gate only after it passes many reruns.",
   "url": "https://goodcodereview.com/codebase#code-flaky-test-quarantine"
  },
  {
   "id": "code-perf-budget-in-ci",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "process"
   ],
   "topics": [
    "ci"
   ],
   "rule": "Write the performance budget down as a CI check that fails the build when it is exceeded.",
   "url": "https://goodcodereview.com/codebase#code-perf-budget-in-ci"
  },
  {
   "id": "code-release-gated-on-ci",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "reliability",
    "process"
   ],
   "topics": [
    "ci",
    "release"
   ],
   "rule": "Make a release or publish job depend on the checks passing for the tagged commit, never on the tag alone.",
   "url": "https://goodcodereview.com/codebase#code-release-gated-on-ci"
  },
  {
   "id": "code-rule-has-enforcer",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "tooling",
    "conventions"
   ],
   "rule": "Back each written repo rule that a type, lint or CI check could enforce with that check, not with a line in an instruction file or a repeated review comment.",
   "url": "https://goodcodereview.com/codebase#code-rule-has-enforcer"
  },
  {
   "id": "code-scoped-validation-loop",
   "level": "codebase",
   "severity": "discuss",
   "concerns": [
    "testing",
    "process"
   ],
   "topics": [
    "onboarding"
   ],
   "rule": "Document a command that checks one package or path, with readable output, so a small change does not need the full-repo run.",
   "url": "https://goodcodereview.com/codebase#code-scoped-validation-loop"
  },
  {
   "id": "code-secret-scan",
   "level": "codebase",
   "severity": "block",
   "concerns": [
    "security",
    "process"
   ],
   "topics": [
    "secrets",
    "ci"
   ],
   "rule": "Scan for committed credentials, and treat any hit as leaked: revoke and replace it first. With no scanner present and no secret found, the FAIL is the missing control; evidence is \"absent in <paths>\". A platform scanner (GitHub secret scanning with push protection, GitLab secret detection) counts when it is enabled on the repo and covers history.",
   "url": "https://goodcodereview.com/codebase#code-secret-scan"
  },
  {
   "id": "code-test-fixtures-built-once",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "performance"
   ],
   "topics": [
    "ci",
    "fixtures"
   ],
   "rule": "Build an expensive fixture once per test run, and reset state between tests with a rollback or a truncate, never a rebuild.",
   "url": "https://goodcodereview.com/codebase#code-test-fixtures-built-once"
  },
  {
   "id": "code-test-selection-on-pr",
   "level": "codebase",
   "severity": "discuss",
   "concerns": [
    "testing",
    "performance",
    "process"
   ],
   "topics": [
    "ci"
   ],
   "rule": "When the full suite is slower than the pull-request feedback target, run only the tests the change affects on the pull request, and run the full suite before deploy or on a schedule.",
   "url": "https://goodcodereview.com/codebase#code-test-selection-on-pr"
  },
  {
   "id": "code-vuln-remediation-window",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "security",
    "process"
   ],
   "topics": [
    "supply-chain"
   ],
   "rule": "Write down how long a known-vulnerable dependency may stay unfixed and fix or upgrade it inside that window.",
   "url": "https://goodcodereview.com/codebase#code-vuln-remediation-window"
  },
  {
   "id": "code-workflow-supply-chain",
   "level": "codebase",
   "severity": "block",
   "concerns": [
    "security",
    "process"
   ],
   "topics": [
    "supply-chain",
    "ci"
   ],
   "rule": "Pin every CI action to a full commit SHA, and keep code from an unreviewed change out of any job that holds secrets or can deploy.",
   "url": "https://goodcodereview.com/codebase#code-workflow-supply-chain"
  },
  {
   "id": "code-workload-identity",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "supply-chain",
    "ci",
    "credentials"
   ],
   "rule": "Exchange the platform's OIDC token for a short-lived cloud credential, and pin the trust policy to the workload.",
   "url": "https://goodcodereview.com/codebase#code-workload-identity"
  },
  {
   "id": "fn-aria-role-has-state-and-keys",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility"
   ],
   "topics": [
    "frontend",
    "aria",
    "keyboard"
   ],
   "rule": "When a native element cannot do the job, give the custom widget the state attribute and the keys its role promises.",
   "url": "https://goodcodereview.com/function#fn-aria-role-has-state-and-keys"
  },
  {
   "id": "fn-bool-arg-at-callsite",
   "level": "function",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "readability",
    "api"
   ],
   "rule": "Replace a boolean flag argument with an enum, keyword-only argument or two functions.",
   "url": "https://goodcodereview.com/function#fn-bool-arg-at-callsite"
  },
  {
   "id": "fn-bounded-read-fails-at-cap",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "reliability",
    "security"
   ],
   "topics": [
    "io"
   ],
   "rule": "When a size cap is reached, return an error; never hand back the first N bytes as if they were the whole input.",
   "url": "https://goodcodereview.com/function#fn-bounded-read-fails-at-cap"
  },
  {
   "id": "fn-colour-not-sole-cue",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "css"
   ],
   "rule": "Pair every colour that carries meaning with a second cue: text, an icon, a shape, or an underline.",
   "url": "https://goodcodereview.com/function#fn-colour-not-sole-cue"
  },
  {
   "id": "fn-comments-explain-why",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "readability",
    "docs"
   ],
   "rule": "Write comments that give a reason, a constraint, or a trade-off, and never restate what the next line does.",
   "url": "https://goodcodereview.com/function#fn-comments-explain-why"
  },
  {
   "id": "fn-comments-survive-context",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "docs"
   ],
   "rule": "Write comments that remain true without outside context: no \"currently\", \"for now\" or \"see the PR\", and give a TODO the date or event that ends it.",
   "url": "https://goodcodereview.com/function#fn-comments-survive-context"
  },
  {
   "id": "fn-confine-file-path",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "path-traversal",
    "files"
   ],
   "rule": "Resolve the final path and check that it stays inside the intended base directory before using it.",
   "url": "https://goodcodereview.com/function#fn-confine-file-path"
  },
  {
   "id": "fn-constant-time-secret-compare",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "crypto"
   ],
   "rule": "Compare a secret, token or MAC with the platform's constant-time function, never with `==` or `!=`.",
   "url": "https://goodcodereview.com/function#fn-constant-time-secret-compare"
  },
  {
   "id": "fn-csprng-for-secrets",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "crypto"
   ],
   "rule": "Draw every security-relevant random value from the platform CSPRNG.",
   "url": "https://goodcodereview.com/function#fn-csprng-for-secrets"
  },
  {
   "id": "fn-destructive-confirm-or-undo",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "usability"
   ],
   "topics": [
    "frontend",
    "forms"
   ],
   "rule": "Make a destructive action reversible with undo, or ask the user to confirm it before it runs.",
   "url": "https://goodcodereview.com/function#fn-destructive-confirm-or-undo"
  },
  {
   "id": "fn-dialog-focus-managed",
   "level": "function",
   "severity": "block",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "keyboard"
   ],
   "rule": "When a modal opens, move focus into it and keep Tab inside it. Make Escape close it.",
   "url": "https://goodcodereview.com/function#fn-dialog-focus-managed"
  },
  {
   "id": "fn-disclosure-hides-only-secondary",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "usability"
   ],
   "topics": [
    "frontend",
    "html"
   ],
   "rule": "Do not hide a required field or information most users need behind a disclosure that starts closed.",
   "url": "https://goodcodereview.com/function#fn-disclosure-hides-only-secondary"
  },
  {
   "id": "fn-distinct-types-for-ids",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "types"
   ],
   "rule": "Give arguments with different meanings distinct types, so a call that swaps them fails to type-check.",
   "url": "https://goodcodereview.com/function#fn-distinct-types-for-ids"
  },
  {
   "id": "fn-english-identifiers",
   "level": "function",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "naming",
    "readability"
   ],
   "rule": "Write identifiers and comments in English, unless the project policy names another language.",
   "url": "https://goodcodereview.com/function#fn-english-identifiers"
  },
  {
   "id": "fn-error-says-what-and-how",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "usability",
    "accessibility"
   ],
   "topics": [
    "frontend",
    "forms"
   ],
   "rule": "Show each validation error next to its field, in plain words that name what is wrong and how to fix it.",
   "url": "https://goodcodereview.com/function#fn-error-says-what-and-how"
  },
  {
   "id": "fn-fetch-only-needed-data",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "database"
   ],
   "rule": "Filter, count, and aggregate in the query, and select only the columns the code uses.",
   "url": "https://goodcodereview.com/function#fn-fetch-only-needed-data"
  },
  {
   "id": "fn-focus-indicator-visible",
   "level": "function",
   "severity": "block",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "css",
    "keyboard"
   ],
   "rule": "Keep a visible focus indicator on every focusable element. Never set `outline: none` without a replacement.",
   "url": "https://goodcodereview.com/function#fn-focus-indicator-visible"
  },
  {
   "id": "fn-form-control-has-label",
   "level": "function",
   "severity": "block",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "forms"
   ],
   "rule": "Tie every form control to a visible `<label>`, with `for` and a matching `id` or by wrapping it. A placeholder is not a label.",
   "url": "https://goodcodereview.com/function#fn-form-control-has-label"
  },
  {
   "id": "fn-guard-uri-decoding",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "reliability",
    "correctness"
   ],
   "topics": [
    "javascript"
   ],
   "rule": "Wrap `decodeURIComponent` on user input in a `try`/`catch`, or parse with `URLSearchParams`, so that a malformed `%` sequence cannot throw.",
   "url": "https://goodcodereview.com/function#fn-guard-uri-decoding"
  },
  {
   "id": "fn-handle-rejected-promises",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "reliability",
    "correctness"
   ],
   "topics": [
    "javascript"
   ],
   "rule": "Handle the rejection of every promise you start: `await` it inside `try`/`catch`, end the chain with `.catch()`, or return it to a caller that does.",
   "url": "https://goodcodereview.com/function#fn-handle-rejected-promises"
  },
  {
   "id": "fn-header-value-encoding",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "http",
    "injection"
   ],
   "rule": "Set every response header through the framework's header API, never by writing to the connection, and reject or encode CR and LF in any request-derived value.",
   "url": "https://goodcodereview.com/function#fn-header-value-encoding"
  },
  {
   "id": "fn-heading-structure",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "html"
   ],
   "rule": "Mark every heading with a real `<h1>` to `<h6>` element, not a styled `div`, `span`, or `p`.",
   "url": "https://goodcodereview.com/function#fn-heading-structure"
  },
  {
   "id": "fn-img-alt-text",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility"
   ],
   "topics": [
    "frontend",
    "html"
   ],
   "rule": "Give every `<img>` an `alt` attribute: text that serves the image's purpose, or `alt=\"\"` when the image is decorative.",
   "url": "https://goodcodereview.com/function#fn-img-alt-text"
  },
  {
   "id": "fn-independent-work-concurrent",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "correctness"
   ],
   "topics": [
    "concurrency"
   ],
   "rule": "Start independent I/O together and wait for all of it; run calls in sequence only when one needs the result of another.",
   "url": "https://goodcodereview.com/function#fn-independent-work-concurrent"
  },
  {
   "id": "fn-join-dont-concat-in-loop",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "strings"
   ],
   "rule": "Build a string from a loop with a builder or a join, never with repeated `+=`.",
   "url": "https://goodcodereview.com/function#fn-join-dont-concat-in-loop"
  },
  {
   "id": "fn-jwt-verify-pinned",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "jwt"
   ],
   "rule": "Verify the signature against a fixed list of accepted algorithms, and check `iss` and `aud`, before reading any claim.",
   "url": "https://goodcodereview.com/function#fn-jwt-verify-pinned"
  },
  {
   "id": "fn-keep-input-on-error",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "usability"
   ],
   "topics": [
    "frontend",
    "forms"
   ],
   "rule": "After a failed validation or submit, show the form again with every value the user entered, correct or not.",
   "url": "https://goodcodereview.com/function#fn-keep-input-on-error"
  },
  {
   "id": "fn-label-above-field",
   "level": "function",
   "severity": "discuss",
   "concerns": [
    "usability",
    "accessibility"
   ],
   "topics": [
    "frontend",
    "forms",
    "css"
   ],
   "rule": "Put the visible label of a text input, select, or textarea directly above it.",
   "url": "https://goodcodereview.com/function#fn-label-above-field"
  },
  {
   "id": "fn-length-budget",
   "level": "function",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "readability",
    "size"
   ],
   "rule": "Split a function that passes the project's length limit (about 40 lines if it sets none) unless its body is one simple operation or one flat dispatch.",
   "url": "https://goodcodereview.com/function#fn-length-budget"
  },
  {
   "id": "fn-link-url-scheme-allowlist",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "xss",
    "javascript"
   ],
   "rule": "Parse a URL that comes from data and allow only `https:` (and `http:` or `mailto:` where needed) before you set it as a link target.",
   "url": "https://goodcodereview.com/function#fn-link-url-scheme-allowlist"
  },
  {
   "id": "fn-mask-credentials-in-output",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "security",
    "usability"
   ],
   "topics": [
    "secrets"
   ],
   "rule": "Mask credentials in list, show and debug output (keep only the last four characters), and print a full value only behind an explicit flag.",
   "url": "https://goodcodereview.com/function#fn-mask-credentials-in-output"
  },
  {
   "id": "fn-name-intermediate-conditions",
   "level": "function",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "readability"
   ],
   "rule": "Name each compound condition by assigning its sub-conditions to booleans that say what they mean.",
   "url": "https://goodcodereview.com/function#fn-name-intermediate-conditions"
  },
  {
   "id": "fn-native-button-or-link",
   "level": "function",
   "severity": "block",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "html"
   ],
   "rule": "Use `<button>` for an action and `<a href>` for navigation. Do not attach a click handler to a `div`, `span`, or `a` with no `href`.",
   "url": "https://goodcodereview.com/function#fn-native-button-or-link"
  },
  {
   "id": "fn-no-blocking-call-in-async-code",
   "level": "function",
   "severity": "block",
   "concerns": [
    "performance",
    "correctness"
   ],
   "topics": [
    "concurrency",
    "io"
   ],
   "rule": "Never make a blocking I/O call or run long CPU work directly in async code; use the async API or hand the work to a thread or worker.",
   "url": "https://goodcodereview.com/function#fn-no-blocking-call-in-async-code"
  },
  {
   "id": "fn-no-caller-mutation",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "testing"
   ],
   "topics": [
    "state"
   ],
   "rule": "Do not mutate a parameter or an object the caller owns, unless the function is documented as mutating it.",
   "url": "https://goodcodereview.com/function#fn-no-caller-mutation"
  },
  {
   "id": "fn-no-check-then-act-across-await",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "concurrency"
   ],
   "rule": "Make check-and-write one atomic operation where the state lives, and never split it across a suspension point.",
   "url": "https://goodcodereview.com/function#fn-no-check-then-act-across-await"
  },
  {
   "id": "fn-no-eval-untrusted",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "injection"
   ],
   "rule": "Never pass untrusted text to `eval`, `exec`, `new Function`, or a template compiler. Pass it to a fixed template or a parser as data.",
   "url": "https://goodcodereview.com/function#fn-no-eval-untrusted"
  },
  {
   "id": "fn-no-getattr-for-known-names",
   "level": "function",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "types",
    "readability"
   ],
   "rule": "Use plain field access, and reserve dynamic access for genuinely dynamic names.",
   "url": "https://goodcodereview.com/function#fn-no-getattr-for-known-names"
  },
  {
   "id": "fn-no-magic-values",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "readability",
    "types"
   ],
   "rule": "Give every meaningful literal a name: an enum member or a constant.",
   "url": "https://goodcodereview.com/function#fn-no-magic-values"
  },
  {
   "id": "fn-no-mass-assignment",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authz",
    "api"
   ],
   "rule": "Bind request data to a DTO or an explicit field allowlist, never straight onto the model.",
   "url": "https://goodcodereview.com/function#fn-no-mass-assignment"
  },
  {
   "id": "fn-no-native-deserialise-untrusted",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "deserialisation"
   ],
   "rule": "Parse untrusted input with a data-only format, never with a native object deserialiser.",
   "url": "https://goodcodereview.com/function#fn-no-native-deserialise-untrusted"
  },
  {
   "id": "fn-no-positive-tabindex",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "keyboard"
   ],
   "rule": "Write the DOM in reading order and never set `tabindex` above 0.",
   "url": "https://goodcodereview.com/function#fn-no-positive-tabindex"
  },
  {
   "id": "fn-no-prototype-pollution",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "javascript",
    "injection"
   ],
   "rule": "Never write an untrusted key into a plain object. Use a `Map`, an object from `Object.create(null)`, or an allowlist of keys.",
   "url": "https://goodcodereview.com/function#fn-no-prototype-pollution"
  },
  {
   "id": "fn-no-raw-html-sink",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "xss",
    "frontend"
   ],
   "rule": "Write untrusted text through an encoding sink (`textContent`, auto-escaped template), never through a raw HTML sink.",
   "url": "https://goodcodereview.com/function#fn-no-raw-html-sink"
  },
  {
   "id": "fn-no-shell-with-input",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "injection",
    "command"
   ],
   "rule": "Start processes with the program and each argument as separate list items, and never through a shell string.",
   "url": "https://goodcodereview.com/function#fn-no-shell-with-input"
  },
  {
   "id": "fn-object-level-authz",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authz"
   ],
   "rule": "Check that the caller may act on the specific record before returning or changing it.",
   "url": "https://goodcodereview.com/function#fn-object-level-authz"
  },
  {
   "id": "fn-parameter-limit",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "readability",
    "api"
   ],
   "rule": "Set a parameter-count limit in the project's linter, and keep signatures within it.",
   "url": "https://goodcodereview.com/function#fn-parameter-limit"
  },
  {
   "id": "fn-password-slow-hash",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "crypto"
   ],
   "rule": "Hash passwords with Argon2id (or scrypt, bcrypt, PBKDF2) and a per-password salt from the library.",
   "url": "https://goodcodereview.com/function#fn-password-slow-hash"
  },
  {
   "id": "fn-redirect-target-allowlist",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "redirect",
    "url"
   ],
   "rule": "Redirect only to a local path or to a host on a server-side allowlist, never to a URL taken from the request as is.",
   "url": "https://goodcodereview.com/function#fn-redirect-target-allowlist"
  },
  {
   "id": "fn-reduced-motion-respected",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "css",
    "motion"
   ],
   "rule": "Switch off or replace large, repeating, or interaction-triggered motion when `prefers-reduced-motion: reduce` is set.",
   "url": "https://goodcodereview.com/function#fn-reduced-motion-respected"
  },
  {
   "id": "fn-regex-compiled-once",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [],
   "rule": "Compile a regular expression once, at module or startup level, and reuse it.",
   "url": "https://goodcodereview.com/function#fn-regex-compiled-once"
  },
  {
   "id": "fn-related-controls-in-fieldset",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "forms",
    "html"
   ],
   "rule": "Wrap each radio group, checkbox group, and multi-part value, such as day, month, and year, in a `<fieldset>` with a `<legend>` that names the group, often as the question.",
   "url": "https://goodcodereview.com/function#fn-related-controls-in-fieldset"
  },
  {
   "id": "fn-rerun-safe-after-crash",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "idempotency"
   ],
   "rule": "Make a state-changing operation give the same result on a second run and after a crash at any step, by deriving each step from current state and making leftovers recognisable as stale.",
   "url": "https://goodcodereview.com/function#fn-rerun-safe-after-crash"
  },
  {
   "id": "fn-response-fields-explicit",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "security",
    "compatibility"
   ],
   "topics": [
    "api",
    "data"
   ],
   "rule": "Return a response type that lists each field, never the stored model or a generic dump of it.",
   "url": "https://goodcodereview.com/function#fn-response-fields-explicit"
  },
  {
   "id": "fn-specific-exceptions-only",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "errors"
   ],
   "rule": "Catch only the specific exception you can handle in business code.",
   "url": "https://goodcodereview.com/function#fn-specific-exceptions-only"
  },
  {
   "id": "fn-status-announced-live-region",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "aria"
   ],
   "rule": "Announce an async status message through a live region (`role=\"status\"` or `role=\"alert\"`), and put a `role=\"status\"` or `aria-live` region in the markup before its text changes.",
   "url": "https://goodcodereview.com/function#fn-status-announced-live-region"
  },
  {
   "id": "fn-target-size",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "css"
   ],
   "rule": "Make each pointer target at least 24 by 24 CSS pixels, or space it so that a 24 px circle centred on it touches no other target and no other undersized target's circle.",
   "url": "https://goodcodereview.com/function#fn-target-size"
  },
  {
   "id": "fn-test-behaviour-not-implementation",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "maintainability"
   ],
   "topics": [
    "tests"
   ],
   "rule": "Assert what a caller can observe through the public interface, so a change that keeps behaviour does not break the test.",
   "url": "https://goodcodereview.com/function#fn-test-behaviour-not-implementation"
  },
  {
   "id": "fn-test-oracle-independent",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "testing"
   ],
   "topics": [
    "tests"
   ],
   "rule": "Take a test's expected value from the requirement, not from the code under test.",
   "url": "https://goodcodereview.com/function#fn-test-oracle-independent"
  },
  {
   "id": "fn-tls-verify-on",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "tls",
    "network"
   ],
   "rule": "Leave certificate and hostname verification on in every environment that ships.",
   "url": "https://goodcodereview.com/function#fn-tls-verify-on"
  },
  {
   "id": "fn-variants-as-tagged-union",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "types",
    "modelling"
   ],
   "rule": "Model variants as a tagged union, and make every switch over it fail the build when a variant is unhandled.",
   "url": "https://goodcodereview.com/function#fn-variants-as-tagged-union"
  },
  {
   "id": "fn-xml-no-external-entities",
   "level": "function",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "xml",
    "parsing"
   ],
   "rule": "Parse untrusted XML with external entity resolution turned off, for example through a hardened parser such as `defusedxml`.",
   "url": "https://goodcodereview.com/function#fn-xml-no-external-entities"
  },
  {
   "id": "inc-perf-fix-has-profile-evidence",
   "level": "incident",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "testing"
   ],
   "topics": [
    "verification"
   ],
   "rule": "Tie the performance fix to evidence that names the bottleneck: a profile, a trace, or a USE check.",
   "url": "https://goodcodereview.com/incident#inc-perf-fix-has-profile-evidence"
  },
  {
   "id": "inc-rollback-path-tested",
   "level": "incident",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "incident",
    "rollback"
   ],
   "rule": "Exercise each mitigation that a runbook names (rollback, failover, flag off) on a regular schedule.",
   "url": "https://goodcodereview.com/incident#inc-rollback-path-tested"
  },
  {
   "id": "mod-behaviour-lives-with-state",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "oop"
   ],
   "rule": "Put the invariants and calculations that read only one object's fields on that object.",
   "url": "https://goodcodereview.com/module#mod-behaviour-lives-with-state"
  },
  {
   "id": "mod-bounded-fan-out",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "structure"
   ],
   "rule": "Set a limit on how many other types or modules one unit depends on, and split a unit that passes it.",
   "url": "https://goodcodereview.com/module#mod-bounded-fan-out"
  },
  {
   "id": "mod-class-size-budget",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "size"
   ],
   "rule": "Split a class that passes the project's size limit for fields, public methods or lines, unless it is a data record.",
   "url": "https://goodcodereview.com/module#mod-class-size-budget"
  },
  {
   "id": "mod-colour-tokens-meet-contrast",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "css",
    "design-system"
   ],
   "rule": "Make every text and background token pair meet 4.5:1 (3:1 for large text), and every border, icon, and focus colour meet 3:1 against its neighbour.",
   "url": "https://goodcodereview.com/module#mod-colour-tokens-meet-contrast"
  },
  {
   "id": "mod-deep-modules",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design"
   ],
   "rule": "Prefer a small interface that hides its implementation, and add a member only when callers need it.",
   "url": "https://goodcodereview.com/module#mod-deep-modules"
  },
  {
   "id": "mod-derive-dont-duplicate",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "compatibility",
    "maintainability"
   ],
   "topics": [
    "duplication",
    "schemas"
   ],
   "rule": "Derive a type, list or enum from the schema or list that owns it, or add a build check that fails when the two disagree.",
   "url": "https://goodcodereview.com/module#mod-derive-dont-duplicate"
  },
  {
   "id": "mod-fowler-smells",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "refactoring"
   ],
   "rule": "Name the smell, point to the line, and suggest the refactoring; do not file smells as taste.",
   "url": "https://goodcodereview.com/module#mod-fowler-smells"
  },
  {
   "id": "mod-inject-boundary-collaborators",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "maintainability"
   ],
   "topics": [
    "design"
   ],
   "rule": "Inject boundary collaborators through the constructor; do not construct them inside or reach for a global.",
   "url": "https://goodcodereview.com/module#mod-inject-boundary-collaborators"
  },
  {
   "id": "mod-internals-unreachable",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "encapsulation",
    "boundaries"
   ],
   "rule": "Keep a module's internals unimportable and untouched from outside it. A caller uses the public surface, not a private file or member.",
   "url": "https://goodcodereview.com/module#mod-internals-unreachable"
  },
  {
   "id": "mod-law-of-demeter",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "coupling"
   ],
   "rule": "Call methods on your direct collaborators, and do not call a method on an object that another call returned (a chain of two or more getters).",
   "url": "https://goodcodereview.com/module#mod-law-of-demeter"
  },
  {
   "id": "mod-layers-point-inward",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "architecture"
   ],
   "rule": "Make dependencies point inward: surface, then logic, then boundary.",
   "url": "https://goodcodereview.com/module#mod-layers-point-inward"
  },
  {
   "id": "mod-no-import-cycles",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "structure"
   ],
   "rule": "Keep the dependency graph between modules or packages acyclic, and break a cycle by moving the shared part into a third module that both depend on.",
   "url": "https://goodcodereview.com/module#mod-no-import-cycles"
  },
  {
   "id": "mod-no-import-side-effects",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "maintainability"
   ],
   "topics": [
    "architecture"
   ],
   "rule": "Keep I/O at the edges: importing a package must not touch the network, read files, or read the environment.",
   "url": "https://goodcodereview.com/module#mod-no-import-side-effects"
  },
  {
   "id": "mod-no-logic-in-constructors",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "testing"
   ],
   "topics": [
    "state"
   ],
   "rule": "Assign only in constructors, and put I/O, parsing, and heavy computation in a named factory.",
   "url": "https://goodcodereview.com/module#mod-no-logic-in-constructors"
  },
  {
   "id": "mod-no-module-mutable-state",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "testing"
   ],
   "topics": [
    "state"
   ],
   "rule": "Keep no mutable state at module level; hold it on an instance.",
   "url": "https://goodcodereview.com/module#mod-no-module-mutable-state"
  },
  {
   "id": "mod-no-shotgun-surgery",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "coupling"
   ],
   "rule": "Keep one decision in one module, and when a single change needs edits in many classes, move the scattered parts together.",
   "url": "https://goodcodereview.com/module#mod-no-shotgun-surgery"
  },
  {
   "id": "mod-no-utils-grab-bag",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "architecture",
    "naming"
   ],
   "rule": "Put a helper in the module that owns the concept, or in a new module named after the concept.",
   "url": "https://goodcodereview.com/module#mod-no-utils-grab-bag"
  },
  {
   "id": "mod-no-wrong-abstraction",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design"
   ],
   "rule": "Inline an abstraction that has grown flags for its callers.",
   "url": "https://goodcodereview.com/module#mod-no-wrong-abstraction"
  },
  {
   "id": "mod-one-name-per-concept",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "naming"
   ],
   "rule": "Use one name for one concept across the codebase.",
   "url": "https://goodcodereview.com/module#mod-one-name-per-concept"
  },
  {
   "id": "mod-pooled-clients-built-once",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "resources"
   ],
   "rule": "Build pooled clients once at startup and reuse them.",
   "url": "https://goodcodereview.com/module#mod-pooled-clients-built-once"
  },
  {
   "id": "mod-proto-enum-zero-unspecified",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "protobuf"
   ],
   "rule": "Give every protobuf enum a zero value named `<ENUM>_UNSPECIFIED` with no real meaning.",
   "url": "https://goodcodereview.com/module#mod-proto-enum-zero-unspecified"
  },
  {
   "id": "mod-single-writer-per-state",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "concurrency",
    "ownership"
   ],
   "rule": "Let only one writer change a piece of state at a time, through a single owner, a queue that serialises the writes, or compare-and-swap, never by convention.",
   "url": "https://goodcodereview.com/module#mod-single-writer-per-state"
  },
  {
   "id": "mod-vetted-crypto-only",
   "level": "module",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "crypto"
   ],
   "rule": "Encrypt with an authenticated mode such as AES-GCM, and never reuse a nonce under one key.",
   "url": "https://goodcodereview.com/module#mod-vetted-crypto-only"
  },
  {
   "id": "mod-yagni",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability",
    "process"
   ],
   "topics": [
    "design",
    "scope"
   ],
   "rule": "Do not build an abstraction or capability for a need that does not exist yet; add it when the need or a second use appears.",
   "url": "https://goodcodereview.com/module#mod-yagni"
  },
  {
   "id": "prod-a11y-audit-before-launch",
   "level": "production",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "release"
   ],
   "rule": "Before a public launch, run an accessibility audit against WCAG 2.2 AA that includes assistive technology, and link the report in the launch checklist.",
   "url": "https://goodcodereview.com/production#prod-a11y-audit-before-launch"
  },
  {
   "id": "prod-alerts-symptoms-golden-signals",
   "level": "production",
   "severity": "should-fix",
   "concerns": [
    "observability"
   ],
   "topics": [
    "monitoring",
    "alerting"
   ],
   "rule": "Page on user-visible symptoms, such as error rate and latency, not on causes.",
   "url": "https://goodcodereview.com/production#prod-alerts-symptoms-golden-signals"
  },
  {
   "id": "prod-canary-staged-rollout",
   "level": "production",
   "severity": "block",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "deploys",
    "release"
   ],
   "rule": "Roll out in stages behind a canary, and abort by rule, not by judgment.",
   "url": "https://goodcodereview.com/production#prod-canary-staged-rollout"
  },
  {
   "id": "prod-kill-switch-fallback",
   "level": "production",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "resilience",
    "flags"
   ],
   "rule": "Make a risky feature switchable off without a deploy, and exercise every fallback path in test or in production on a schedule.",
   "url": "https://goodcodereview.com/production#prod-kill-switch-fallback"
  },
  {
   "id": "prod-latency-slo-percentile",
   "level": "production",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "observability"
   ],
   "topics": [
    "slo"
   ],
   "rule": "Define latency SLOs and alerts on high percentiles, never on the mean.",
   "url": "https://goodcodereview.com/production#prod-latency-slo-percentile"
  },
  {
   "id": "prod-load-test-before-launch",
   "level": "production",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "reliability"
   ],
   "topics": [
    "release",
    "capacity"
   ],
   "rule": "Load test before launch, past the expected peak, with pass and fail thresholds written down.",
   "url": "https://goodcodereview.com/production#prod-load-test-before-launch"
  },
  {
   "id": "prod-profile-on-demand",
   "level": "production",
   "severity": "discuss",
   "concerns": [
    "performance",
    "observability"
   ],
   "topics": [],
   "rule": "Make a CPU and memory profile of a production instance obtainable, through a continuous profiler or a private profile endpoint.",
   "url": "https://goodcodereview.com/production#prod-profile-on-demand"
  },
  {
   "id": "prod-shadow-compare-before-cutover",
   "level": "production",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "reliability"
   ],
   "topics": [
    "migration",
    "release"
   ],
   "rule": "Before you move traffic to a new system, run it beside the old one on live or captured production traffic, diff the results, and cut over only when every mismatch is fixed or explained.",
   "url": "https://goodcodereview.com/production#prod-shadow-compare-before-cutover"
  },
  {
   "id": "prod-slo-error-budget",
   "level": "production",
   "severity": "discuss",
   "concerns": [
    "reliability",
    "observability"
   ],
   "topics": [
    "slo"
   ],
   "rule": "Define an SLO with an indicator and window, and use its remaining error budget to gate risky releases.",
   "url": "https://goodcodereview.com/production#prod-slo-error-budget"
  },
  {
   "id": "svc-account-linking",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "accounts"
   ],
   "rule": "Link a federated identity to an existing account only after proving control of both, and key the link on the pair `iss` and `sub`, never on an unverified email or another profile claim.",
   "url": "https://goodcodereview.com/service-server#svc-account-linking"
  },
  {
   "id": "svc-api-cache-control",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "security"
   ],
   "topics": [
    "api",
    "http",
    "caching"
   ],
   "rule": "Set an explicit `Cache-Control` on every response a cache may store, use `private` or `no-store` for user-specific data, add `Vary` for any request header that changes the body, keep the origin's `Cache-Control` authoritative at the edge (no minimum TTL or force-cache override), and decide cacheability by the response `Content-Type`, not the URL extension.",
   "url": "https://goodcodereview.com/service-server#svc-api-cache-control"
  },
  {
   "id": "svc-api-conditional-writes",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "api",
    "http",
    "concurrency"
   ],
   "rule": "Return an `ETag` on reads and honour `If-Match` on writes, answering 412 when the entity tag is stale.",
   "url": "https://goodcodereview.com/service-server#svc-api-conditional-writes"
  },
  {
   "id": "svc-api-contract-tests",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "compatibility",
    "testing"
   ],
   "topics": [
    "api",
    "contracts"
   ],
   "rule": "Run a contract test for each cross-service call, derived from the consumer's real requests, and fail the provider's build when it breaks one.",
   "url": "https://goodcodereview.com/service-server#svc-api-contract-tests"
  },
  {
   "id": "svc-api-deprecation-sunset",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "deprecation"
   ],
   "rule": "Before removing an endpoint, mark it `deprecated` in the spec and send `Deprecation` and `Sunset` headers.",
   "url": "https://goodcodereview.com/service-server#svc-api-deprecation-sunset"
  },
  {
   "id": "svc-api-documented-errors",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "compatibility"
   ],
   "topics": [
    "api",
    "contracts",
    "errors"
   ],
   "rule": "Document every error status each operation can return, with a schema and one example.",
   "url": "https://goodcodereview.com/service-server#svc-api-documented-errors"
  },
  {
   "id": "svc-api-error-code-stable",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "errors"
   ],
   "rule": "Give each error a stable machine-readable code that callers branch on, and never make them parse the message text.",
   "url": "https://goodcodereview.com/service-server#svc-api-error-code-stable"
  },
  {
   "id": "svc-api-key-scope",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "secrets",
    "api"
   ],
   "rule": "Issue each API key with the narrowest scopes and a bounded lifetime, and rotate or revoke it after any exposure.",
   "url": "https://goodcodereview.com/service-server#svc-api-key-scope"
  },
  {
   "id": "svc-api-naming-consistent",
   "level": "service",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "api",
    "naming"
   ],
   "rule": "Use one casing convention per location (fields, query parameters, headers, paths) across the whole API, and state it in the API guide.",
   "url": "https://goodcodereview.com/service-server#svc-api-naming-consistent"
  },
  {
   "id": "svc-api-problem-json",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "errors"
   ],
   "rule": "Return errors as `application/problem+json` with a `status` that equals the HTTP status, and leave stack traces and internal detail out.",
   "url": "https://goodcodereview.com/service-server#svc-api-problem-json"
  },
  {
   "id": "svc-api-retry-after",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "api",
    "http",
    "resilience"
   ],
   "rule": "Send `Retry-After` on every 429 and 503, and set it no earlier than the time capacity returns.",
   "url": "https://goodcodereview.com/service-server#svc-api-retry-after"
  },
  {
   "id": "svc-api-specific-status-codes",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "http"
   ],
   "rule": "Return the most specific status code that fits: 201 with `Location` for a create, 405 with `Allow` for a wrong method, and a 4xx or 5xx for any failure.",
   "url": "https://goodcodereview.com/service-server#svc-api-specific-status-codes"
  },
  {
   "id": "svc-api-versioning-policy",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "versioning"
   ],
   "rule": "Write down one versioning scheme for the API, and ship no breaking change inside a version it has published.",
   "url": "https://goodcodereview.com/service-server#svc-api-versioning-policy"
  },
  {
   "id": "svc-async-content-reserves-space",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "usability",
    "performance"
   ],
   "topics": [
    "frontend",
    "css"
   ],
   "rule": "Reserve the space for late-loading content with set dimensions or an aspect ratio, so nothing already on screen moves.",
   "url": "https://goodcodereview.com/service-ui#svc-async-content-reserves-space"
  },
  {
   "id": "svc-auth-throttle-generic-errors",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "rate-limit"
   ],
   "rule": "Limit failed attempts per account, and return the same message and status code whether or not the account exists.",
   "url": "https://goodcodereview.com/service-server#svc-auth-throttle-generic-errors"
  },
  {
   "id": "svc-authn-by-default",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn"
   ],
   "rule": "Require authentication on every route by default, and mark each public route by name.",
   "url": "https://goodcodereview.com/service-server#svc-authn-by-default"
  },
  {
   "id": "svc-authz-central-deny-default",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authz"
   ],
   "rule": "Route every request through one authorization layer that denies when no rule allows it.",
   "url": "https://goodcodereview.com/service-server#svc-authz-central-deny-default"
  },
  {
   "id": "svc-best-effort-optional-deps",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability",
    "observability"
   ],
   "topics": [
    "resilience",
    "dependencies"
   ],
   "rule": "Give each call to a non-critical dependency a short budget and a default, so its failure degrades the result instead of failing the critical path, and count every fallback.",
   "url": "https://goodcodereview.com/service-any#svc-best-effort-optional-deps"
  },
  {
   "id": "svc-bound-client-controlled-sizes",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "dos",
    "api"
   ],
   "rule": "Cap every client-controlled size and count on the server: body bytes, string length, array items, page size and batch size.",
   "url": "https://goodcodereview.com/service-server#svc-bound-client-controlled-sizes"
  },
  {
   "id": "svc-bounded-background-tasks",
   "level": "service",
   "severity": "block",
   "concerns": [
    "reliability",
    "correctness"
   ],
   "topics": [
    "concurrency",
    "resilience",
    "async"
   ],
   "rule": "Cap how many background tasks run at once, and never spawn one per input with no limit.",
   "url": "https://goodcodereview.com/service-any#svc-bounded-background-tasks"
  },
  {
   "id": "svc-cache-key-completeness",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "http",
    "caching"
   ],
   "rule": "Key every request input that can change the response, and strip any other request value before it reaches a cached body.",
   "url": "https://goodcodereview.com/service-server#svc-cache-key-completeness"
  },
  {
   "id": "svc-circuit-breaker-bulkhead",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "resilience",
    "isolation"
   ],
   "rule": "Give each critical dependency its own concurrency limit.",
   "url": "https://goodcodereview.com/service-any#svc-circuit-breaker-bulkhead"
  },
  {
   "id": "svc-cli-destructive-dry-run",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability",
    "maintainability"
   ],
   "topics": [
    "cli",
    "safety"
   ],
   "rule": "Give a destructive command a preview flag that changes nothing and a flag that skips the confirmation prompt.",
   "url": "https://goodcodereview.com/service-cli#svc-cli-destructive-dry-run"
  },
  {
   "id": "svc-cli-exit-codes-and-streams",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "maintainability"
   ],
   "topics": [
    "cli",
    "automation"
   ],
   "rule": "Exit non-zero when a command fails, and write results to stdout and errors and progress to stderr.",
   "url": "https://goodcodereview.com/service-cli#svc-cli-exit-codes-and-streams"
  },
  {
   "id": "svc-cli-non-interactive",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "maintainability",
    "process"
   ],
   "topics": [
    "cli",
    "automation"
   ],
   "rule": "Let the caller turn every prompt off with a flag or an environment variable, so the command never waits on a terminal.",
   "url": "https://goodcodereview.com/service-cli#svc-cli-non-interactive"
  },
  {
   "id": "svc-cors-allowlist",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "cors",
    "http"
   ],
   "rule": "Allow cross-origin access only to a fixed list of named origins, and never echo the request `Origin` header back unchecked.",
   "url": "https://goodcodereview.com/service-server#svc-cors-allowlist"
  },
  {
   "id": "svc-csp-strict-script-src",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "http",
    "headers",
    "xss"
   ],
   "rule": "Send a `Content-Security-Policy` whose `script-src` uses a per-response nonce or script hashes, with `object-src 'none'` and `base-uri 'none'`.",
   "url": "https://goodcodereview.com/service-server#svc-csp-strict-script-src"
  },
  {
   "id": "svc-csrf-state-changing",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "csrf",
    "sessions"
   ],
   "rule": "Require a CSRF token (or an equivalent header check) on every cookie-authenticated request that changes state, and never change state on GET.",
   "url": "https://goodcodereview.com/service-server#svc-csrf-state-changing"
  },
  {
   "id": "svc-decompression-cap",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security",
    "performance"
   ],
   "topics": [
    "dos"
   ],
   "rule": "Cap the decompressed output of every decoder, and set the cap on the output rather than the compressed input.",
   "url": "https://goodcodereview.com/service-server#svc-decompression-cap"
  },
  {
   "id": "svc-dlq",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "queues",
    "resilience"
   ],
   "rule": "Give every consumer queue a dead-letter queue and keep a way to replay it after the fix. On an ordered queue, key the group or session to the unit that must stay ordered, so a poison message holds only its own unit.",
   "url": "https://goodcodereview.com/service-server#svc-dlq"
  },
  {
   "id": "svc-export-scope",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "data",
    "multi-tenant"
   ],
   "rule": "Scope an export to what the requesting principal may read.",
   "url": "https://goodcodereview.com/service-data#svc-export-scope"
  },
  {
   "id": "svc-fail-closed-defaults",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "configuration"
   ],
   "rule": "Ship every security control switched on, with an empty allow-list denying everything.",
   "url": "https://goodcodereview.com/service-server#svc-fail-closed-defaults"
  },
  {
   "id": "svc-host-header-trust",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "http",
    "authn"
   ],
   "rule": "Build absolute URLs from configured values, answer only for a `Host` on an allowlist, and take `X-Forwarded-*` values only from a trusted proxy.",
   "url": "https://goodcodereview.com/service-server#svc-host-header-trust"
  },
  {
   "id": "svc-idempotency-key",
   "level": "service",
   "severity": "block",
   "concerns": [
    "reliability",
    "correctness"
   ],
   "topics": [
    "resilience"
   ],
   "rule": "Make every retryable write idempotent: the caller sends a unique key, and a retry with the same key never applies the write twice.",
   "url": "https://goodcodereview.com/service-server#svc-idempotency-key"
  },
  {
   "id": "svc-invalid-input-is-4xx",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "reliability"
   ],
   "topics": [
    "api",
    "validation"
   ],
   "rule": "Check each caller-supplied value against its allowed domain (range, allowed set, an id that must exist, an encoding the code can handle) at the boundary, and answer a failed check with a 4xx, never a 5xx.",
   "url": "https://goodcodereview.com/service-server#svc-invalid-input-is-4xx"
  },
  {
   "id": "svc-list-endpoint-paginates",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "api"
   ],
   "rule": "Paginate every list endpoint, with a default page size and a server-side maximum.",
   "url": "https://goodcodereview.com/service-server#svc-list-endpoint-paginates"
  },
  {
   "id": "svc-mfa-step-up",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "mfa"
   ],
   "rule": "Require a fresh authentication with an already-bound factor before sensitive actions and before adding, replacing or removing an MFA factor; an existing session alone is not enough.",
   "url": "https://goodcodereview.com/service-server#svc-mfa-step-up"
  },
  {
   "id": "svc-no-redundant-entry",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "usability",
    "accessibility"
   ],
   "topics": [
    "frontend",
    "forms"
   ],
   "rule": "Do not ask for information the user already gave in the same flow. Fill it in, or let the user pick it.",
   "url": "https://goodcodereview.com/service-ui#svc-no-redundant-entry"
  },
  {
   "id": "svc-no-secrets-in-url",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "secrets",
    "http"
   ],
   "rule": "Send tokens, keys, passwords, and personal data in a header or the request body, never in the path or query string.",
   "url": "https://goodcodereview.com/service-server#svc-no-secrets-in-url"
  },
  {
   "id": "svc-oauth-code-flow-binding",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "oauth"
   ],
   "rule": "Finish the authorization-code flow with PKCE and a challenge method that keeps the verifier out of the authorization request (`S256`), send the exact registered `redirect_uri` (a native app on the loopback interface may vary the port), and reject the response unless this transaction's `state` or OIDC `nonce` matches and the ID token's signature, `iss`, `aud` and `exp` check out.",
   "url": "https://goodcodereview.com/service-server#svc-oauth-code-flow-binding"
  },
  {
   "id": "svc-password-reset",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "passwords"
   ],
   "rule": "Make the reset token single-use and short-lived, and on success revoke every session.",
   "url": "https://goodcodereview.com/service-server#svc-password-reset"
  },
  {
   "id": "svc-rate-limit-quota",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security",
    "reliability"
   ],
   "topics": [
    "multi-tenant",
    "overload"
   ],
   "rule": "Enforce a per-tenant quota on shared APIs and queues.",
   "url": "https://goodcodereview.com/service-server#svc-rate-limit-quota"
  },
  {
   "id": "svc-reflow-and-zoom",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability"
   ],
   "topics": [
    "frontend",
    "css",
    "responsive"
   ],
   "rule": "Make the page usable at 320 CSS pixels wide and at 200% text zoom, with no sideways scrolling, no clipped content, and no blocked pinch-zoom.",
   "url": "https://goodcodereview.com/service-ui#svc-reflow-and-zoom"
  },
  {
   "id": "svc-request-framing",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "http",
    "protocol"
   ],
   "rule": "Reject a request that carries both `Transfer-Encoding` and `Content-Length`, or remove one field at the first hop, and parse header framing strictly rather than with a leniency flag.",
   "url": "https://goodcodereview.com/service-server#svc-request-framing"
  },
  {
   "id": "svc-retry-policy",
   "level": "service",
   "severity": "block",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "resilience",
    "retries"
   ],
   "rule": "Retry only transient errors, with capped attempts and jittered exponential backoff.",
   "url": "https://goodcodereview.com/service-any#svc-retry-policy"
  },
  {
   "id": "svc-saga-steps",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability",
    "correctness"
   ],
   "topics": [
    "distributed",
    "consistency"
   ],
   "rule": "Make steps after the pivot idempotent and retryable, and make every compensation idempotent with a failure path.",
   "url": "https://goodcodereview.com/service-server#svc-saga-steps"
  },
  {
   "id": "svc-saml-assertion-binding",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "saml"
   ],
   "rule": "Verify the XML signature over the assertion you read, with the IdP's configured key rather than a key carried in the response, then require the assertion's `Audience` and its bearer `SubjectConfirmationData` `Recipient` to name this SP, the response `Destination` to be this endpoint, `InResponseTo` to match your request (absent for an IdP-initiated response), `NotOnOrAfter` to be current, and the assertion ID to be unseen. These are one step, verify the assertion, and each check is cited.",
   "url": "https://goodcodereview.com/service-server#svc-saml-assertion-binding"
  },
  {
   "id": "svc-session-lifecycle",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "authn",
    "sessions"
   ],
   "rule": "Issue a new session ID at login, and set `Secure`, `HttpOnly` and `SameSite` on the session cookie.",
   "url": "https://goodcodereview.com/service-server#svc-session-lifecycle"
  },
  {
   "id": "svc-slow-operation-shows-progress",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "usability",
    "accessibility"
   ],
   "topics": [
    "frontend"
   ],
   "rule": "Show that a slow action is under way, and show its progress when it runs long.",
   "url": "https://goodcodereview.com/service-ui#svc-slow-operation-shows-progress"
  },
  {
   "id": "svc-soft-delete-default",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security",
    "correctness"
   ],
   "topics": [
    "data"
   ],
   "rule": "Filter soft-deleted rows out of every read path by default, and make a read that includes them an explicit call.",
   "url": "https://goodcodereview.com/service-data#svc-soft-delete-default"
  },
  {
   "id": "svc-sqli-authn",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "injection",
    "sql"
   ],
   "rule": "Pass untrusted data to queries as bound parameters, never by string concatenation or formatting.",
   "url": "https://goodcodereview.com/service-server#svc-sqli-authn"
  },
  {
   "id": "svc-stream-dont-materialise",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "memory",
    "io"
   ],
   "rule": "Process large results as a stream with backpressure; do not load them whole into memory.",
   "url": "https://goodcodereview.com/service-any#svc-stream-dont-materialise"
  },
  {
   "id": "svc-tenant-id-in-telemetry",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security",
    "observability"
   ],
   "topics": [
    "multi-tenant"
   ],
   "rule": "Put the verified tenant id on every tenant-scoped log, metric and audit record.",
   "url": "https://goodcodereview.com/service-server#svc-tenant-id-in-telemetry"
  },
  {
   "id": "svc-timeouts",
   "level": "service",
   "severity": "block",
   "concerns": [
    "performance",
    "reliability"
   ],
   "topics": [
    "resilience",
    "io"
   ],
   "rule": "Set an explicit timeout on every remote call.",
   "url": "https://goodcodereview.com/service-any#svc-timeouts"
  },
  {
   "id": "svc-tls-modern-only",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "tls",
    "network"
   ],
   "rule": "Accept only TLS 1.2 and TLS 1.3 on servers.",
   "url": "https://goodcodereview.com/service-server#svc-tls-modern-only"
  },
  {
   "id": "svc-update-rollback-on-failure",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "cli"
   ],
   "rule": "When an update fails, restore the previous version instead of leaving a missing or half-written one.",
   "url": "https://goodcodereview.com/service-any#svc-update-rollback-on-failure"
  },
  {
   "id": "svc-update-verify-provenance",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "supply-chain",
    "cli"
   ],
   "rule": "Verify a downloaded update against a signature, an attestation or a pinned key, or against a checksum that reached you by another route than the file; a checksum fetched from the same host as the file does not count.",
   "url": "https://goodcodereview.com/service-any#svc-update-verify-provenance"
  },
  {
   "id": "svc-upload-validate-store",
   "level": "service",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "files",
    "uploads"
   ],
   "rule": "Allowlist the file type, cap the size, and store each upload under a generated name where the server will not execute it.",
   "url": "https://goodcodereview.com/service-server#svc-upload-validate-store"
  },
  {
   "id": "svc-webhook-replay-window",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "messaging",
    "webhooks"
   ],
   "rule": "Reject an inbound signed message whose creation time is outside a short tolerance, and sign that time with the body so it cannot be swapped.",
   "url": "https://goodcodereview.com/service-server#svc-webhook-replay-window"
  },
  {
   "id": "sys-agent-tool-least-privilege",
   "level": "system",
   "severity": "block",
   "concerns": [
    "security",
    "process"
   ],
   "topics": [
    "llm",
    "agents"
   ],
   "rule": "Give the agent only the narrow tools and the minimal credentials its task needs.",
   "url": "https://goodcodereview.com/system#sys-agent-tool-least-privilege"
  },
  {
   "id": "sys-cache-bounds-invalidation",
   "level": "system",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "caching",
    "memory"
   ],
   "rule": "Bound every cache by size and give its entries an expiry.",
   "url": "https://goodcodereview.com/system#sys-cache-bounds-invalidation"
  },
  {
   "id": "sys-cells-limit-blast-radius",
   "level": "system",
   "severity": "discuss",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "isolation",
    "availability"
   ],
   "rule": "Split shared infrastructure into independent cells, each with its own control plane and storage, and route each tenant or request to one cell, so one failure stops only that cell.",
   "url": "https://goodcodereview.com/system#sys-cells-limit-blast-radius"
  },
  {
   "id": "sys-consistent-ui-terms",
   "level": "system",
   "severity": "discuss",
   "concerns": [
    "usability",
    "accessibility"
   ],
   "topics": [
    "frontend",
    "design-system"
   ],
   "rule": "Use one label and one icon for the same action and the same concept across all screens.",
   "url": "https://goodcodereview.com/system#sys-consistent-ui-terms"
  },
  {
   "id": "sys-fanout-leg-deadlines",
   "level": "system",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "reliability"
   ],
   "topics": [
    "latency",
    "resilience"
   ],
   "rule": "Give every leg of a fan-out its own deadline, and decide in code what happens when a leg misses it: a partial result, a hedged request, or an error.",
   "url": "https://goodcodereview.com/system#sys-fanout-leg-deadlines"
  },
  {
   "id": "sys-health-liveness-readiness",
   "level": "system",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "health",
    "availability"
   ],
   "rule": "Wire load balancers and restarters to liveness and local checks only, never to shared-dependency checks.",
   "url": "https://goodcodereview.com/system#sys-health-liveness-readiness"
  },
  {
   "id": "sys-index-concurrently",
   "level": "system",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "database",
    "migration",
    "postgres"
   ],
   "rule": "Create indexes with `CONCURRENTLY`, outside a transaction block, and handle a failed build that leaves an INVALID index.",
   "url": "https://goodcodereview.com/system#sys-index-concurrently"
  },
  {
   "id": "sys-load-shedding-bounded-queues",
   "level": "system",
   "severity": "block",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "overload",
    "queues"
   ],
   "rule": "Bound every queue and reject excess work cheaply.",
   "url": "https://goodcodereview.com/system#sys-load-shedding-bounded-queues"
  },
  {
   "id": "sys-lock-fencing",
   "level": "system",
   "severity": "block",
   "concerns": [
    "reliability",
    "correctness"
   ],
   "topics": [
    "locks",
    "distributed"
   ],
   "rule": "Check a correctness lock on the resource side (fencing token or compare-and-set), never by lock possession alone.",
   "url": "https://goodcodereview.com/system#sys-lock-fencing"
  },
  {
   "id": "sys-migration-expand-contract",
   "level": "system",
   "severity": "block",
   "concerns": [
    "reliability",
    "compatibility"
   ],
   "topics": [
    "database",
    "migration",
    "deploys"
   ],
   "rule": "Run data backfills in batches, in a migration separate from the schema change.",
   "url": "https://goodcodereview.com/system#sys-migration-expand-contract"
  },
  {
   "id": "sys-migration-lock-timeout",
   "level": "system",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "database",
    "migration",
    "postgres"
   ],
   "rule": "Set `lock_timeout` for the migration session and retry on timeout.",
   "url": "https://goodcodereview.com/system#sys-migration-lock-timeout"
  },
  {
   "id": "sys-n-plus-one-pooling",
   "level": "system",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "database"
   ],
   "rule": "Fetch related rows in one query or batch, never one query per row.",
   "url": "https://goodcodereview.com/system#sys-n-plus-one-pooling"
  },
  {
   "id": "sys-pii-minimise-retention",
   "level": "system",
   "severity": "should-fix",
   "concerns": [
    "security"
   ],
   "topics": [
    "privacy",
    "data"
   ],
   "rule": "Give every store of personal or sensitive data a retention period, and delete or anonymise the data when it ends.",
   "url": "https://goodcodereview.com/system#sys-pii-minimise-retention"
  },
  {
   "id": "sys-prompt-injection",
   "level": "system",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "llm"
   ],
   "rule": "Validate model output deterministically before code acts on it.",
   "url": "https://goodcodereview.com/system#sys-prompt-injection"
  },
  {
   "id": "sys-secrets-and-errors",
   "level": "system",
   "severity": "block",
   "concerns": [
    "security",
    "correctness"
   ],
   "topics": [
    "secrets",
    "errors"
   ],
   "rule": "Fail closed: a validation or auth error must deny, never continue, and an error response must not carry internals such as stack traces, SQL or tokens.",
   "url": "https://goodcodereview.com/system#sys-secrets-and-errors"
  },
  {
   "id": "sys-ssrf",
   "level": "system",
   "severity": "block",
   "concerns": [
    "security"
   ],
   "topics": [
    "ssrf"
   ],
   "rule": "Fetch a user-supplied URL only when its host matches a server-side allowlist.",
   "url": "https://goodcodereview.com/system#sys-ssrf"
  },
  {
   "id": "chg-agent-grounded-code",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "maintainability",
    "process"
   ],
   "topics": [
    "agents",
    "ai-generated",
    "reuse"
   ],
   "rule": "Verify that every import and external call the agent wrote exists with that signature.",
   "url": "https://goodcodereview.com/change#chg-agent-grounded-code"
  },
  {
   "id": "chg-agent-independent-review",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "process"
   ],
   "topics": [
    "agents",
    "review"
   ],
   "rule": "Get sign-off from a person or a fresh-context reviewer who has the spec but not the author's reasoning; self-review by the writing session does not count.",
   "url": "https://goodcodereview.com/change#chg-agent-independent-review"
  },
  {
   "id": "chg-approval-tied-to-patch",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "process"
   ],
   "topics": [
    "review"
   ],
   "rule": "Treat an approval or verification verdict as current only if the patch is unchanged: compare `git patch-id` at the verdict commit with the current head. If the patches differ only in tests, docs, or lint config, the verdict can stand when the built output is the same; any other difference needs a fresh check.",
   "url": "https://goodcodereview.com/change#chg-approval-tied-to-patch"
  },
  {
   "id": "chg-author-hygiene",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "process"
   ],
   "topics": [
    "author",
    "ci"
   ],
   "rule": "Self-review the diff and write the description before requesting review.",
   "url": "https://goodcodereview.com/change#chg-author-hygiene"
  },
  {
   "id": "chg-breaking-change-taxonomy",
   "level": "change",
   "severity": "block",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api"
   ],
   "rule": "Treat any change that callers can observe in a signature, return values, error types, defaults, or side effects as breaking until a consumer check says otherwise.",
   "url": "https://goodcodereview.com/change#chg-breaking-change-taxonomy"
  },
  {
   "id": "chg-chestertons-fence",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "maintainability",
    "process"
   ],
   "topics": [
    "legacy",
    "history"
   ],
   "rule": "Add a characterization test before rewriting code you do not understand.",
   "url": "https://goodcodereview.com/change#chg-chestertons-fence"
  },
  {
   "id": "chg-delete-legacy-after-migration",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "compatibility",
    "maintainability"
   ],
   "topics": [
    "migration",
    "cleanup"
   ],
   "rule": "When no consumer sits outside the repo, move every caller to the new API and delete the old one, and the tests that pinned its internals, in the same change.",
   "url": "https://goodcodereview.com/change#chg-delete-legacy-after-migration"
  },
  {
   "id": "chg-devex-breaking-config",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "compatibility",
    "process"
   ],
   "topics": [
    "config"
   ],
   "rule": "Flag a change that renames or removes an environment variable, moves a secret, or remaps a port as breaking for developers and operators, and update every place that documents or sets it.",
   "url": "https://goodcodereview.com/change#chg-devex-breaking-config"
  },
  {
   "id": "chg-expand-contract",
   "level": "change",
   "severity": "block",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "migration"
   ],
   "rule": "Evolve shared contracts in steps: add the new form beside the old (expand), migrate every consumer, then remove the old form (contract) in a later change.",
   "url": "https://goodcodereview.com/change#chg-expand-contract"
  },
  {
   "id": "chg-match-codebase-pattern",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "maintainability"
   ],
   "topics": [
    "consistency",
    "style"
   ],
   "rule": "Follow the established pattern nearby.",
   "url": "https://goodcodereview.com/change#chg-match-codebase-pattern"
  },
  {
   "id": "chg-migration-add-column-rewrite",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "database",
    "migration",
    "postgres"
   ],
   "rule": "Add the column nullable or with a constant default, then fill volatile, computed, or identity values in batches.",
   "url": "https://goodcodereview.com/change#chg-migration-add-column-rewrite"
  },
  {
   "id": "chg-name-attack-surface",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "security",
    "process"
   ],
   "topics": [
    "review"
   ],
   "rule": "List any new attack surface in the description.",
   "url": "https://goodcodereview.com/change#chg-name-attack-surface"
  },
  {
   "id": "chg-no-silenced-diagnostics",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "correctness",
    "maintainability",
    "process"
   ],
   "topics": [
    "errors",
    "lint",
    "ci"
   ],
   "rule": "Name the rule, the reason, and a ticket on every suppression; a swallowed error, skipped test, or disabled check is a FAIL unless justified.",
   "url": "https://goodcodereview.com/change#chg-no-silenced-diagnostics"
  },
  {
   "id": "chg-no-special-case-branches",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "design",
    "complexity"
   ],
   "rule": "Put a new case behind its own function or type; do not add a one-off branch to a shared flow.",
   "url": "https://goodcodereview.com/change#chg-no-special-case-branches"
  },
  {
   "id": "chg-one-concern",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "process"
   ],
   "topics": [
    "scope",
    "size"
   ],
   "rule": "Make each change do one logical thing; if the description needs \"and\" between unrelated outcomes, split it.",
   "url": "https://goodcodereview.com/change#chg-one-concern"
  },
  {
   "id": "chg-perf-claim-evidence",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "performance",
    "testing"
   ],
   "topics": [
    "verification"
   ],
   "rule": "Back a performance claim with measured before-and-after numbers.",
   "url": "https://goodcodereview.com/change#chg-perf-claim-evidence"
  },
  {
   "id": "chg-proto-no-field-type-change",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "protobuf"
   ],
   "rule": "Never change the type of a protobuf field, switch it between repeated and scalar, or rename it while any consumer reads JSON or text format; add a new field instead.",
   "url": "https://goodcodereview.com/change#chg-proto-no-field-type-change"
  },
  {
   "id": "chg-proto-reserve-removed-fields",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "compatibility"
   ],
   "topics": [
    "api",
    "protobuf"
   ],
   "rule": "When you delete a protobuf field or enum value, add `reserved` for its number and name in the same change, and never reuse a number.",
   "url": "https://goodcodereview.com/change#chg-proto-reserve-removed-fields"
  },
  {
   "id": "chg-refactor-has-behaviour-pin",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "maintainability"
   ],
   "topics": [
    "refactoring",
    "tests"
   ],
   "rule": "Pin current behaviour with a characterization test, snapshot or equivalence check before the refactor moves any structure.",
   "url": "https://goodcodereview.com/change#chg-refactor-has-behaviour-pin"
  },
  {
   "id": "chg-refactor-separate",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "maintainability",
    "process"
   ],
   "topics": [
    "refactoring",
    "scope"
   ],
   "rule": "Put refactors, renames, and reformatting in their own commit or PR, apart from behaviour changes.",
   "url": "https://goodcodereview.com/change#chg-refactor-separate"
  },
  {
   "id": "chg-reuse-before-write",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "reuse",
    "duplication"
   ],
   "rule": "Do not add a helper that duplicates one already in the repo; search for it first.",
   "url": "https://goodcodereview.com/change#chg-reuse-before-write"
  },
  {
   "id": "chg-review-signal",
   "level": "change",
   "severity": "discuss",
   "concerns": [
    "process"
   ],
   "topics": [
    "reviewer",
    "etiquette",
    "signal"
   ],
   "rule": "Do not spend review comments on what a tool enforces or on minor style points; spend them on the findings that matter.",
   "url": "https://goodcodereview.com/change#chg-review-signal"
  },
  {
   "id": "chg-rollback-path",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "reliability"
   ],
   "topics": [
    "release",
    "rollback"
   ],
   "rule": "State in the description how to undo the change.",
   "url": "https://goodcodereview.com/change#chg-rollback-path"
  },
  {
   "id": "chg-size-ceiling",
   "level": "change",
   "severity": "discuss",
   "concerns": [
    "process"
   ],
   "topics": [
    "size",
    "review-quality"
   ],
   "rule": "Split a change past about 400 changed lines or about 20 files, or say in the description why not; aim for about 200.",
   "url": "https://goodcodereview.com/change#chg-size-ceiling"
  },
  {
   "id": "chg-tests-ship-with-change",
   "level": "change",
   "severity": "block",
   "concerns": [
    "testing"
   ],
   "topics": [],
   "rule": "Ship new or changed behaviour in the same change as a test that fails if the behaviour breaks.",
   "url": "https://goodcodereview.com/change#chg-tests-ship-with-change"
  },
  {
   "id": "chg-ui-change-screenshots-and-keyboard-pass",
   "level": "change",
   "severity": "should-fix",
   "concerns": [
    "accessibility",
    "usability",
    "process"
   ],
   "topics": [
    "frontend"
   ],
   "rule": "A UI change shows before-and-after screenshots and says what a keyboard-only pass and a 200% zoom check found on the changed screens.",
   "url": "https://goodcodereview.com/change#chg-ui-change-screenshots-and-keyboard-pass"
  },
  {
   "id": "chg-verify-before-claim",
   "level": "change",
   "severity": "block",
   "concerns": [
    "testing",
    "process"
   ],
   "topics": [
    "verification",
    "reviewer"
   ],
   "rule": "Back every \"works\" or \"bug\" claim with something run: a repro, a test or command output.",
   "url": "https://goodcodereview.com/change#chg-verify-before-claim"
  },
  {
   "id": "py-cancellation",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "reliability",
    "correctness"
   ],
   "topics": [
    "asyncio",
    "cancellation"
   ],
   "rule": "Re-raise `CancelledError` (do not catch it via bare `except` or `BaseException`), and catch `TimeoutError` outside the `asyncio.timeout()` block.",
   "url": "https://goodcodereview.com/pack-python#py-cancellation"
  },
  {
   "id": "py-class-earns-its-instance",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "python",
    "classes"
   ],
   "rule": "Give a class real state or a collaborator; otherwise write a module function.",
   "url": "https://goodcodereview.com/pack-python#py-class-earns-its-instance"
  },
  {
   "id": "py-docstrings-google",
   "level": "function",
   "severity": "discuss",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "python",
    "docs"
   ],
   "rule": "Write a Google-style docstring only when it adds what the signature cannot say.",
   "url": "https://goodcodereview.com/pack-python#py-docstrings-google"
  },
  {
   "id": "py-field-only-when-adds",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "python",
    "pydantic"
   ],
   "rule": "Use `Field()` only when it adds something (a constraint, an alias, or API docs), and set plain defaults directly.",
   "url": "https://goodcodereview.com/pack-python#py-field-only-when-adds"
  },
  {
   "id": "py-httpx-client-lifespan",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "performance"
   ],
   "topics": [
    "python",
    "resources"
   ],
   "rule": "Pass an explicit `httpx.Timeout` to every `httpx` client.",
   "url": "https://goodcodereview.com/pack-python#py-httpx-client-lifespan"
  },
  {
   "id": "py-imports",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "python",
    "imports"
   ],
   "rule": "Put imports at module top, absolute only.",
   "url": "https://goodcodereview.com/pack-python#py-imports"
  },
  {
   "id": "py-modern-typing",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "python",
    "types"
   ],
   "rule": "Write `X | None` and builtin generics, not `typing` aliases.",
   "url": "https://goodcodereview.com/pack-python#py-modern-typing"
  },
  {
   "id": "py-no-cast",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "python",
    "types"
   ],
   "rule": "Do not use `cast()`; parse the boundary into a typed model, or narrow with `isinstance`.",
   "url": "https://goodcodereview.com/pack-python#py-no-cast"
  },
  {
   "id": "py-no-init-or-model-tests",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "testing"
   ],
   "topics": [
    "python"
   ],
   "rule": "Cover `__init__` and plain models through the behaviour that uses them.",
   "url": "https://goodcodereview.com/pack-python#py-no-init-or-model-tests"
  },
  {
   "id": "py-paths-from-file",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "python",
    "io"
   ],
   "rule": "Resolve paths from `__file__`, not the current working directory.",
   "url": "https://goodcodereview.com/pack-python#py-paths-from-file"
  },
  {
   "id": "py-pytest-expensive-fixture-scope",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "performance"
   ],
   "topics": [
    "python",
    "fixtures"
   ],
   "rule": "Give an expensive pytest fixture `scope=\"session\"` or `\"module\"` and isolate each test with a rollback, never a schema build or a seed load inside a function-scoped fixture.",
   "url": "https://goodcodereview.com/pack-python#py-pytest-expensive-fixture-scope"
  },
  {
   "id": "py-pytest-parametrize",
   "level": "function",
   "severity": "should-fix",
   "concerns": [
    "testing"
   ],
   "topics": [
    "python"
   ],
   "rule": "Write tests that differ only in inputs and expected values as one `@pytest.mark.parametrize` test.",
   "url": "https://goodcodereview.com/pack-python#py-pytest-parametrize"
  },
  {
   "id": "py-ruff-gate",
   "level": "codebase",
   "severity": "should-fix",
   "concerns": [
    "maintainability"
   ],
   "topics": [
    "python",
    "tooling"
   ],
   "rule": "Enable the Ruff rule sets E, F, I, B, UP, SIM, BLE, TID and D in CI.",
   "url": "https://goodcodereview.com/pack-python#py-ruff-gate"
  },
  {
   "id": "py-task-reference",
   "level": "service",
   "severity": "should-fix",
   "concerns": [
    "correctness"
   ],
   "topics": [
    "asyncio",
    "concurrency"
   ],
   "rule": "Never discard the result of `create_task`; keep a reference and surface its exceptions, preferably through a `TaskGroup`.",
   "url": "https://goodcodereview.com/pack-python#py-task-reference"
  },
  {
   "id": "py-test-hygiene",
   "level": "module",
   "severity": "discuss",
   "concerns": [
    "testing",
    "reliability"
   ],
   "topics": [
    "python"
   ],
   "rule": "Keep unit tests off external I/O (the network, the shared filesystem and the database) and off the real clock, and run tests that need them in a separate, slower tier.",
   "url": "https://goodcodereview.com/pack-python#py-test-hygiene"
  },
  {
   "id": "py-xdist-worker-isolated-state",
   "level": "module",
   "severity": "should-fix",
   "concerns": [
    "testing",
    "reliability"
   ],
   "topics": [
    "python",
    "parallelism"
   ],
   "rule": "Under pytest-xdist, give each worker its own database or other mutable resource, keyed by `worker_id`, and build an expensive shared one once with a lock file.",
   "url": "https://goodcodereview.com/pack-python#py-xdist-worker-isolated-state"
  }
 ]
}
