@aicqtools/guardrail 1.0.0-alpha.2

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 (269) hide show
  1. package/LICENSE +21 -0
  2. package/dist/docs/build.d.ts +12 -0
  3. package/dist/docs/build.d.ts.map +1 -0
  4. package/dist/docs/build.js +23 -0
  5. package/dist/docs/build.js.map +1 -0
  6. package/dist/docs/index.d.ts +4 -0
  7. package/dist/docs/index.d.ts.map +1 -0
  8. package/dist/docs/index.js +3 -0
  9. package/dist/docs/index.js.map +1 -0
  10. package/dist/docs/render-rule-md.d.ts +4 -0
  11. package/dist/docs/render-rule-md.d.ts.map +1 -0
  12. package/dist/docs/render-rule-md.js +117 -0
  13. package/dist/docs/render-rule-md.js.map +1 -0
  14. package/dist/index.d.ts +12 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +7 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/matcher/index.d.ts +4 -0
  19. package/dist/matcher/index.d.ts.map +1 -0
  20. package/dist/matcher/index.js +3 -0
  21. package/dist/matcher/index.js.map +1 -0
  22. package/dist/matcher/traverse.d.ts +3 -0
  23. package/dist/matcher/traverse.d.ts.map +1 -0
  24. package/dist/matcher/traverse.js +9 -0
  25. package/dist/matcher/traverse.js.map +1 -0
  26. package/dist/matcher/yaml-rule.d.ts +31 -0
  27. package/dist/matcher/yaml-rule.d.ts.map +1 -0
  28. package/dist/matcher/yaml-rule.js +30 -0
  29. package/dist/matcher/yaml-rule.js.map +1 -0
  30. package/dist/mcp/handlers.d.ts +36 -0
  31. package/dist/mcp/handlers.d.ts.map +1 -0
  32. package/dist/mcp/handlers.js +32 -0
  33. package/dist/mcp/handlers.js.map +1 -0
  34. package/dist/mcp/index.d.ts +6 -0
  35. package/dist/mcp/index.d.ts.map +1 -0
  36. package/dist/mcp/index.js +4 -0
  37. package/dist/mcp/index.js.map +1 -0
  38. package/dist/mcp/server.d.ts +9 -0
  39. package/dist/mcp/server.d.ts.map +1 -0
  40. package/dist/mcp/server.js +53 -0
  41. package/dist/mcp/server.js.map +1 -0
  42. package/dist/mcp/stdio.d.ts +3 -0
  43. package/dist/mcp/stdio.d.ts.map +1 -0
  44. package/dist/mcp/stdio.js +8 -0
  45. package/dist/mcp/stdio.js.map +1 -0
  46. package/dist/rules-default/ai-explainability-metadata.d.ts +3 -0
  47. package/dist/rules-default/ai-explainability-metadata.d.ts.map +1 -0
  48. package/dist/rules-default/ai-explainability-metadata.js +41 -0
  49. package/dist/rules-default/ai-explainability-metadata.js.map +1 -0
  50. package/dist/rules-default/api-response-shape.d.ts +3 -0
  51. package/dist/rules-default/api-response-shape.d.ts.map +1 -0
  52. package/dist/rules-default/api-response-shape.js +52 -0
  53. package/dist/rules-default/api-response-shape.js.map +1 -0
  54. package/dist/rules-default/async-await-consistency.d.ts +3 -0
  55. package/dist/rules-default/async-await-consistency.d.ts.map +1 -0
  56. package/dist/rules-default/async-await-consistency.js +38 -0
  57. package/dist/rules-default/async-await-consistency.js.map +1 -0
  58. package/dist/rules-default/audit-log-ai-decision.d.ts +3 -0
  59. package/dist/rules-default/audit-log-ai-decision.d.ts.map +1 -0
  60. package/dist/rules-default/audit-log-ai-decision.js +33 -0
  61. package/dist/rules-default/audit-log-ai-decision.js.map +1 -0
  62. package/dist/rules-default/camelcase-migration-column.d.ts +3 -0
  63. package/dist/rules-default/camelcase-migration-column.d.ts.map +1 -0
  64. package/dist/rules-default/camelcase-migration-column.js +56 -0
  65. package/dist/rules-default/camelcase-migration-column.js.map +1 -0
  66. package/dist/rules-default/controller-needs-async-wrapper.d.ts +3 -0
  67. package/dist/rules-default/controller-needs-async-wrapper.d.ts.map +1 -0
  68. package/dist/rules-default/controller-needs-async-wrapper.js +56 -0
  69. package/dist/rules-default/controller-needs-async-wrapper.js.map +1 -0
  70. package/dist/rules-default/enforce-utf8-encoding.d.ts +10 -0
  71. package/dist/rules-default/enforce-utf8-encoding.d.ts.map +1 -0
  72. package/dist/rules-default/enforce-utf8-encoding.js +28 -0
  73. package/dist/rules-default/enforce-utf8-encoding.js.map +1 -0
  74. package/dist/rules-default/explicit-kst-timezone.d.ts +3 -0
  75. package/dist/rules-default/explicit-kst-timezone.d.ts.map +1 -0
  76. package/dist/rules-default/explicit-kst-timezone.js +49 -0
  77. package/dist/rules-default/explicit-kst-timezone.js.map +1 -0
  78. package/dist/rules-default/fk-needs-on-delete.d.ts +3 -0
  79. package/dist/rules-default/fk-needs-on-delete.d.ts.map +1 -0
  80. package/dist/rules-default/fk-needs-on-delete.js +54 -0
  81. package/dist/rules-default/fk-needs-on-delete.js.map +1 -0
  82. package/dist/rules-default/human-oversight-checkpoint.d.ts +3 -0
  83. package/dist/rules-default/human-oversight-checkpoint.d.ts.map +1 -0
  84. package/dist/rules-default/human-oversight-checkpoint.js +37 -0
  85. package/dist/rules-default/human-oversight-checkpoint.js.map +1 -0
  86. package/dist/rules-default/index.d.ts +6 -0
  87. package/dist/rules-default/index.d.ts.map +1 -0
  88. package/dist/rules-default/index.js +138 -0
  89. package/dist/rules-default/index.js.map +1 -0
  90. package/dist/rules-default/korean-comment-encoding.d.ts +3 -0
  91. package/dist/rules-default/korean-comment-encoding.d.ts.map +1 -0
  92. package/dist/rules-default/korean-comment-encoding.js +28 -0
  93. package/dist/rules-default/korean-comment-encoding.js.map +1 -0
  94. package/dist/rules-default/mask-card-number.d.ts +3 -0
  95. package/dist/rules-default/mask-card-number.d.ts.map +1 -0
  96. package/dist/rules-default/mask-card-number.js +45 -0
  97. package/dist/rules-default/mask-card-number.js.map +1 -0
  98. package/dist/rules-default/mask-pii-in-ai-prompt.d.ts +3 -0
  99. package/dist/rules-default/mask-pii-in-ai-prompt.d.ts.map +1 -0
  100. package/dist/rules-default/mask-pii-in-ai-prompt.js +41 -0
  101. package/dist/rules-default/mask-pii-in-ai-prompt.js.map +1 -0
  102. package/dist/rules-default/naver-kakao-oauth-webview.d.ts +3 -0
  103. package/dist/rules-default/naver-kakao-oauth-webview.d.ts.map +1 -0
  104. package/dist/rules-default/naver-kakao-oauth-webview.js +40 -0
  105. package/dist/rules-default/naver-kakao-oauth-webview.js.map +1 -0
  106. package/dist/rules-default/no-bare-except.d.ts +7 -0
  107. package/dist/rules-default/no-bare-except.d.ts.map +1 -0
  108. package/dist/rules-default/no-bare-except.js +23 -0
  109. package/dist/rules-default/no-bare-except.js.map +1 -0
  110. package/dist/rules-default/no-bare-throw.d.ts +7 -0
  111. package/dist/rules-default/no-bare-throw.d.ts.map +1 -0
  112. package/dist/rules-default/no-bare-throw.js +32 -0
  113. package/dist/rules-default/no-bare-throw.js.map +1 -0
  114. package/dist/rules-default/no-boolean-trap.d.ts +8 -0
  115. package/dist/rules-default/no-boolean-trap.d.ts.map +1 -0
  116. package/dist/rules-default/no-boolean-trap.js +33 -0
  117. package/dist/rules-default/no-boolean-trap.js.map +1 -0
  118. package/dist/rules-default/no-console-log.d.ts +3 -0
  119. package/dist/rules-default/no-console-log.d.ts.map +1 -0
  120. package/dist/rules-default/no-console-log.js +19 -0
  121. package/dist/rules-default/no-console-log.js.map +1 -0
  122. package/dist/rules-default/no-cvv-logging.d.ts +3 -0
  123. package/dist/rules-default/no-cvv-logging.d.ts.map +1 -0
  124. package/dist/rules-default/no-cvv-logging.js +36 -0
  125. package/dist/rules-default/no-cvv-logging.js.map +1 -0
  126. package/dist/rules-default/no-default-export-from-libs.d.ts +7 -0
  127. package/dist/rules-default/no-default-export-from-libs.d.ts.map +1 -0
  128. package/dist/rules-default/no-default-export-from-libs.js +24 -0
  129. package/dist/rules-default/no-default-export-from-libs.js.map +1 -0
  130. package/dist/rules-default/no-direct-anthropic.yaml +9 -0
  131. package/dist/rules-default/no-direct-openai.yaml +9 -0
  132. package/dist/rules-default/no-empty-catch.d.ts +7 -0
  133. package/dist/rules-default/no-empty-catch.d.ts.map +1 -0
  134. package/dist/rules-default/no-empty-catch.js +30 -0
  135. package/dist/rules-default/no-empty-catch.js.map +1 -0
  136. package/dist/rules-default/no-fstring-sql.d.ts +3 -0
  137. package/dist/rules-default/no-fstring-sql.d.ts.map +1 -0
  138. package/dist/rules-default/no-fstring-sql.js +24 -0
  139. package/dist/rules-default/no-fstring-sql.js.map +1 -0
  140. package/dist/rules-default/no-id-overwrite.d.ts +7 -0
  141. package/dist/rules-default/no-id-overwrite.d.ts.map +1 -0
  142. package/dist/rules-default/no-id-overwrite.js +26 -0
  143. package/dist/rules-default/no-id-overwrite.js.map +1 -0
  144. package/dist/rules-default/no-inline-date.yaml +9 -0
  145. package/dist/rules-default/no-inline-math-round.yaml +12 -0
  146. package/dist/rules-default/no-jsonb-circular.d.ts +3 -0
  147. package/dist/rules-default/no-jsonb-circular.d.ts.map +1 -0
  148. package/dist/rules-default/no-jsonb-circular.js +33 -0
  149. package/dist/rules-default/no-jsonb-circular.js.map +1 -0
  150. package/dist/rules-default/no-magic-number.d.ts +3 -0
  151. package/dist/rules-default/no-magic-number.d.ts.map +1 -0
  152. package/dist/rules-default/no-magic-number.js +42 -0
  153. package/dist/rules-default/no-magic-number.js.map +1 -0
  154. package/dist/rules-default/no-mutable-default-arg.d.ts +3 -0
  155. package/dist/rules-default/no-mutable-default-arg.d.ts.map +1 -0
  156. package/dist/rules-default/no-mutable-default-arg.js +30 -0
  157. package/dist/rules-default/no-mutable-default-arg.js.map +1 -0
  158. package/dist/rules-default/no-pickle.yaml +12 -0
  159. package/dist/rules-default/no-plain-card-number.d.ts +3 -0
  160. package/dist/rules-default/no-plain-card-number.d.ts.map +1 -0
  161. package/dist/rules-default/no-plain-card-number.js +51 -0
  162. package/dist/rules-default/no-plain-card-number.js.map +1 -0
  163. package/dist/rules-default/no-print-in-prod.yaml +9 -0
  164. package/dist/rules-default/no-process-env-leak.d.ts +7 -0
  165. package/dist/rules-default/no-process-env-leak.d.ts.map +1 -0
  166. package/dist/rules-default/no-process-env-leak.js +34 -0
  167. package/dist/rules-default/no-process-env-leak.js.map +1 -0
  168. package/dist/rules-default/no-shell-true.d.ts +3 -0
  169. package/dist/rules-default/no-shell-true.d.ts.map +1 -0
  170. package/dist/rules-default/no-shell-true.js +42 -0
  171. package/dist/rules-default/no-shell-true.js.map +1 -0
  172. package/dist/rules-default/prefer-const-array.d.ts +9 -0
  173. package/dist/rules-default/prefer-const-array.d.ts.map +1 -0
  174. package/dist/rules-default/prefer-const-array.js +34 -0
  175. package/dist/rules-default/prefer-const-array.js.map +1 -0
  176. package/dist/rules-default/prefer-named-imports.d.ts +8 -0
  177. package/dist/rules-default/prefer-named-imports.d.ts.map +1 -0
  178. package/dist/rules-default/prefer-named-imports.js +25 -0
  179. package/dist/rules-default/prefer-named-imports.js.map +1 -0
  180. package/dist/rules-default/preserve-transaction-log.d.ts +3 -0
  181. package/dist/rules-default/preserve-transaction-log.d.ts.map +1 -0
  182. package/dist/rules-default/preserve-transaction-log.js +33 -0
  183. package/dist/rules-default/preserve-transaction-log.js.map +1 -0
  184. package/dist/rules-default/pytest-fixture-naming.d.ts +3 -0
  185. package/dist/rules-default/pytest-fixture-naming.d.ts.map +1 -0
  186. package/dist/rules-default/pytest-fixture-naming.js +36 -0
  187. package/dist/rules-default/pytest-fixture-naming.js.map +1 -0
  188. package/dist/rules-default/requests-needs-timeout.d.ts +3 -0
  189. package/dist/rules-default/requests-needs-timeout.d.ts.map +1 -0
  190. package/dist/rules-default/requests-needs-timeout.js +43 -0
  191. package/dist/rules-default/requests-needs-timeout.js.map +1 -0
  192. package/dist/rules-default/require-idempotency-key.d.ts +3 -0
  193. package/dist/rules-default/require-idempotency-key.d.ts.map +1 -0
  194. package/dist/rules-default/require-idempotency-key.js +47 -0
  195. package/dist/rules-default/require-idempotency-key.js.map +1 -0
  196. package/dist/rules-default/require-tls-1-2-plus.d.ts +3 -0
  197. package/dist/rules-default/require-tls-1-2-plus.d.ts.map +1 -0
  198. package/dist/rules-default/require-tls-1-2-plus.js +30 -0
  199. package/dist/rules-default/require-tls-1-2-plus.js.map +1 -0
  200. package/dist/rules-default/rfc5987-korean-filename.d.ts +3 -0
  201. package/dist/rules-default/rfc5987-korean-filename.d.ts.map +1 -0
  202. package/dist/rules-default/rfc5987-korean-filename.js +32 -0
  203. package/dist/rules-default/rfc5987-korean-filename.js.map +1 -0
  204. package/dist/rules-default/route-needs-auth.d.ts +3 -0
  205. package/dist/rules-default/route-needs-auth.d.ts.map +1 -0
  206. package/dist/rules-default/route-needs-auth.js +48 -0
  207. package/dist/rules-default/route-needs-auth.js.map +1 -0
  208. package/dist/rules-default/route-needs-rate-limit.d.ts +3 -0
  209. package/dist/rules-default/route-needs-rate-limit.d.ts.map +1 -0
  210. package/dist/rules-default/route-needs-rate-limit.js +47 -0
  211. package/dist/rules-default/route-needs-rate-limit.js.map +1 -0
  212. package/dist/rules-default/separate-refund-permission.d.ts +3 -0
  213. package/dist/rules-default/separate-refund-permission.d.ts.map +1 -0
  214. package/dist/rules-default/separate-refund-permission.js +33 -0
  215. package/dist/rules-default/separate-refund-permission.js.map +1 -0
  216. package/dist/rules-default/track-ai-model-version.d.ts +3 -0
  217. package/dist/rules-default/track-ai-model-version.d.ts.map +1 -0
  218. package/dist/rules-default/track-ai-model-version.js +37 -0
  219. package/dist/rules-default/track-ai-model-version.js.map +1 -0
  220. package/dist/rules-default/type-hint-required-public.d.ts +10 -0
  221. package/dist/rules-default/type-hint-required-public.d.ts.map +1 -0
  222. package/dist/rules-default/type-hint-required-public.js +29 -0
  223. package/dist/rules-default/type-hint-required-public.js.map +1 -0
  224. package/dist/rules-default/verify-pg-response.d.ts +3 -0
  225. package/dist/rules-default/verify-pg-response.d.ts.map +1 -0
  226. package/dist/rules-default/verify-pg-response.js +37 -0
  227. package/dist/rules-default/verify-pg-response.js.map +1 -0
  228. package/dist/rules-default/won-format-thousands.d.ts +3 -0
  229. package/dist/rules-default/won-format-thousands.d.ts.map +1 -0
  230. package/dist/rules-default/won-format-thousands.js +24 -0
  231. package/dist/rules-default/won-format-thousands.js.map +1 -0
  232. package/dist/runner/context.d.ts +12 -0
  233. package/dist/runner/context.d.ts.map +1 -0
  234. package/dist/runner/context.js +34 -0
  235. package/dist/runner/context.js.map +1 -0
  236. package/dist/runner/index.d.ts +7 -0
  237. package/dist/runner/index.d.ts.map +1 -0
  238. package/dist/runner/index.js +5 -0
  239. package/dist/runner/index.js.map +1 -0
  240. package/dist/runner/ruleset-signature.d.ts +4 -0
  241. package/dist/runner/ruleset-signature.d.ts.map +1 -0
  242. package/dist/runner/ruleset-signature.js +11 -0
  243. package/dist/runner/ruleset-signature.js.map +1 -0
  244. package/dist/runner/run-file.d.ts +10 -0
  245. package/dist/runner/run-file.d.ts.map +1 -0
  246. package/dist/runner/run-file.js +20 -0
  247. package/dist/runner/run-file.js.map +1 -0
  248. package/dist/runner/run-project.d.ts +12 -0
  249. package/dist/runner/run-project.d.ts.map +1 -0
  250. package/dist/runner/run-project.js +55 -0
  251. package/dist/runner/run-project.js.map +1 -0
  252. package/dist/runner/run-rule.d.ts +5 -0
  253. package/dist/runner/run-rule.d.ts.map +1 -0
  254. package/dist/runner/run-rule.js +37 -0
  255. package/dist/runner/run-rule.js.map +1 -0
  256. package/dist/sync/index.d.ts +5 -0
  257. package/dist/sync/index.d.ts.map +1 -0
  258. package/dist/sync/index.js +3 -0
  259. package/dist/sync/index.js.map +1 -0
  260. package/dist/sync/render.d.ts +9 -0
  261. package/dist/sync/render.d.ts.map +1 -0
  262. package/dist/sync/render.js +70 -0
  263. package/dist/sync/render.js.map +1 -0
  264. package/dist/sync/sync-files.d.ts +12 -0
  265. package/dist/sync/sync-files.d.ts.map +1 -0
  266. package/dist/sync/sync-files.js +29 -0
  267. package/dist/sync/sync-files.js.map +1 -0
  268. package/package.json +62 -0
  269. package/scripts/copy-yaml-rules.mjs +19 -0
