vanara 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +14 -0
  2. package/bin/vanara.js +66 -2
  3. package/catalog/agents/api-designer/AGENT.md +140 -0
  4. package/catalog/agents/api-designer/examples/openapi-snippet.yaml +130 -0
  5. package/catalog/agents/api-designer/examples/review-notes.md +61 -0
  6. package/catalog/agents/api-designer/references/contract-and-openapi.md +82 -0
  7. package/catalog/agents/api-designer/references/design-checklist.md +68 -0
  8. package/catalog/agents/api-designer/references/versioning-and-evolution.md +63 -0
  9. package/catalog/agents/api-designer/scripts/lint-openapi.mjs +180 -0
  10. package/catalog/agents/code-reviewer/AGENT.md +168 -0
  11. package/catalog/agents/code-reviewer/examples/pr-comment-template.md +48 -0
  12. package/catalog/agents/code-reviewer/examples/sample-review-output.md +38 -0
  13. package/catalog/agents/code-reviewer/references/review-checklist.md +46 -0
  14. package/catalog/agents/code-reviewer/references/security-review.md +62 -0
  15. package/catalog/agents/code-reviewer/references/severity-rubric.md +63 -0
  16. package/catalog/agents/code-reviewer/scripts/review-guard.mjs +102 -0
  17. package/catalog/agents/debugger/AGENT.md +112 -0
  18. package/catalog/agents/debugger/examples/postmortem-template.md +59 -0
  19. package/catalog/agents/debugger/examples/repro-template.md +50 -0
  20. package/catalog/agents/debugger/references/bisection.md +63 -0
  21. package/catalog/agents/debugger/references/debugging-method.md +57 -0
  22. package/catalog/agents/debugger/references/observability.md +61 -0
  23. package/catalog/agents/debugger/scripts/parse-stacktrace.mjs +109 -0
  24. package/catalog/agents/pr-summarizer/AGENT.md +156 -0
  25. package/catalog/agents/pr-summarizer/examples/sample-pr-summary.md +46 -0
  26. package/catalog/agents/pr-summarizer/examples/weak-vs-strong-summary.md +68 -0
  27. package/catalog/agents/pr-summarizer/references/identifying-risk.md +68 -0
  28. package/catalog/agents/pr-summarizer/references/reading-the-diff.md +68 -0
  29. package/catalog/agents/pr-summarizer/references/test-plan-and-missing-tests.md +64 -0
  30. package/catalog/agents/pr-summarizer/references/writing-the-summary.md +63 -0
  31. package/catalog/agents/pr-summarizer/scripts/diff-risk.mjs +111 -0
  32. package/catalog/agents/refactoring-specialist/AGENT.md +185 -0
  33. package/catalog/agents/refactoring-specialist/examples/before-after.md +91 -0
  34. package/catalog/agents/refactoring-specialist/examples/refactor-plan.md +97 -0
  35. package/catalog/agents/refactoring-specialist/references/large-scale-refactor.md +50 -0
  36. package/catalog/agents/refactoring-specialist/references/safe-workflow.md +75 -0
  37. package/catalog/agents/refactoring-specialist/references/smell-catalog.md +76 -0
  38. package/catalog/agents/refactoring-specialist/scripts/detect-smells.mjs +150 -0
  39. package/catalog/agents/security-auditor/AGENT.md +168 -0
  40. package/catalog/agents/security-auditor/examples/audit-report.md +68 -0
  41. package/catalog/agents/security-auditor/examples/finding-template.md +31 -0
  42. package/catalog/agents/security-auditor/references/audit-workflow.md +116 -0
  43. package/catalog/agents/security-auditor/references/severity-and-reporting.md +56 -0
  44. package/catalog/agents/security-auditor/references/vuln-classes.md +129 -0
  45. package/catalog/agents/security-auditor/scripts/scan-secrets.mjs +86 -0
  46. package/catalog/agents/technical-writer/AGENT.md +163 -0
  47. package/catalog/agents/technical-writer/examples/how-to-example.md +76 -0
  48. package/catalog/agents/technical-writer/examples/reference-example.md +75 -0
  49. package/catalog/agents/technical-writer/references/clarity-and-style.md +52 -0
  50. package/catalog/agents/technical-writer/references/diataxis-and-doc-types.md +61 -0
  51. package/catalog/agents/technical-writer/references/structure-and-maintenance.md +59 -0
  52. package/catalog/agents/technical-writer/scripts/readability.mjs +103 -0
  53. package/catalog/agents/test-author/AGENT.md +177 -0
  54. package/catalog/agents/test-author/examples/test-plan.md +54 -0
  55. package/catalog/agents/test-author/examples/unit-test-example.ts +55 -0
  56. package/catalog/agents/test-author/references/aaa-and-naming.md +75 -0
  57. package/catalog/agents/test-author/references/mocking-and-fixtures.md +94 -0
  58. package/catalog/agents/test-author/references/test-types-and-pyramid.md +60 -0
  59. package/catalog/agents/test-author/scripts/check-coverage.mjs +145 -0
  60. package/catalog/agents/threat-modeler/AGENT.md +163 -0
  61. package/catalog/agents/threat-modeler/examples/dfd-example.md +55 -0
  62. package/catalog/agents/threat-modeler/examples/threat-model.md +81 -0
  63. package/catalog/agents/threat-modeler/references/dfd-and-trust-boundaries.md +76 -0
  64. package/catalog/agents/threat-modeler/references/mitigation-catalog.md +77 -0
  65. package/catalog/agents/threat-modeler/references/stride-method.md +68 -0
  66. package/catalog/agents/threat-modeler/scripts/stride-checklist.mjs +183 -0
  67. package/catalog/agents/vuln-scanner/AGENT.md +146 -0
  68. package/catalog/agents/vuln-scanner/examples/finding-template.md +57 -0
  69. package/catalog/agents/vuln-scanner/examples/scan-report.md +49 -0
  70. package/catalog/agents/vuln-scanner/references/remediation-and-severity.md +68 -0
  71. package/catalog/agents/vuln-scanner/references/scan-types-and-tools.md +83 -0
  72. package/catalog/agents/vuln-scanner/references/triage-and-false-positives.md +73 -0
  73. package/catalog/agents/vuln-scanner/scripts/parse-scan-results.mjs +133 -0
  74. package/catalog/packs/code-review-pack/PACK.md +100 -0
  75. package/catalog/packs/code-review-pack/examples/pr-flow-example.md +50 -0
  76. package/catalog/packs/code-review-pack/references/rollout-guide.md +40 -0
  77. package/catalog/packs/security-pack/PACK.md +128 -0
  78. package/catalog/packs/security-pack/examples/owasp-vuln-triage-and-fix.md +66 -0
  79. package/catalog/packs/security-pack/examples/threat-model-then-audit.md +77 -0
  80. package/catalog/packs/security-pack/references/choosing-the-right-tool.md +37 -0
  81. package/catalog/packs/security-pack/references/threat-model-to-remediation.md +69 -0
  82. package/catalog/packs/security-pack/references/workflow.md +56 -0
  83. package/catalog/skills/api-pagination/SKILL.md +83 -0
  84. package/catalog/skills/api-pagination/examples/keyset-queries.sql +38 -0
  85. package/catalog/skills/api-pagination/examples/response-shapes.md +51 -0
  86. package/catalog/skills/api-pagination/references/consuming-pages.md +39 -0
  87. package/catalog/skills/api-pagination/references/counting-and-totals.md +41 -0
  88. package/catalog/skills/api-pagination/references/cursor-encoding.md +34 -0
  89. package/catalog/skills/api-pagination/scripts/check-cursor.mjs +51 -0
  90. package/catalog/skills/caching-strategies/SKILL.md +180 -0
  91. package/catalog/skills/caching-strategies/examples/http-cache-headers.md +82 -0
  92. package/catalog/skills/caching-strategies/examples/redis-cache-aside.js +110 -0
  93. package/catalog/skills/caching-strategies/references/cache-patterns.md +93 -0
  94. package/catalog/skills/caching-strategies/references/eviction-and-ttl.md +67 -0
  95. package/catalog/skills/caching-strategies/references/invalidation-and-stampede.md +99 -0
  96. package/catalog/skills/caching-strategies/scripts/ttl-jitter.mjs +99 -0
  97. package/catalog/skills/conventional-commits/SKILL.md +135 -0
  98. package/catalog/skills/conventional-commits/examples/commit-examples.md +60 -0
  99. package/catalog/skills/conventional-commits/examples/commitlint.config.js +31 -0
  100. package/catalog/skills/conventional-commits/references/breaking-changes-semver.md +50 -0
  101. package/catalog/skills/conventional-commits/references/scoping-commits.md +42 -0
  102. package/catalog/skills/conventional-commits/references/spec.md +78 -0
  103. package/catalog/skills/conventional-commits/scripts/lint-commit.mjs +97 -0
  104. package/catalog/skills/database-migrations/SKILL.md +137 -0
  105. package/catalog/skills/database-migrations/examples/add-column-safe.sql +34 -0
  106. package/catalog/skills/database-migrations/examples/migration-config.example.json +27 -0
  107. package/catalog/skills/database-migrations/references/expand-contract.md +74 -0
  108. package/catalog/skills/database-migrations/references/rollback-and-safety.md +71 -0
  109. package/catalog/skills/database-migrations/references/zero-downtime-changes.md +84 -0
  110. package/catalog/skills/database-migrations/scripts/check-migration-reversible.mjs +139 -0
  111. package/catalog/skills/error-handling-patterns/SKILL.md +136 -0
  112. package/catalog/skills/error-handling-patterns/examples/express-error-middleware.js +93 -0
  113. package/catalog/skills/error-handling-patterns/examples/result-pattern.ts +81 -0
  114. package/catalog/skills/error-handling-patterns/references/error-taxonomy.md +91 -0
  115. package/catalog/skills/error-handling-patterns/references/language-patterns.md +102 -0
  116. package/catalog/skills/error-handling-patterns/references/retry-and-backoff.md +76 -0
  117. package/catalog/skills/error-handling-patterns/scripts/lint-empty-catch.mjs +113 -0
  118. package/catalog/skills/git-collaboration-workflows/SKILL.md +104 -0
  119. package/catalog/skills/git-collaboration-workflows/examples/branch-protection.md +48 -0
  120. package/catalog/skills/git-collaboration-workflows/examples/pr-review-playbook.md +48 -0
  121. package/catalog/skills/git-collaboration-workflows/references/branching-models.md +52 -0
  122. package/catalog/skills/git-collaboration-workflows/references/history-hygiene.md +44 -0
  123. package/catalog/skills/git-collaboration-workflows/scripts/check-branch-hygiene.mjs +62 -0
  124. package/catalog/skills/owasp-top10/SKILL.md +112 -0
  125. package/catalog/skills/owasp-top10/examples/sql-injection-fix.md +33 -0
  126. package/catalog/skills/owasp-top10/examples/xss-fix.md +27 -0
  127. package/catalog/skills/owasp-top10/references/access-control.md +36 -0
  128. package/catalog/skills/owasp-top10/references/crypto-failures.md +29 -0
  129. package/catalog/skills/owasp-top10/references/injection.md +39 -0
  130. package/catalog/skills/owasp-top10/references/ssrf-and-design.md +35 -0
  131. package/catalog/skills/owasp-top10/scripts/scan-injection.mjs +73 -0
  132. package/catalog/skills/prompt-engineering/SKILL.md +100 -0
  133. package/catalog/skills/prompt-engineering/examples/classification-prompt.md +29 -0
  134. package/catalog/skills/prompt-engineering/examples/extraction-prompt.md +25 -0
  135. package/catalog/skills/prompt-engineering/references/prompt-injection.md +34 -0
  136. package/catalog/skills/prompt-engineering/references/structured-output.md +34 -0
  137. package/catalog/skills/prompt-engineering/references/techniques.md +33 -0
  138. package/catalog/skills/prompt-engineering/scripts/validate-output.mjs +71 -0
  139. package/catalog/skills/readme-writing/SKILL.md +176 -0
  140. package/catalog/skills/readme-writing/examples/README.template.md +73 -0
  141. package/catalog/skills/readme-writing/examples/good-readme-example.md +95 -0
  142. package/catalog/skills/readme-writing/references/anatomy.md +107 -0
  143. package/catalog/skills/readme-writing/references/maintenance.md +68 -0
  144. package/catalog/skills/readme-writing/references/writing-style.md +79 -0
  145. package/catalog/skills/readme-writing/scripts/lint-readme.mjs +117 -0
  146. package/catalog/skills/refactoring-patterns/SKILL.md +178 -0
  147. package/catalog/skills/refactoring-patterns/examples/extract-function.before-after.js +57 -0
  148. package/catalog/skills/refactoring-patterns/examples/replace-conditional-with-polymorphism.before-after.ts +63 -0
  149. package/catalog/skills/refactoring-patterns/references/code-smells.md +92 -0
  150. package/catalog/skills/refactoring-patterns/references/refactoring-catalog.md +78 -0
  151. package/catalog/skills/refactoring-patterns/references/safe-workflow.md +74 -0
  152. package/catalog/skills/refactoring-patterns/scripts/detect-smells.mjs +137 -0
  153. package/catalog/skills/rest-api-design/SKILL.md +147 -0
  154. package/catalog/skills/rest-api-design/examples/error-envelope.json +26 -0
  155. package/catalog/skills/rest-api-design/examples/orders-api.openapi.yaml +106 -0
  156. package/catalog/skills/rest-api-design/references/error-handling.md +43 -0
  157. package/catalog/skills/rest-api-design/references/pagination.md +41 -0
  158. package/catalog/skills/rest-api-design/references/status-codes.md +32 -0
  159. package/catalog/skills/rest-api-design/references/versioning.md +31 -0
  160. package/catalog/skills/rest-api-design/scripts/check-envelope.mjs +62 -0
  161. package/catalog/skills/secrets-management/SKILL.md +134 -0
  162. package/catalog/skills/secrets-management/examples/env-example.md +41 -0
  163. package/catalog/skills/secrets-management/examples/rotation-runbook.md +50 -0
  164. package/catalog/skills/secrets-management/references/leak-response.md +47 -0
  165. package/catalog/skills/secrets-management/references/rotation.md +46 -0
  166. package/catalog/skills/secrets-management/references/secret-managers.md +52 -0
  167. package/catalog/skills/secrets-management/scripts/detect-hardcoded.mjs +96 -0
  168. package/catalog/skills/secure-auth/SKILL.md +135 -0
  169. package/catalog/skills/secure-auth/examples/auth-flow.md +60 -0
  170. package/catalog/skills/secure-auth/examples/jwt-verify.ts +89 -0
  171. package/catalog/skills/secure-auth/references/auth-attacks.md +76 -0
  172. package/catalog/skills/secure-auth/references/oauth2-oidc.md +65 -0
  173. package/catalog/skills/secure-auth/references/password-hashing.md +70 -0
  174. package/catalog/skills/secure-auth/references/sessions-vs-jwt.md +69 -0
  175. package/catalog/skills/secure-auth/scripts/check-password-policy.mjs +114 -0
  176. package/catalog/skills/sql-index-tuning/SKILL.md +171 -0
  177. package/catalog/skills/sql-index-tuning/examples/explain-walkthrough.sql +91 -0
  178. package/catalog/skills/sql-index-tuning/examples/index-ddl.sql +67 -0
  179. package/catalog/skills/sql-index-tuning/references/btree-internals.md +58 -0
  180. package/catalog/skills/sql-index-tuning/references/composite-and-covering.md +60 -0
  181. package/catalog/skills/sql-index-tuning/references/reading-explain.md +54 -0
  182. package/catalog/skills/sql-index-tuning/references/selectivity-and-cardinality.md +62 -0
  183. package/catalog/skills/sql-index-tuning/scripts/suggest-index.mjs +213 -0
  184. package/catalog/skills/test-plan-design/SKILL.md +154 -0
  185. package/catalog/skills/test-plan-design/examples/test-case-template.md +45 -0
  186. package/catalog/skills/test-plan-design/examples/test-plan.md +57 -0
  187. package/catalog/skills/test-plan-design/references/case-design.md +79 -0
  188. package/catalog/skills/test-plan-design/references/risk-prioritization.md +58 -0
  189. package/catalog/skills/test-plan-design/references/test-pyramid.md +58 -0
  190. package/catalog/skills/test-plan-design/scripts/coverage-gaps.mjs +109 -0
  191. package/free-tier.json +15 -0
  192. package/package.json +15 -4
  193. package/premium-index.json +1 -0
  194. package/src/config.js +31 -1
  195. package/src/license.js +143 -0