@@ -0,0 +1,25 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * `import * as X from 'module'` namespace imports prevent tree-shaking and
4
+ * obscure dependency analysis. Prefer named imports unless the module
5
+ * genuinely exports many disparate symbols (rare).
6
+ */
7
+ export default defineRule({
8
+ id: 'prefer-named-imports',
9
+ language: ['typescript', 'javascript', 'tsx'],
10
+ severity: 'info',
11
+ message: 'Avoid `import * as X` namespace imports; use named imports for tree-shaking.',
12
+ messageKo: '`import * as X` 네임스페이스 import 지양 — tree-shaking을 위해 named import 권장.',
13
+ visitors: {
14
+ import_statement(node, ctx) {
15
+ const text = ctx.textOf(node);
16
+ if (/import\s+\*\s+as\s+\w+/.test(text)) {
17
+ // Allow type-only namespace imports (less impact on bundle)
18
+ if (/import\s+type\s+\*/.test(text))
19
+ return;
20
+ ctx.report({ node });
21
+ }
22
+ },
23
+ },
24
+ });
25
+ //# sourceMappingURL=prefer-named-imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-named-imports.js","sourceRoot":"","sources":["../../src/rules-default/prefer-named-imports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;GAIG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,sBAAsB;IAC1B,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,8EAA8E;IACvF,SAAS,EAAE,sEAAsE;IACjF,QAAQ,EAAE;QACR,gBAAgB,CAAC,IAAI,EAAE,GAAG;YACxB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,4DAA4D;gBAC5D,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAC5C,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=preserve-transaction-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preserve-transaction-log.d.ts","sourceRoot":"","sources":["../../src/rules-default/preserve-transaction-log.ts"],"names":[],"mappings":";AAsBA,wBAWG"}
@@ -0,0 +1,33 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * PCI DSS § 10: financial transactions must produce an audit trail.
4
+ * Detect functions named pay/charge/payment/refund that lack any logging
5
+ * or transaction-table write call in their body.
6
+ */
7
+ const TX_NAME = /^(pay|charge|payment|refund|cancelRefund|issueRefund|pay\w*|charge\w*|payment\w*|refund\w*)$/;
8
+ const LOG_OR_AUDIT = /\b(logger|auditLog|audit|winston|pino)\.\w+|\bconsole\.(log|info|warn|error)|\b(transactions|payment_log|paymentLogs|auditLogs|tx_log)\b.*\.(insert|create|save|push)/;
9
+ function check(node, ctx) {
10
+ const name = node.childForFieldName('name');
11
+ if (!name)
12
+ return;
13
+ const fnName = ctx.textOf(name);
14
+ if (!TX_NAME.test(fnName))
15
+ return;
16
+ const text = ctx.textOf(node);
17
+ if (LOG_OR_AUDIT.test(text))
18
+ return;
19
+ ctx.report({ node });
20
+ }
21
+ export default defineRule({
22
+ id: 'preserve-transaction-log',
23
+ language: ['typescript', 'tsx'],
24
+ severity: 'error',
25
+ message: 'Payment/refund function does not produce an audit log entry (PCI DSS § 10.2 — implement audit logs for all access to cardholder data).',
26
+ messageKo: '결제/환불 함수에 감사 로그 기록이 없습니다 (PCI DSS § 10.2 — 카드 소지자 데이터 접근에 대한 감사 로그 필수).',
27
+ docs: 'https://github.com/aicqtools/aicqtools/blob/main/docs/rules/preserve-transaction-log.md',
28
+ visitors: {
29
+ function_declaration: check,
30
+ method_definition: check,
31
+ },
32
+ });
33
+ //# sourceMappingURL=preserve-transaction-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preserve-transaction-log.js","sourceRoot":"","sources":["../../src/rules-default/preserve-transaction-log.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,OAAO,GAAG,8FAA8F,CAAC;AAC/G,MAAM,YAAY,GAAG,uKAAuK,CAAC;AAE7L,SAAS,KAAK,CAAC,IAAuB,EAAE,GAAgB;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI;QAAE,OAAO;IAClB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO;IAClC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO;IACpC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACvB,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,0BAA0B;IAC9B,QAAQ,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC;IAC/B,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,wIAAwI;IACjJ,SAAS,EAAE,yEAAyE;IACpF,IAAI,EAAE,yFAAyF;IAC/F,QAAQ,EAAE;QACR,oBAAoB,EAAE,KAAK;QAC3B,iBAAiB,EAAE,KAAK;KACzB;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=pytest-fixture-naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pytest-fixture-naming.d.ts","sourceRoot":"","sources":["../../src/rules-default/pytest-fixture-naming.ts"],"names":[],"mappings":";AAgBA,wBAeG"}
@@ -0,0 +1,36 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ function hasPytestFixtureDecorator(node, textOf) {
3
+ // function_definition's parent is decorated_definition when decorated
4
+ const parent = node.parent;
5
+ if (!parent || parent.type !== 'decorated_definition')
6
+ return false;
7
+ for (let i = 0; i < parent.namedChildCount; i++) {
8
+ const child = parent.namedChild(i);
9
+ if (!child || child.type !== 'decorator')
10
+ continue;
11
+ const text = textOf(child);
12
+ if (/@pytest\.fixture\b/.test(text) || /^@fixture\b/.test(text))
13
+ return true;
14
+ }
15
+ return false;
16
+ }
17
+ export default defineRule({
18
+ id: 'pytest-fixture-naming',
19
+ language: 'python',
20
+ severity: 'warning',
21
+ message: 'pytest fixture should not start with `test_` (it would be collected as a test instead).',
22
+ messageKo: 'pytest fixture 함수는 `test_`로 시작하면 안 됩니다 (테스트로 인식되어 버립니다).',
23
+ visitors: {
24
+ function_definition(node, ctx) {
25
+ const name = node.childForFieldName('name');
26
+ if (!name)
27
+ return;
28
+ const nameText = ctx.textOf(name);
29
+ if (!nameText.startsWith('test_'))
30
+ return;
31
+ if (hasPytestFixtureDecorator(node, ctx.textOf))
32
+ ctx.report({ node: name });
33
+ },
34
+ },
35
+ });
36
+ //# sourceMappingURL=pytest-fixture-naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pytest-fixture-naming.js","sourceRoot":"","sources":["../../src/rules-default/pytest-fixture-naming.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,SAAS,yBAAyB,CAAC,IAAuB,EAAE,MAAwC;IAClG,sEAAsE;IACtE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,sBAAsB;QAAE,OAAO,KAAK,CAAC;IACpE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;YAAE,SAAS;QACnD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IAC/E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,uBAAuB;IAC3B,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,yFAAyF;IAClG,SAAS,EAAE,0DAA0D;IACrE,QAAQ,EAAE;QACR,mBAAmB,CAAC,IAAI,EAAE,GAAG;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,OAAO;YAC1C,IAAI,yBAAyB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9E,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=requests-needs-timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests-needs-timeout.d.ts","sourceRoot":"","sources":["../../src/rules-default/requests-needs-timeout.ts"],"names":[],"mappings":";AAiBA,wBAoBG"}
@@ -0,0 +1,43 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ const REQUESTS_METHODS = new Set(['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'request']);
3
+ function hasTimeoutKwarg(args, textOf) {
4
+ for (let i = 0; i < args.namedChildCount; i++) {
5
+ const arg = args.namedChild(i);
6
+ if (!arg)
7
+ continue;
8
+ if (arg.type === 'keyword_argument') {
9
+ const name = arg.childForFieldName('name');
10
+ if (name && textOf(name) === 'timeout')
11
+ return true;
12
+ }
13
+ }
14
+ return false;
15
+ }
16
+ export default defineRule({
17
+ id: 'requests-needs-timeout',
18
+ language: 'python',
19
+ severity: 'error',
20
+ message: 'requests call missing `timeout=...` — without it the call can hang indefinitely.',
21
+ messageKo: 'requests 호출에 `timeout=...` 누락 — 무한 대기 위험.',
22
+ visitors: {
23
+ call(node, ctx) {
24
+ const fn = node.childForFieldName('function');
25
+ if (!fn || fn.type !== 'attribute')
26
+ return;
27
+ const obj = fn.childForFieldName('object');
28
+ const attr = fn.childForFieldName('attribute');
29
+ if (!obj || !attr)
30
+ return;
31
+ if (ctx.textOf(obj) !== 'requests')
32
+ return;
33
+ if (!REQUESTS_METHODS.has(ctx.textOf(attr)))
34
+ return;
35
+ const args = node.childForFieldName('arguments');
36
+ if (!args)
37
+ return;
38
+ if (!hasTimeoutKwarg(args, ctx.textOf))
39
+ ctx.report({ node });
40
+ },
41
+ },
42
+ });
43
+ //# sourceMappingURL=requests-needs-timeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests-needs-timeout.js","sourceRoot":"","sources":["../../src/rules-default/requests-needs-timeout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAE1G,SAAS,eAAe,CAAC,IAAuB,EAAE,MAAwC;IACxF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAC;QACtD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,wBAAwB;IAC5B,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,kFAAkF;IAC3F,SAAS,EAAE,2CAA2C;IACtD,QAAQ,EAAE;QACR,IAAI,CAAC,IAAI,EAAE,GAAG;YACZ,MAAM,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,KAAK,WAAW;gBAAE,OAAO;YAC3C,MAAM,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAC/C,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;gBAAE,OAAO;YAC1B,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,UAAU;gBAAE,OAAO;YAC3C,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAAE,OAAO;YACpD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=require-idempotency-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-idempotency-key.d.ts","sourceRoot":"","sources":["../../src/rules-default/require-idempotency-key.ts"],"names":[],"mappings":";AAgBA,wBA2BG"}
@@ -0,0 +1,47 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * Payment best practice: charge/pay/refund operations must include an
4
+ * idempotency key to prevent double-spend on retry. Detect functions whose
5
+ * name contains `pay` / `charge` / `payment` and which lack an
6
+ * `idempotencyKey` / `Idempotency-Key` reference in the body.
7
+ *
8
+ * Limitation: name-based detection — functions named differently
9
+ * (`processOrder`, `bill`, etc.) are not flagged.
10
+ */
11
+ const PAYMENT_NAME = /^(pay|charge|payment|chargePayment|pay\w*|charge\w*|payment\w*|process(Pay|Payment|Charge))$/;
12
+ const IDEMPOTENCY = /\b(idempotency[_-]?key|idempotencyKey|Idempotency-Key)\b/i;
13
+ export default defineRule({
14
+ id: 'require-idempotency-key',
15
+ language: ['typescript', 'tsx'],
16
+ severity: 'error',
17
+ message: 'Payment function missing an idempotency key — required to prevent double-charge on retry (payment-domain best practice; aligns with PCI DSS § 10.2 audit trail integrity).',
18
+ messageKo: '결제 함수에 idempotency key 누락 — 재시도 시 중복 청구 방지 필수 (결제 도메인 권장 사항; PCI DSS § 10.2 감사 추적 무결성 정렬).',
19
+ docs: 'https://github.com/aicqtools/aicqtools/blob/main/docs/rules/require-idempotency-key.md',
20
+ visitors: {
21
+ function_declaration(node, ctx) {
22
+ const name = node.childForFieldName('name');
23
+ if (!name)
24
+ return;
25
+ const fnName = ctx.textOf(name);
26
+ if (!PAYMENT_NAME.test(fnName))
27
+ return;
28
+ const text = ctx.textOf(node);
29
+ if (IDEMPOTENCY.test(text))
30
+ return;
31
+ ctx.report({ node });
32
+ },
33
+ method_definition(node, ctx) {
34
+ const name = node.childForFieldName('name');
35
+ if (!name)
36
+ return;
37
+ const fnName = ctx.textOf(name);
38
+ if (!PAYMENT_NAME.test(fnName))
39
+ return;
40
+ const text = ctx.textOf(node);
41
+ if (IDEMPOTENCY.test(text))
42
+ return;
43
+ ctx.report({ node });
44
+ },
45
+ },
46
+ });
47
+ //# sourceMappingURL=require-idempotency-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-idempotency-key.js","sourceRoot":"","sources":["../../src/rules-default/require-idempotency-key.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;;;;;GAQG;AACH,MAAM,YAAY,GAAG,8FAA8F,CAAC;AACpH,MAAM,WAAW,GAAG,2DAA2D,CAAC;AAEhF,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,yBAAyB;IAC7B,QAAQ,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC;IAC/B,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,4KAA4K;IACrL,SAAS,EAAE,4FAA4F;IACvG,IAAI,EAAE,wFAAwF;IAC9F,QAAQ,EAAE;QACR,oBAAoB,CAAC,IAAuB,EAAE,GAAgB;YAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAE,OAAO;YACvC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACnC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvB,CAAC;QACD,iBAAiB,CAAC,IAAuB,EAAE,GAAgB;YACzD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAE,OAAO;YACvC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACnC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvB,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=require-tls-1-2-plus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-tls-1-2-plus.d.ts","sourceRoot":"","sources":["../../src/rules-default/require-tls-1-2-plus.ts"],"names":[],"mappings":";AAWA,wBAkBG"}
@@ -0,0 +1,30 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * PCI DSS § 4.1: cardholder data in transit must use strong cryptography.
4
+ * Detect TLS configuration that explicitly allows TLSv1 / TLSv1.1 via
5
+ * `secureProtocol` or `minVersion` options.
6
+ */
7
+ const FORBIDDEN_PROTO = /['"`](TLSv1(_method)?|TLSv1\.1|TLSv1_1(_method)?|SSLv\d|SSLv\d_method)['"`]/;
8
+ export default defineRule({
9
+ id: 'require-tls-1-2-plus',
10
+ language: ['typescript', 'tsx'],
11
+ severity: 'error',
12
+ message: 'TLS configuration allows TLS < 1.2 (PCI DSS § 4.2.1 — strong cryptography for cardholder data in transit).',
13
+ messageKo: 'TLS 1.2 미만 프로토콜을 허용하는 설정 (PCI DSS § 4.2.1 — 카드 소지자 데이터 전송 시 강한 암호화 필수).',
14
+ docs: 'https://github.com/aicqtools/aicqtools/blob/main/docs/rules/require-tls-1-2-plus.md',
15
+ visitors: {
16
+ pair(node, ctx) {
17
+ const key = node.childForFieldName('key');
18
+ const value = node.childForFieldName('value');
19
+ if (!key || !value)
20
+ return;
21
+ const keyText = ctx.textOf(key).replace(/^['"`]|['"`]$/g, '');
22
+ if (keyText !== 'secureProtocol' && keyText !== 'minVersion')
23
+ return;
24
+ const valueText = ctx.textOf(value);
25
+ if (FORBIDDEN_PROTO.test(valueText))
26
+ ctx.report({ node });
27
+ },
28
+ },
29
+ });
30
+ //# sourceMappingURL=require-tls-1-2-plus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-tls-1-2-plus.js","sourceRoot":"","sources":["../../src/rules-default/require-tls-1-2-plus.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,eAAe,GAAG,6EAA6E,CAAC;AAEtG,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,sBAAsB;IAC1B,QAAQ,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC;IAC/B,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,4GAA4G;IACrH,SAAS,EAAE,yEAAyE;IACpF,IAAI,EAAE,qFAAqF;IAC3F,QAAQ,EAAE;QACR,IAAI,CAAC,IAAuB,EAAE,GAAgB;YAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC9C,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK;gBAAE,OAAO;YAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;YAC9D,IAAI,OAAO,KAAK,gBAAgB,IAAI,OAAO,KAAK,YAAY;gBAAE,OAAO;YACrE,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=rfc5987-korean-filename.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rfc5987-korean-filename.d.ts","sourceRoot":"","sources":["../../src/rules-default/rfc5987-korean-filename.ts"],"names":[],"mappings":";AAcA,wBAeG"}
@@ -0,0 +1,32 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * `Content-Disposition: attachment; filename="<korean>.csv"` without RFC 5987 encoding
4
+ * breaks Korean filenames in older browsers (esp. IE11/old Safari). Use
5
+ * `filename*=UTF-8''<encoded>` form.
6
+ *
7
+ * Heuristic: inspect whole call expressions (e.g. `setHeader("Content-Disposition", "...")`)
8
+ * so multi-arg patterns where the header name and value live in separate strings are caught.
9
+ */
10
+ const HAS_KOREAN = /[ㄱ-힝]/;
11
+ const HAS_RFC5987 = /filename\*\s*=\s*UTF-8''/i;
12
+ const HAS_CONTENT_DISPOSITION = /Content-Disposition/i;
13
+ export default defineRule({
14
+ id: 'rfc5987-korean-filename',
15
+ language: ['typescript', 'javascript', 'tsx'],
16
+ severity: 'warning',
17
+ message: 'Content-Disposition with Korean filename should use RFC 5987 (`filename*=UTF-8\'\'...`).',
18
+ messageKo: '한글 파일명 Content-Disposition은 RFC 5987 인코딩 필요 (`filename*=UTF-8\'\'...`).',
19
+ visitors: {
20
+ call_expression(node, ctx) {
21
+ const text = ctx.textOf(node);
22
+ if (!HAS_CONTENT_DISPOSITION.test(text))
23
+ return;
24
+ if (!HAS_KOREAN.test(text))
25
+ return;
26
+ if (HAS_RFC5987.test(text))
27
+ return;
28
+ ctx.report({ node });
29
+ },
30
+ },
31
+ });
32
+ //# sourceMappingURL=rfc5987-korean-filename.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rfc5987-korean-filename.js","sourceRoot":"","sources":["../../src/rules-default/rfc5987-korean-filename.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,OAAO,CAAC;AAC3B,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAChD,MAAM,uBAAuB,GAAG,sBAAsB,CAAC;AAEvD,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,yBAAyB;IAC7B,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,0FAA0F;IACnG,SAAS,EAAE,yEAAyE;IACpF,QAAQ,EAAE;QACR,eAAe,CAAC,IAAI,EAAE,GAAG;YACvB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACnC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACnC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvB,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=route-needs-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-needs-auth.d.ts","sourceRoot":"","sources":["../../src/rules-default/route-needs-auth.ts"],"names":[],"mappings":";AAkBA,wBA2BG"}
@@ -0,0 +1,48 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ const ROUTER_METHODS = new Set(['get', 'post', 'put', 'patch', 'delete']);
3
+ const AUTH_PATTERN = /auth(enticate)?|requireUser|requireAuth|isAuthenticated/i;
4
+ // Public path patterns that don't require auth
5
+ const PUBLIC_PATH_PATTERN = /^["'`](\/health|\/ping|\/login|\/signup|\/auth\/|\/public\/)/;
6
+ function isRouterCall(callee, textOf) {
7
+ if (callee.type !== 'member_expression')
8
+ return false;
9
+ const obj = callee.childForFieldName('object');
10
+ const prop = callee.childForFieldName('property');
11
+ if (!obj || !prop)
12
+ return false;
13
+ const objText = textOf(obj);
14
+ if (objText !== 'router' && objText !== 'app')
15
+ return false;
16
+ return ROUTER_METHODS.has(textOf(prop));
17
+ }
18
+ export default defineRule({
19
+ id: 'route-needs-auth',
20
+ language: ['typescript', 'javascript', 'tsx'],
21
+ severity: 'error',
22
+ message: 'Route is missing an authentication middleware (e.g. `authenticate`, `requireAuth`).',
23
+ messageKo: '라우트에 인증 미들웨어가 빠졌습니다 (`authenticate` / `requireAuth` 등).',
24
+ visitors: {
25
+ call_expression(node, ctx) {
26
+ const callee = node.childForFieldName('function');
27
+ if (!callee || !isRouterCall(callee, ctx.textOf))
28
+ return;
29
+ const args = node.childForFieldName('arguments');
30
+ if (!args || args.namedChildCount < 2)
31
+ return;
32
+ const pathArg = args.namedChild(0);
33
+ if (pathArg && PUBLIC_PATH_PATTERN.test(ctx.textOf(pathArg)))
34
+ return;
35
+ let hasAuth = false;
36
+ for (let i = 1; i < args.namedChildCount; i++) {
37
+ const arg = args.namedChild(i);
38
+ if (arg && AUTH_PATTERN.test(ctx.textOf(arg))) {
39
+ hasAuth = true;
40
+ break;
41
+ }
42
+ }
43
+ if (!hasAuth)
44
+ ctx.report({ node });
45
+ },
46
+ },
47
+ });
48
+ //# sourceMappingURL=route-needs-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-needs-auth.js","sourceRoot":"","sources":["../../src/rules-default/route-needs-auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC1E,MAAM,YAAY,GAAG,0DAA0D,CAAC;AAChF,+CAA+C;AAC/C,MAAM,mBAAmB,GAAG,8DAA8D,CAAC;AAE3F,SAAS,YAAY,CAAC,MAAyB,EAAE,MAAwC;IACvF,IAAI,MAAM,CAAC,IAAI,KAAK,mBAAmB;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC5D,OAAO,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,kBAAkB;IACtB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,qFAAqF;IAC9F,SAAS,EAAE,yDAAyD;IACpE,QAAQ,EAAE;QACR,eAAe,CAAC,IAAI,EAAE,GAAG;YACvB,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;gBAAE,OAAO;YACzD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,GAAG,CAAC;gBAAE,OAAO;YAE9C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACnC,IAAI,OAAO,IAAI,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAAE,OAAO;YAErE,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC/B,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBAC9C,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,OAAO;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=route-needs-rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-needs-rate-limit.d.ts","sourceRoot":"","sources":["../../src/rules-default/route-needs-rate-limit.ts"],"names":[],"mappings":";AAqBA,wBAuBG"}
@@ -0,0 +1,47 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ const ROUTER_METHODS = new Set(['get', 'post', 'put', 'patch', 'delete']);
3
+ const RATE_LIMIT_PATTERN = /rate.?limit/i;
4
+ function isRouterCall(callee, textOf) {
5
+ if (callee.type !== 'member_expression')
6
+ return false;
7
+ const obj = callee.childForFieldName('object');
8
+ const prop = callee.childForFieldName('property');
9
+ if (!obj || !prop)
10
+ return false;
11
+ const objText = textOf(obj);
12
+ if (objText !== 'router' && objText !== 'app')
13
+ return false;
14
+ return ROUTER_METHODS.has(textOf(prop));
15
+ }
16
+ function argHasRateLimit(arg, textOf) {
17
+ const text = textOf(arg);
18
+ return RATE_LIMIT_PATTERN.test(text);
19
+ }
20
+ export default defineRule({
21
+ id: 'route-needs-rate-limit',
22
+ language: ['typescript', 'javascript', 'tsx'],
23
+ severity: 'error',
24
+ message: 'New route is missing a rate-limit middleware.',
25
+ messageKo: '새 라우트에 rate-limit 미들웨어가 빠졌습니다.',
26
+ visitors: {
27
+ call_expression(node, ctx) {
28
+ const callee = node.childForFieldName('function');
29
+ if (!callee || !isRouterCall(callee, ctx.textOf))
30
+ return;
31
+ const args = node.childForFieldName('arguments');
32
+ if (!args)
33
+ return;
34
+ let hasRateLimit = false;
35
+ for (let i = 0; i < args.namedChildCount; i++) {
36
+ const arg = args.namedChild(i);
37
+ if (arg && argHasRateLimit(arg, ctx.textOf)) {
38
+ hasRateLimit = true;
39
+ break;
40
+ }
41
+ }
42
+ if (!hasRateLimit)
43
+ ctx.report({ node });
44
+ },
45
+ },
46
+ });
47
+ //# sourceMappingURL=route-needs-rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-needs-rate-limit.js","sourceRoot":"","sources":["../../src/rules-default/route-needs-rate-limit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC1E,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAE1C,SAAS,YAAY,CAAC,MAAyB,EAAE,MAAwC;IACvF,IAAI,MAAM,CAAC,IAAI,KAAK,mBAAmB;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC5D,OAAO,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,eAAe,CAAC,GAAsB,EAAE,MAAwC;IACvF,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,wBAAwB;IAC5B,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,+CAA+C;IACxD,SAAS,EAAE,gCAAgC;IAC3C,QAAQ,EAAE;QACR,eAAe,CAAC,IAAI,EAAE,GAAG;YACvB,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;gBAAE,OAAO;YACzD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,IAAI,YAAY,GAAG,KAAK,CAAC;YACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC/B,IAAI,GAAG,IAAI,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5C,YAAY,GAAG,IAAI,CAAC;oBACpB,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,YAAY;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=separate-refund-permission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separate-refund-permission.d.ts","sourceRoot":"","sources":["../../src/rules-default/separate-refund-permission.ts"],"names":[],"mappings":";AAsBA,wBAWG"}
@@ -0,0 +1,33 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * Refund operations are highly privileged — separation of duties requires
4
+ * a permission check before invoking any refund logic. Detect functions
5
+ * named `refund*` whose body lacks a permission/role check.
6
+ */
7
+ const REFUND_NAME = /^(refund|cancelRefund|issueRefund|refund\w*)$/;
8
+ const PERMISSION_CHECK = /\b(req\.user\.role|hasPermission|checkPermission|isAdmin|requireRole|allowedRoles|authGuard|RBAC|canRefund|verifyPermission)\b/i;
9
+ function check(node, ctx) {
10
+ const name = node.childForFieldName('name');
11
+ if (!name)
12
+ return;
13
+ const fnName = ctx.textOf(name);
14
+ if (!REFUND_NAME.test(fnName))
15
+ return;
16
+ const text = ctx.textOf(node);
17
+ if (PERMISSION_CHECK.test(text))
18
+ return;
19
+ ctx.report({ node });
20
+ }
21
+ export default defineRule({
22
+ id: 'separate-refund-permission',
23
+ language: ['typescript', 'tsx'],
24
+ severity: 'error',
25
+ message: 'Refund function lacks a permission/role check (PCI DSS § 7.2 — restrict access by business need-to-know; separation of duties).',
26
+ messageKo: '환불 함수에 권한 체크가 없습니다 (PCI DSS § 7.2 — 업무 필요에 따른 접근 제한; 직무 분리 원칙).',
27
+ docs: 'https://github.com/aicqtools/aicqtools/blob/main/docs/rules/separate-refund-permission.md',
28
+ visitors: {
29
+ function_declaration: check,
30
+ method_definition: check,
31
+ },
32
+ });
33
+ //# sourceMappingURL=separate-refund-permission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separate-refund-permission.js","sourceRoot":"","sources":["../../src/rules-default/separate-refund-permission.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,WAAW,GAAG,+CAA+C,CAAC;AACpE,MAAM,gBAAgB,GAAG,iIAAiI,CAAC;AAE3J,SAAS,KAAK,CAAC,IAAuB,EAAE,GAAgB;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI;QAAE,OAAO;IAClB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO;IACtC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO;IACxC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACvB,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,4BAA4B;IAChC,QAAQ,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC;IAC/B,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,iIAAiI;IAC1I,SAAS,EAAE,iEAAiE;IAC5E,IAAI,EAAE,2FAA2F;IACjG,QAAQ,EAAE;QACR,oBAAoB,EAAE,KAAK;QAC3B,iBAAiB,EAAE,KAAK;KACzB;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=track-ai-model-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track-ai-model-version.d.ts","sourceRoot":"","sources":["../../src/rules-default/track-ai-model-version.ts"],"names":[],"mappings":";AAeA,wBAoBG"}
@@ -0,0 +1,37 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * FSC AI guideline: AI inference calls must specify the model name explicitly
4
+ * so audits can trace which model produced a given decision. Detect calls to
5
+ * `openai.chat.completions.create()` / `anthropic.messages.create()` whose
6
+ * argument object lacks a `model:` property.
7
+ *
8
+ * Limitation: false negatives when the options object is built elsewhere and
9
+ * passed in as a variable.
10
+ */
11
+ const TARGET_FN = /\b(openai\.chat\.completions\.create|anthropic\.messages\.create|openai\.completions\.create)$/;
12
+ export default defineRule({
13
+ id: 'track-ai-model-version',
14
+ language: ['typescript', 'tsx'],
15
+ severity: 'warning',
16
+ message: 'AI inference call missing explicit `model:` parameter (FSC AI guideline — model governance).',
17
+ messageKo: 'AI 추론 호출에 `model:` 파라미터가 명시되지 않았습니다 (금감원 AI 가이드라인 — 모델 거버넌스).',
18
+ docs: 'https://github.com/aicqtools/aicqtools/blob/main/docs/rules/track-ai-model-version.md',
19
+ visitors: {
20
+ call_expression(node, ctx) {
21
+ const fnNode = node.childForFieldName('function');
22
+ if (!fnNode)
23
+ return;
24
+ const fnText = ctx.textOf(fnNode);
25
+ if (!TARGET_FN.test(fnText))
26
+ return;
27
+ const args = node.childForFieldName('arguments');
28
+ if (!args)
29
+ return;
30
+ const argsText = ctx.textOf(args);
31
+ if (/\bmodel\s*:/.test(argsText))
32
+ return;
33
+ ctx.report({ node });
34
+ },
35
+ },
36
+ });
37
+ //# sourceMappingURL=track-ai-model-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track-ai-model-version.js","sourceRoot":"","sources":["../../src/rules-default/track-ai-model-version.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;;;;;GAQG;AACH,MAAM,SAAS,GAAG,gGAAgG,CAAC;AAEnH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,wBAAwB;IAC5B,QAAQ,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC;IAC/B,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,8FAA8F;IACvG,SAAS,EAAE,+DAA+D;IAC1E,IAAI,EAAE,uFAAuF;IAC7F,QAAQ,EAAE;QACR,eAAe,CAAC,IAAuB,EAAE,GAAgB;YACvD,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;gBAAE,OAAO;YACpC,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAAE,OAAO;YACzC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvB,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Public functions (not starting with `_`) should have a return type annotation.
3
+ * Helps catch type errors and serves as inline documentation.
4
+ *
5
+ * Heuristic: looks for `-> Type:` after parameter list. False positives possible
6
+ * for functions that genuinely have no useful return type, but that's rare.
7
+ */
8
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
9
+ export default _default;
10
+ //# sourceMappingURL=type-hint-required-public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-hint-required-public.d.ts","sourceRoot":"","sources":["../../src/rules-default/type-hint-required-public.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;;AACH,wBAgBG"}
@@ -0,0 +1,29 @@
1
+ import { defineRule } from '@aicqtools/rule-sdk';
2
+ /**
3
+ * Public functions (not starting with `_`) should have a return type annotation.
4
+ * Helps catch type errors and serves as inline documentation.
5
+ *
6
+ * Heuristic: looks for `-> Type:` after parameter list. False positives possible
7
+ * for functions that genuinely have no useful return type, but that's rare.
8
+ */
9
+ export default defineRule({
10
+ id: 'type-hint-required-public',
11
+ language: 'python',
12
+ severity: 'info',
13
+ message: 'Public function is missing a return type annotation (`-> Type:`).',
14
+ messageKo: 'public 함수에 반환 타입 어노테이션 누락 (`-> Type:`).',
15
+ visitors: {
16
+ function_definition(node, ctx) {
17
+ const name = node.childForFieldName('name');
18
+ if (!name)
19
+ return;
20
+ const nameText = ctx.textOf(name);
21
+ if (nameText.startsWith('_'))
22
+ return;
23
+ const returnType = node.childForFieldName('return_type');
24
+ if (!returnType)
25
+ ctx.report({ node: name });
26
+ },
27
+ },
28
+ });
29
+ //# sourceMappingURL=type-hint-required-public.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-hint-required-public.js","sourceRoot":"","sources":["../../src/rules-default/type-hint-required-public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;;;GAMG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,2BAA2B;IAC/B,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,mEAAmE;IAC5E,SAAS,EAAE,yCAAyC;IACpD,QAAQ,EAAE;QACR,mBAAmB,CAAC,IAAI,EAAE,GAAG;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,OAAO;YACrC,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;YACzD,IAAI,CAAC,UAAU;gBAAE,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
+ export default _default;
3
+ //# sourceMappingURL=verify-pg-response.d.ts.map