@@ -0,0 +1,63 @@
1
+ # Versioning & Evolution
2
+
3
+ APIs are forever once published: a consumer you've never met may depend on any field you expose. Design
4
+ so you can **add without breaking**, and version explicitly when you must break.
5
+
6
+ ## Choosing a versioning strategy
7
+
8
+ | Strategy | Example | Pros | Cons |
9
+ |---|---|---|---|
10
+ | **URI path** | `/v1/orders` | Operationally clearest; trivial to route, cache, log | Version in every URL; "ugly" to purists |
11
+ | **Header** | `Accept: application/vnd.api.v2+json` | Clean URLs; content-negotiation native | Invisible in logs/caches; easy to get wrong |
12
+ | **Query param** | `/orders?version=2` | Simple | Pollutes caching; easy to omit |
13
+
14
+ **Default recommendation: URI path versioning** (`/v1/...`). It is the most operationally legible —
15
+ you can see the version in every request log, route it at the gateway, and cache it cleanly. Reserve
16
+ header-based versioning for APIs where URL stability is a hard requirement.
17
+
18
+ Version the **major** number only. Minor, backward-compatible changes ship within the same version.
19
+
20
+ ## Additive (safe) vs breaking (needs a new version)
21
+
22
+ **Safe — ship within the current version:**
23
+
24
+ - Adding a new endpoint.
25
+ - Adding a new **optional** request field (with a sensible default).
26
+ - Adding a new field to a response (clients must ignore unknown fields — the *tolerant reader* rule).
27
+ - Adding a new optional query parameter.
28
+ - Adding a new enum value **only if** clients are documented to tolerate unknown values.
29
+
30
+ **Breaking — requires a new major version:**
31
+
32
+ - Removing or renaming a field (request or response).
33
+ - Changing a field's type or its meaning.
34
+ - Making a previously optional request field required.
35
+ - Tightening validation so previously valid requests now fail.
36
+ - Changing default behavior, pagination style, or the error shape.
37
+ - Removing an endpoint or changing its URL/method.
38
+
39
+ ## The tolerant reader contract
40
+
41
+ Tell consumers, in the docs, that they **must ignore unknown fields** and tolerate new enum values. This
42
+ single rule turns a whole class of otherwise-breaking changes (adding fields, adding enum members) into
43
+ safe additive ones. State it explicitly — you cannot rely on behavior you never published.
44
+
45
+ ## Deprecation playbook
46
+
47
+ When a breaking change is unavoidable:
48
+
49
+ 1. **Ship the new version** (`/v2`) alongside the old. Never break `/v1` in place.
50
+ 2. **Announce** in the changelog and to known consumers, with a concrete sunset date.
51
+ 3. **Signal at runtime.** Return a `Deprecation: true` header and a `Sunset: <date>` header on the old
52
+ endpoints; optionally add a `Warning` header.
53
+ 4. **Monitor usage** of the old version so you know who still depends on it.
54
+ 5. **Sunset** only after traffic to the old version has fallen to near zero or the announced date passes.
55
+
56
+ ## Anti-patterns
57
+
58
+ - **Breaking `/v1` in place** "because only a few clients use that field" — you cannot know who depends
59
+ on it; that's the whole point of a published contract.
60
+ - **Versioning per endpoint** — a patchwork of `/orders/v2` and `/users/v3` is unnavigable. Version the
61
+ API surface, not individual routes.
62
+ - **Infinite versions** — every major version is an operational and support cost. Deprecate aggressively
63
+ once a successor is stable.
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env node
2
+ // Runnable check: validates that an OpenAPI document (supplied as JSON) has the
3
+ // load-bearing required fields. Zero dependencies — JSON in, no YAML parser — so it
4
+ // runs anywhere Node does. Demonstrates an *executed*, verifiable asset for the
5
+ // api-designer agent.
6
+ //
7
+ // Checks:
8
+ // - "openapi" version string is present
9
+ // - info.title and info.version are non-empty strings
10
+ // - "paths" is an object
11
+ // - every operation's responses object is non-empty and each response carries a
12
+ // schema or a description (so the contract documents its outcomes)
13
+ //
14
+ // Usage:
15
+ // node lint-openapi.mjs path/to/openapi.json # lint a JSON file
16
+ // cat openapi.json | node lint-openapi.mjs # lint from stdin
17
+ // node lint-openapi.mjs --selftest # run built-in cases (exit 0/1)
18
+
19
+ import { readFile } from 'node:fs/promises';
20
+
21
+ const HTTP_METHODS = ['get', 'put', 'post', 'delete', 'patch', 'options', 'head', 'trace'];
22
+
23
+ function isNonEmptyString(v) {
24
+ return typeof v === 'string' && v.trim().length > 0;
25
+ }
26
+
27
+ function isObject(v) {
28
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
29
+ }
30
+
31
+ export function lintOpenApi(doc) {
32
+ const errors = [];
33
+
34
+ if (!isObject(doc)) {
35
+ return { ok: false, errors: ['document is not a JSON object'] };
36
+ }
37
+
38
+ if (!isNonEmptyString(doc.openapi)) {
39
+ errors.push('missing "openapi" version string');
40
+ }
41
+
42
+ if (!isObject(doc.info)) {
43
+ errors.push('missing "info" object');
44
+ } else {
45
+ if (!isNonEmptyString(doc.info.title)) errors.push('missing "info.title"');
46
+ if (!isNonEmptyString(doc.info.version)) errors.push('missing "info.version"');
47
+ }
48
+
49
+ if (!isObject(doc.paths)) {
50
+ errors.push('missing "paths" object');
51
+ } else {
52
+ for (const [path, item] of Object.entries(doc.paths)) {
53
+ if (!isObject(item)) {
54
+ errors.push(`path "${path}" is not an object`);
55
+ continue;
56
+ }
57
+ const operations = Object.entries(item).filter(([m]) => HTTP_METHODS.includes(m));
58
+ for (const [method, op] of operations) {
59
+ const where = `${method.toUpperCase()} ${path}`;
60
+ if (!isObject(op.responses) || Object.keys(op.responses).length === 0) {
61
+ errors.push(`operation "${where}" has no responses`);
62
+ continue;
63
+ }
64
+ for (const [code, res] of Object.entries(op.responses)) {
65
+ if (!isObject(res)) {
66
+ errors.push(`response ${code} on "${where}" is not an object`);
67
+ continue;
68
+ }
69
+ const hasSchema = isObject(res.content) || '$ref' in res;
70
+ const hasDescription = isNonEmptyString(res.description);
71
+ if (!hasSchema && !hasDescription) {
72
+ errors.push(`response ${code} on "${where}" lacks a schema or description`);
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+
79
+ return { ok: errors.length === 0, errors };
80
+ }
81
+
82
+ function report(label, doc) {
83
+ const { ok, errors } = lintOpenApi(doc);
84
+ if (ok) {
85
+ console.log(`✓ ${label}: valid OpenAPI document (required fields present)`);
86
+ } else {
87
+ console.error(`✗ ${label}: ${errors.length} problem(s):`);
88
+ errors.forEach((e) => console.error(` - ${e}`));
89
+ }
90
+ return ok;
91
+ }
92
+
93
+ function parse(label, text) {
94
+ try {
95
+ return JSON.parse(text);
96
+ } catch {
97
+ console.error(`✗ ${label}: invalid JSON`);
98
+ return undefined;
99
+ }
100
+ }
101
+
102
+ function selftest() {
103
+ const valid = {
104
+ openapi: '3.1.0',
105
+ info: { title: 'Orders API', version: '1.0.0' },
106
+ paths: {
107
+ '/orders': {
108
+ get: {
109
+ summary: 'List orders',
110
+ responses: {
111
+ 200: { description: 'A page of orders' },
112
+ 401: { $ref: '#/components/responses/Error' },
113
+ },
114
+ },
115
+ post: {
116
+ summary: 'Create an order',
117
+ responses: { 201: { content: { 'application/json': {} } } },
118
+ },
119
+ },
120
+ },
121
+ };
122
+
123
+ const invalidNoInfoVersion = {
124
+ openapi: '3.1.0',
125
+ info: { title: 'Orders API' }, // missing version
126
+ paths: {},
127
+ };
128
+
129
+ const invalidNoOpenapi = {
130
+ info: { title: 'X', version: '1.0.0' },
131
+ paths: { '/x': { get: { responses: { 200: { description: 'ok' } } } } },
132
+ };
133
+
134
+ const invalidEmptyResponses = {
135
+ openapi: '3.1.0',
136
+ info: { title: 'X', version: '1.0.0' },
137
+ paths: { '/x': { get: { summary: 'no responses', responses: {} } } },
138
+ };
139
+
140
+ const invalidResponseNoSchema = {
141
+ openapi: '3.1.0',
142
+ info: { title: 'X', version: '1.0.0' },
143
+ paths: { '/x': { get: { responses: { 200: {} } } } }, // no schema or description
144
+ };
145
+
146
+ const cases = [
147
+ ['valid full doc', valid, true],
148
+ ['missing info.version', invalidNoInfoVersion, false],
149
+ ['missing openapi field', invalidNoOpenapi, false],
150
+ ['empty responses', invalidEmptyResponses, false],
151
+ ['response without schema/description', invalidResponseNoSchema, false],
152
+ ];
153
+
154
+ let allExpected = true;
155
+ for (const [name, doc, shouldPass] of cases) {
156
+ const { ok } = lintOpenApi(doc);
157
+ const correct = ok === shouldPass;
158
+ allExpected = allExpected && correct;
159
+ console.log(
160
+ `${correct ? '✓' : '✗'} selftest ${name}: ${ok ? 'valid' : 'invalid'} (expected ${shouldPass ? 'valid' : 'invalid'})`,
161
+ );
162
+ }
163
+ process.exit(allExpected ? 0 : 1);
164
+ }
165
+
166
+ const arg = process.argv[2];
167
+ if (arg === '--selftest') {
168
+ selftest();
169
+ } else if (arg) {
170
+ const text = await readFile(arg, 'utf8');
171
+ const doc = parse(arg, text);
172
+ process.exit(doc !== undefined && report(arg, doc) ? 0 : 1);
173
+ } else {
174
+ let buf = '';
175
+ process.stdin.on('data', (c) => (buf += c));
176
+ process.stdin.on('end', () => {
177
+ const doc = parse('stdin', buf);
178
+ process.exit(doc !== undefined && report('stdin', doc) ? 0 : 1);
179
+ });
180
+ }
@@ -0,0 +1,168 @@
1
+ ---
2
+ name: code-reviewer
3
+ description: Use PROACTIVELY immediately after writing or modifying code, and before any commit to a shared branch. Reviews a diff the way a senior engineer would — security first, then correctness, then maintainability — and reports findings by severity (CRITICAL/HIGH/MEDIUM/LOW) with a concrete file:line → fix for each.
4
+ tools: Read, Grep, Glob, Bash
5
+ model: claude-sonnet-4-6
6
+ type: agent
7
+ version: 2.0.0
8
+ updated: 2026-06-29
9
+ ---
10
+ # Code Reviewer
11
+
12
+ You are a **senior staff engineer doing code review**. Your job is to protect the codebase from
13
+ defects, security holes, and maintainability decay — without slowing the team down with noise. You
14
+ review the way the best reviewers do: you read the *change*, you reason about *risk*, and you give
15
+ every comment a severity and a concrete fix. You never rubber-stamp, and you never bury a real bug
16
+ under a pile of style nitpicks.
17
+
18
+ A review is **trustworthy** when every finding is real, points at a specific line, and ships with a
19
+ fix the author can apply. That is the bar. If the code is clean, you say so plainly and approve.
20
+
21
+ ## Role and operating principles
22
+
23
+ - **Risk-ordered, not file-ordered.** A SQL injection on line 200 matters more than a naming nit on
24
+ line 4. Lead with what can hurt.
25
+ - **Evidence over opinion.** Every finding cites `file:line` and quotes the offending code. No
26
+ vibes-based comments.
27
+ - **Fix, don't just complain.** Each finding proposes the corrected code or a precise action.
28
+ - **Scope discipline.** Review the diff and what it touches. Don't redesign the system in a review.
29
+ - **Calibrated severity.** Most comments are MEDIUM/LOW. CRITICAL/HIGH should be rare and defensible.
30
+
31
+ ## Step-by-step review workflow
32
+
33
+ Follow these in order. Do not skip security to get to style.
34
+
35
+ 1. **Establish the change set.** Run `git diff` (or `git diff <base>...HEAD`), or read the modified
36
+ files directly. Understand *what* changed and *why* before judging *how*. If the intent is
37
+ unclear, note it as a question rather than guessing.
38
+ 2. **Security pass (first, always).** Scan for: injection (SQL/command/template/XSS), missing or
39
+ broken authorization (IDOR — ownership not checked, only authentication), hardcoded secrets,
40
+ unsafe deserialization, path traversal, SSRF, weak crypto, and unvalidated input crossing a trust
41
+ boundary. See `references/security-review.md`.
42
+ 3. **Correctness pass.** Logic errors, unhandled error paths, swallowed exceptions, race conditions,
43
+ off-by-one, null/undefined dereferences, resource leaks (unclosed handles/connections), and
44
+ incorrect edge-case handling.
45
+ 4. **Maintainability pass.** Function length (<50 lines), file size (<800 lines), nesting depth
46
+ (>4 is a smell), naming, duplication (DRY), dead code, and unclear control flow. Use
47
+ `scripts/review-guard.mjs` to flag oversized functions/files mechanically.
48
+ 5. **Tests pass.** Does new behavior have tests? Do tests assert behavior (not implementation)? Are
49
+ error paths and edge cases covered? Flag missing coverage as HIGH for risky code paths.
50
+ 6. **Self-verification (maker-checker).** Re-read your own findings before emitting them. For each:
51
+ does it point at a line that actually exists in the diff? Is the described problem real (not a
52
+ misread of the surrounding context)? Is the proposed fix correct and minimal? Delete anything you
53
+ cannot defend. This step is what separates a useful review from noise.
54
+
55
+ See `references/review-checklist.md` for the full per-category checklist.
56
+
57
+ ## Severity rubric
58
+
59
+ Assign exactly one severity per finding. The full rubric with examples lives in
60
+ `references/severity-rubric.md`; the summary:
61
+
62
+ | Severity | Meaning | Required action |
63
+ |---|---|---|
64
+ | **CRITICAL** | Exploitable vuln or data-loss/corruption risk | **Block merge.** Must fix. |
65
+ | **HIGH** | Real bug or significant quality/security risk | Fix before merge. |
66
+ | **MEDIUM** | Maintainability or minor correctness concern | Should fix; author's call if deferred. |
67
+ | **LOW** | Style, naming, micro-improvement | Optional; never blocks. |
68
+
69
+ End every review with one verdict: **Approve** / **Approve-with-nits** / **Request-changes** /
70
+ **Block**.
71
+
72
+ ## Output format
73
+
74
+ Group findings by severity, highest first. Each finding is one block: a `file:line` anchor, the
75
+ problem, and the fix. Then a one-line verdict and a short summary.
76
+
77
+ ```md
78
+ ## Code Review — <branch or PR title>
79
+
80
+ ### CRITICAL
81
+ - `auth/session.js:42` — Session token compared with `==`, vulnerable to timing attack and type
82
+ coercion (`"0" == 0`). **Fix:** use `crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))`.
83
+
84
+ ### HIGH
85
+ - `orders/repo.js:88` — User-supplied `sort` interpolated into SQL → injection. **Fix:** whitelist
86
+ allowed columns; bind values as parameters.
87
+
88
+ ### MEDIUM
89
+ - `orders/service.js:12-71` — `processOrder` is 59 lines doing 3 jobs. **Fix:** extract
90
+ `validate()`, `charge()`, `persist()`.
91
+
92
+ ### LOW
93
+ - `orders/service.js:5` — `const d` → rename to `createdAt` for clarity.
94
+
95
+ **Verdict: Request-changes** — 1 critical, 1 high block merge; medium/low can follow up.
96
+ Summary: logic is sound; the SQL and session-compare issues are the blockers.
97
+ ```
98
+
99
+ ### Worked example: a finding from problem to fix
100
+
101
+ Given this diff hunk:
102
+
103
+ ```js
104
+ // users/controller.js
105
+ app.get('/users/:id/invoices', async (req, res) => {
106
+ const invoices = await db.invoices.findByUser(req.params.id); // line 31
107
+ res.json({ data: invoices });
108
+ });
109
+ ```
110
+
111
+ The review finding:
112
+
113
+ ```md
114
+ ### CRITICAL
115
+ - `users/controller.js:31` — IDOR: any authenticated user can read another user's invoices by
116
+ changing `:id`. Ownership is never checked against the session. **Fix:**
117
+ `if (req.params.id !== req.session.userId) return res.status(404).end();` (404 not 403 to avoid
118
+ leaking existence), then query.
119
+ ```
120
+
121
+ ## Common pitfalls (failure modes to avoid)
122
+
123
+ These are the ways reviews go wrong. Actively guard against each:
124
+
125
+ - **Rubber-stamping.** Approving without reading the diff, or "LGTM" on a change you didn't trace.
126
+ Every approval must be earned by an actual read. If you didn't look, don't approve.
127
+ - **Nitpicking style over substance.** Drowning a security bug under ten LOW naming comments. Lead
128
+ with risk; keep LOW comments few and clearly optional.
129
+ - **Inventing issues to look thorough.** Reporting problems that aren't real, or flagging a "bug"
130
+ that's actually correct once you read the surrounding code. The maker-checker step exists to catch
131
+ this — if you can't point at the line and explain the concrete failure, cut it.
132
+ - **Missing the security pass.** Jumping straight to readability and never checking authz/injection/
133
+ secrets. Security is step 2 for a reason — do it first, every time.
134
+ - **Severity inflation.** Marking a naming nit HIGH, or a real injection MEDIUM. Miscalibrated
135
+ severity makes the whole review untrustworthy. Calibrate against the rubric.
136
+ - **Out-of-scope redesign.** Demanding an architectural rewrite in a 20-line bugfix PR. Note larger
137
+ concerns separately as non-blocking observations.
138
+ - **Vague comments.** "This could be better" with no line and no fix. Useless. Always anchor + fix.
139
+
140
+ ## When NOT to use / boundaries
141
+
142
+ - **Not a build/test runner.** If the goal is to make a failing build green, use the
143
+ `build-error-resolver` agent. You review code; you don't chase compiler errors.
144
+ - **Not a deep security audit.** For threat modeling, full OWASP coverage, or pen-test-style review
145
+ of an auth/payments subsystem, escalate to the `security-auditor` agent. You flag obvious vulns;
146
+ you don't replace a dedicated security audit.
147
+ - **Not for writing the feature.** You don't author the change under review (maker-checker
148
+ separation); you assess someone else's diff.
149
+ - **Not a style-only linter.** Formatting belongs to the project's formatter/linter, not a human
150
+ review. Don't spend the review on whitespace a tool already fixes.
151
+ - **Language-specific depth.** For idiom-heavy languages, pair with the matching reviewer
152
+ (`typescript-reviewer`, `python-reviewer`, `go-reviewer`, `rust-reviewer`) for deeper checks.
153
+
154
+ ## Files in this package
155
+
156
+ - `AGENT.md` — this system prompt: role, workflow, severity rubric, output format, boundaries.
157
+ - `references/review-checklist.md` — the full per-category checklist (security, correctness,
158
+ maintainability, tests).
159
+ - `references/severity-rubric.md` — CRITICAL/HIGH/MEDIUM/LOW with examples and required action.
160
+ - `references/security-review.md` — injection, authz/IDOR, secrets, unsafe deserialization, SSRF.
161
+ - `examples/sample-review-output.md` — a full worked review in the standard format.
162
+ - `examples/pr-comment-template.md` — copy-paste inline PR comment template.
163
+ - `scripts/review-guard.mjs` — runnable Node check that flags oversized functions/files from a
164
+ diff-stat JSON; run with `--selftest`.
165
+
166
+ **Pairs with** the `security-auditor` agent for deep security
167
+ audits, the `owasp-top10` skill for the vulnerability catalogue, and the `error-handling-patterns`
168
+ skill for correct error propagation.
@@ -0,0 +1,48 @@
1
+ # PR Comment Templates
2
+
3
+ Copy-paste templates for leaving review comments. Keep each comment to one finding: an anchor, the
4
+ problem, and the fix.
5
+
6
+ ## Inline comment (single finding)
7
+
8
+ ```md
9
+ **[HIGH]** `path/to/file.js:88`
10
+
11
+ User-supplied `sort` is interpolated into the SQL string, allowing injection.
12
+
13
+ **Fix:** whitelist the sortable columns and bind the value:
14
+ \`\`\`js
15
+ const SORTABLE = { date: 'created_at', total: 'amount' };
16
+ const col = SORTABLE[sort] ?? 'created_at';
17
+ \`\`\`
18
+ ```
19
+
20
+ ## Top-level summary comment
21
+
22
+ ```md
23
+ ## Review summary
24
+
25
+ - **Verdict:** Request-changes
26
+ - **Blocking:** 1 HIGH (SQL injection at `repo.js:88`)
27
+ - **Non-blocking:** 2 MEDIUM, 1 LOW
28
+
29
+ Logic is sound and the tests are well structured. The one blocker is the dynamic sort column —
30
+ once that's whitelisted this is good to merge. Detailed findings are inline.
31
+ ```
32
+
33
+ ## Approval comment (clean change)
34
+
35
+ ```md
36
+ ## Review summary
37
+
38
+ **Verdict: Approve** — read the full diff. Security, correctness, and tests all check out; no
39
+ findings above LOW. Nice, focused change.
40
+ ```
41
+
42
+ ## Nit prefix convention
43
+
44
+ Prefix optional comments with `nit:` so authors know they don't block:
45
+
46
+ ```md
47
+ nit: `const d` → `createdAt` reads more clearly here.
48
+ ```
@@ -0,0 +1,38 @@
1
+ # Sample Review Output
2
+
3
+ A complete review of a hypothetical PR, in the standard format. Use this as the model for tone,
4
+ structure, and the anchor → problem → fix pattern.
5
+
6
+ ---
7
+
8
+ ## Code Review — feat: add invoice export endpoint
9
+
10
+ ### CRITICAL
11
+ - `api/invoices.js:31` — **IDOR.** `findByUser(req.params.id)` returns any user's invoices; ownership
12
+ is never checked against the session. Any logged-in user can read others' financial data.
13
+ **Fix:** `if (req.params.id !== req.session.userId) return res.status(404).end();` before the query
14
+ (404, not 403, to avoid leaking existence).
15
+ - `api/invoices.js:47` — **SQL injection.** `order by ${req.query.sort}` interpolates user input.
16
+ **Fix:** whitelist sortable columns:
17
+ ```js
18
+ const SORTABLE = { date: 'created_at', total: 'amount' };
19
+ const col = SORTABLE[req.query.sort] ?? 'created_at';
20
+ ```
21
+
22
+ ### HIGH
23
+ - `api/invoices.js:58` — Unhandled rejection: `await pdf.render()` has no try/catch; a render failure
24
+ 500s with a stack trace in the body. **Fix:** wrap in try/catch, log server-side, return a generic
25
+ error envelope.
26
+ - `api/invoices.test.js` — No test covers the export path or the authz check. **Fix:** add a test
27
+ asserting a non-owner gets 404 and an owner gets 200.
28
+
29
+ ### MEDIUM
30
+ - `api/invoices.js:20-72` — `exportInvoices` is 52 lines doing auth, query, formatting, and PDF
31
+ rendering. **Fix:** extract `assertOwnership()`, `loadInvoices()`, `renderPdf()`.
32
+
33
+ ### LOW
34
+ - `api/invoices.js:24` — `const r` → rename to `rows` for readability.
35
+
36
+ **Verdict: Block** — two CRITICAL issues (IDOR + SQL injection) must be fixed before merge. The
37
+ HIGH items (error handling + missing tests) should land in the same change. Structure is otherwise
38
+ reasonable; the medium refactor is a nice-to-have.
@@ -0,0 +1,46 @@
1
+ # Review Checklist
2
+
3
+ Work top to bottom. Security first, style last. Anchor every finding to `file:line` with a fix.
4
+
5
+ ## 1. Security (do this first)
6
+
7
+ - [ ] No injection: user input never concatenated into SQL, shell, template, or HTML. Parameterized
8
+ queries / escaped output everywhere.
9
+ - [ ] Authorization checked per action, not just authentication. Ownership verified (no IDOR — see
10
+ `security-review.md`).
11
+ - [ ] No hardcoded secrets (API keys, passwords, tokens, connection strings). Pulled from env/secret
12
+ manager.
13
+ - [ ] No unsafe deserialization of untrusted data (`pickle`, `yaml.load`, native deserializers).
14
+ - [ ] No path traversal: file paths derived from input are normalized and confined to a base dir.
15
+ - [ ] No SSRF: outbound URLs from user input are allow-listed.
16
+ - [ ] Crypto is current: no MD5/SHA1 for passwords, constant-time comparison for secrets, no custom
17
+ crypto.
18
+ - [ ] Error messages don't leak stack traces, secrets, or internal structure to the client.
19
+
20
+ ## 2. Correctness
21
+
22
+ - [ ] Logic does what the PR intends; edge cases (empty, null, zero, max, unicode) handled.
23
+ - [ ] Errors handled explicitly — no swallowed exceptions, no empty `catch {}`, no ignored returns.
24
+ - [ ] No off-by-one / boundary errors in loops and slicing.
25
+ - [ ] No null/undefined dereference on optional paths.
26
+ - [ ] No race conditions on shared state; async results awaited; no unhandled promise rejections.
27
+ - [ ] Resources released (files, sockets, DB connections, locks) on all paths including errors.
28
+ - [ ] No N+1 queries or unbounded loops over external calls.
29
+
30
+ ## 3. Maintainability
31
+
32
+ - [ ] Functions < 50 lines and single-purpose.
33
+ - [ ] Files < 800 lines; cohesive, organized by feature.
34
+ - [ ] Nesting depth ≤ 4; prefer early returns.
35
+ - [ ] Names are descriptive; booleans use is/has/should/can.
36
+ - [ ] No duplication (DRY) where the repetition is real, not speculative.
37
+ - [ ] No dead code, commented-out blocks, or leftover debug logging.
38
+ - [ ] No magic numbers — named constants for thresholds/limits.
39
+
40
+ ## 4. Tests
41
+
42
+ - [ ] New behavior has tests; bug fixes include a regression test.
43
+ - [ ] Tests assert behavior, not implementation details.
44
+ - [ ] Error paths and edge cases are covered, not just the happy path.
45
+ - [ ] Coverage meets the project threshold (commonly 80%) for changed lines.
46
+ - [ ] Tests are deterministic — no sleeps, no order dependence, no shared mutable fixtures.
@@ -0,0 +1,62 @@
1
+ # Security Review
2
+
3
+ The first pass of every review. These are the highest-impact, most-missed classes. Map to OWASP Top
4
+ 10; for a deep audit escalate to the `security-auditor` agent and the `owasp-top10` skill.
5
+
6
+ ## Injection
7
+
8
+ User input must never be interpreted as code/query syntax.
9
+
10
+ ```js
11
+ // BAD — SQL injection
12
+ db.query(`SELECT * FROM orders WHERE status = '${req.query.status}'`);
13
+
14
+ // GOOD — parameterized
15
+ db.query('SELECT * FROM orders WHERE status = $1', [req.query.status]);
16
+ ```
17
+
18
+ - SQL: bind parameters; never string-concatenate. For dynamic columns (sort/filter), **whitelist**
19
+ the allowed set — you can't parameterize an identifier.
20
+ - Command: avoid shelling out with user input; if unavoidable, pass an argv array, never a shell
21
+ string.
22
+ - Template/XSS: escape output by default; treat any HTML built from input as suspect.
23
+
24
+ ## Broken authorization (IDOR)
25
+
26
+ The most common real vuln in CRUD apps. Authentication ≠ authorization.
27
+
28
+ ```js
29
+ // BAD — authenticated, but ownership never checked
30
+ const doc = await db.docs.findById(req.params.id);
31
+
32
+ // GOOD — verify the caller owns the resource
33
+ const doc = await db.docs.findById(req.params.id);
34
+ if (!doc || doc.ownerId !== req.session.userId) return res.status(404).end();
35
+ ```
36
+
37
+ - Check ownership/role on **every** action that reads or mutates a specific resource.
38
+ - Prefer 404 over 403 for resources the caller may not even know exist (avoid leaking existence).
39
+ - Don't trust IDs, roles, or prices sent from the client — re-derive server-side.
40
+
41
+ ## Secrets
42
+
43
+ - No hardcoded keys, tokens, passwords, or connection strings — even in tests or comments.
44
+ - Pull from environment variables or a secret manager; validate presence at startup.
45
+ - If a secret is found in a diff, flag CRITICAL and instruct rotation — committed secrets are
46
+ compromised even if later removed (git history).
47
+
48
+ ## Unsafe deserialization
49
+
50
+ - Never deserialize untrusted data with executable formats: Python `pickle`, `yaml.load` (use
51
+ `safe_load`), Java native serialization, PHP `unserialize` on user input.
52
+ - Prefer JSON with a schema validator at the boundary.
53
+
54
+ ## Other high-value checks
55
+
56
+ - **SSRF:** outbound requests to user-supplied URLs must be allow-listed; block internal IP ranges
57
+ and metadata endpoints (`169.254.169.254`).
58
+ - **Path traversal:** normalize and confine file paths to a base directory; reject `..` segments.
59
+ - **Crypto:** constant-time comparison for tokens (`crypto.timingSafeEqual`); strong, salted hashing
60
+ (argon2/bcrypt/scrypt) for passwords; never MD5/SHA1 for secrets.
61
+ - **Rate limiting:** state-changing and auth endpoints should be rate-limited (return 429).
62
+ - **Error leakage:** no stack traces or internal details in client-facing error responses.
@@ -0,0 +1,63 @@
1
+ # Severity Rubric
2
+
3
+ Every finding gets exactly one severity. Calibration matters more than volume: an inflated severity
4
+ makes the whole review untrustworthy. When unsure between two levels, pick the lower one and explain.
5
+
6
+ ## CRITICAL — Block merge
7
+
8
+ Exploitable vulnerability, data loss, or data corruption. The change must not merge as-is.
9
+
10
+ Examples:
11
+ - SQL/command injection reachable from user input.
12
+ - Authentication bypass or broken authorization (IDOR) exposing other users' data.
13
+ - Hardcoded production secret committed to the repo.
14
+ - A migration or write path that can corrupt or delete data.
15
+ - Unsafe deserialization of untrusted input (RCE class).
16
+
17
+ **Action:** Verdict = Block. Author must fix before merge. Rotate any exposed secret immediately.
18
+
19
+ ## HIGH — Fix before merge
20
+
21
+ A real bug or significant security/quality risk that will bite in production, but not an immediate
22
+ exploit/data-loss.
23
+
24
+ Examples:
25
+ - Unhandled error path that crashes the process on bad input.
26
+ - Race condition on shared state under concurrency.
27
+ - Missing tests on a risky new code path.
28
+ - Resource leak (unclosed connection) under load.
29
+ - XSS via unescaped output in a low-traffic admin view.
30
+
31
+ **Action:** Verdict = Request-changes. Should be fixed before merge.
32
+
33
+ ## MEDIUM — Should fix
34
+
35
+ Maintainability concern or minor correctness issue. Won't cause an outage but adds risk or friction.
36
+
37
+ Examples:
38
+ - A 59-line function doing three jobs.
39
+ - Duplication that will drift.
40
+ - Deep nesting that obscures logic.
41
+ - Missing validation on an internal, low-risk input.
42
+
43
+ **Action:** Fix when reasonable; author may defer with a tracking note.
44
+
45
+ ## LOW — Optional
46
+
47
+ Style, naming, micro-improvements. Never blocks a merge.
48
+
49
+ Examples:
50
+ - A poorly named variable.
51
+ - A comment that's now stale.
52
+ - A spot where a constant would read better than a literal.
53
+
54
+ **Action:** Note as a nit. Verdict can still be Approve-with-nits.
55
+
56
+ ## Verdict mapping
57
+
58
+ | Findings present | Verdict |
59
+ |---|---|
60
+ | Any CRITICAL | Block |
61
+ | Any HIGH (no CRITICAL) | Request-changes |
62
+ | Only MEDIUM/LOW | Approve-with-nits |
63
+ | None | Approve |