@aicqtools/guardrail 1.0.0-alpha.9 → 1.0.0-beta.1

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 (75) hide show
  1. package/dist/docs/render-rule-md.d.ts.map +1 -1
  2. package/dist/docs/render-rule-md.js +80 -0
  3. package/dist/docs/render-rule-md.js.map +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/matcher/yaml-rule.d.ts +13 -0
  9. package/dist/matcher/yaml-rule.d.ts.map +1 -1
  10. package/dist/matcher/yaml-rule.js +32 -0
  11. package/dist/matcher/yaml-rule.js.map +1 -1
  12. package/dist/rules-default/camelcase-migration-column.d.ts.map +1 -1
  13. package/dist/rules-default/camelcase-migration-column.js +26 -2
  14. package/dist/rules-default/camelcase-migration-column.js.map +1 -1
  15. package/dist/rules-default/index.js +1 -1
  16. package/dist/rules-default/index.js.map +1 -1
  17. package/dist/rules-default/mask-pii-in-ai-prompt.d.ts.map +1 -1
  18. package/dist/rules-default/mask-pii-in-ai-prompt.js +44 -7
  19. package/dist/rules-default/mask-pii-in-ai-prompt.js.map +1 -1
  20. package/dist/rules-default/no-console-log.d.ts +6 -0
  21. package/dist/rules-default/no-console-log.d.ts.map +1 -1
  22. package/dist/rules-default/no-console-log.js +30 -1
  23. package/dist/rules-default/no-console-log.js.map +1 -1
  24. package/dist/rules-default/no-empty-catch.d.ts +11 -0
  25. package/dist/rules-default/no-empty-catch.d.ts.map +1 -1
  26. package/dist/rules-default/no-empty-catch.js +48 -0
  27. package/dist/rules-default/no-empty-catch.js.map +1 -1
  28. package/dist/rules-default/no-fstring-sql.d.ts.map +1 -1
  29. package/dist/rules-default/no-fstring-sql.js +51 -2
  30. package/dist/rules-default/no-fstring-sql.js.map +1 -1
  31. package/dist/rules-default/no-id-overwrite.d.ts +2 -1
  32. package/dist/rules-default/no-id-overwrite.d.ts.map +1 -1
  33. package/dist/rules-default/no-id-overwrite.js +2 -1
  34. package/dist/rules-default/no-id-overwrite.js.map +1 -1
  35. package/dist/rules-default/no-magic-number.d.ts +1 -0
  36. package/dist/rules-default/no-magic-number.d.ts.map +1 -1
  37. package/dist/rules-default/no-magic-number.js +35 -5
  38. package/dist/rules-default/no-magic-number.js.map +1 -1
  39. package/dist/rules-default/no-print-in-prod.yaml +8 -0
  40. package/dist/runner/apply-rule-config.d.ts +79 -13
  41. package/dist/runner/apply-rule-config.d.ts.map +1 -1
  42. package/dist/runner/apply-rule-config.js +175 -44
  43. package/dist/runner/apply-rule-config.js.map +1 -1
  44. package/dist/runner/context.d.ts +7 -0
  45. package/dist/runner/context.d.ts.map +1 -1
  46. package/dist/runner/context.js +2 -0
  47. package/dist/runner/context.js.map +1 -1
  48. package/dist/runner/index.d.ts +4 -2
  49. package/dist/runner/index.d.ts.map +1 -1
  50. package/dist/runner/index.js +2 -1
  51. package/dist/runner/index.js.map +1 -1
  52. package/dist/runner/resolve-rule-options.d.ts +28 -0
  53. package/dist/runner/resolve-rule-options.d.ts.map +1 -0
  54. package/dist/runner/resolve-rule-options.js +27 -0
  55. package/dist/runner/resolve-rule-options.js.map +1 -0
  56. package/dist/runner/run-file.d.ts +16 -2
  57. package/dist/runner/run-file.d.ts.map +1 -1
  58. package/dist/runner/run-file.js +49 -7
  59. package/dist/runner/run-file.js.map +1 -1
  60. package/dist/runner/run-project.d.ts +20 -0
  61. package/dist/runner/run-project.d.ts.map +1 -1
  62. package/dist/runner/run-project.js +33 -5
  63. package/dist/runner/run-project.js.map +1 -1
  64. package/dist/runner/suppressions.d.ts +46 -1
  65. package/dist/runner/suppressions.d.ts.map +1 -1
  66. package/dist/runner/suppressions.js +101 -15
  67. package/dist/runner/suppressions.js.map +1 -1
  68. package/dist/suggest/analyze.js +3 -0
  69. package/dist/suggest/analyze.js.map +1 -1
  70. package/dist/suggest/format.d.ts.map +1 -1
  71. package/dist/suggest/format.js +9 -0
  72. package/dist/suggest/format.js.map +1 -1
  73. package/dist/suggest/types.d.ts +7 -0
  74. package/dist/suggest/types.d.ts.map +1 -1
  75. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"no-empty-catch.js","sourceRoot":"","sources":["../../src/rules-default/no-empty-catch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;GAGG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,gBAAgB;IACpB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,iDAAiD;IAC1D,SAAS,EAAE,6CAA6C;IACxD,QAAQ,EAAE;QACR,YAAY,CAAC,IAAI,EAAE,GAAG;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBACjC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBACtC,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"}
1
+ {"version":3,"file":"no-empty-catch.js","sourceRoot":"","sources":["../../src/rules-default/no-empty-catch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,+CAA+C,CAAC;AAE5E,MAAM,qBAAqB,GAAsB;IAC/C,kDAAkD;CAC1C,CAAC;AAEX,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC;CAC1E,CAAC;KACD,MAAM,EAAE,CAAC;AAMZ,2FAA2F;AAC3F,gGAAgG;AAChG,+FAA+F;AAC/F,IAAI,YAAY,GAA6B,IAAI,CAAC;AAClD,IAAI,cAAc,GAA6B,IAAI,CAAC;AAEpD,SAAS,mBAAmB,CAAC,MAAyB;IACpD,IAAI,YAAY,KAAK,MAAM,IAAI,cAAc,KAAK,IAAI;QAAE,OAAO,cAAc,CAAC;IAC9E,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,YAAY,GAAG,MAAM,CAAC;IACtB,cAAc,GAAG,QAAQ,CAAC;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,gBAAgB;IACpB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,iDAAiD;IAC1D,SAAS,EAAE,6CAA6C;IACxD,YAAY,EAAE,CAAC,YAAY,CAAC;IAC5B,OAAO,EAAE;QACP,MAAM,EAAE,aAAa;QACrB,QAAQ,EAAE,EAAE,gBAAgB,EAAE,CAAC,GAAG,qBAAqB,CAAC,EAAE;KAC3D;IACD,QAAQ,EAAE;QACR,YAAY,CAAC,IAAI,EAAE,GAAG;YACpB,yFAAyF;YACzF,6EAA6E;YAC7E,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;gBAC1B,MAAM,IAAI,GAAI,GAAG,CAAC,OAA2C,IAAI;oBAC/D,gBAAgB,EAAE,qBAAqB;iBACxC,CAAC;gBACF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAC5D,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBAAE,OAAO;YAC3D,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAClB,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBACjC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBACtC,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"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-fstring-sql.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-fstring-sql.ts"],"names":[],"mappings":";AAIA,wBAiBG"}
1
+ {"version":3,"file":"no-fstring-sql.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-fstring-sql.ts"],"names":[],"mappings":";AAkDA,wBA0BG"}
@@ -1,18 +1,67 @@
1
+ import { z } from 'zod';
1
2
  import { defineRule } from '@aicqtools/rule-sdk';
2
- const SQL_KEYWORD_PATTERN = /\b(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|VALUES)\b/i;
3
+ /**
4
+ * Default SQL keywords flagged inside Python f-strings. Alpha.16 exposes this list as
5
+ * `options.sqlKeywords` so projects can shrink it (e.g. `['SELECT']` only) or extend it
6
+ * (e.g. add `'CREATE TABLE'`). Default keeps alpha.15 behavior bit-for-bit identical.
7
+ *
8
+ * Multi-token keywords like `'CREATE TABLE'` work via `\b(...)\b` with the literal space
9
+ * preserved — note that double spaces or newlines between tokens won't match, and meta
10
+ * characters are escaped via `escapeRegex` to keep user-supplied keywords safe.
11
+ */
12
+ const DEFAULT_SQL_KEYWORDS = [
13
+ 'SELECT',
14
+ 'INSERT',
15
+ 'UPDATE',
16
+ 'DELETE',
17
+ 'FROM',
18
+ 'WHERE',
19
+ 'JOIN',
20
+ 'VALUES',
21
+ ];
22
+ const optionsSchema = z
23
+ .object({
24
+ sqlKeywords: z.array(z.string()).default([...DEFAULT_SQL_KEYWORDS]),
25
+ })
26
+ .strict();
27
+ function escapeRegex(s) {
28
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
29
+ }
30
+ // Module-scope compile cache — keyed by source array reference equality (same trade-off as
31
+ // alpha.15 `no-empty-catch.compileSkipPatterns`).
32
+ let cachedSource = null;
33
+ let cachedPattern = null;
34
+ function compileSqlKeywordPattern(source) {
35
+ if (cachedSource === source && cachedPattern !== null)
36
+ return cachedPattern;
37
+ const pattern = new RegExp('\\b(' + source.map(escapeRegex).join('|') + ')\\b', 'i');
38
+ cachedSource = source;
39
+ cachedPattern = pattern;
40
+ return pattern;
41
+ }
3
42
  export default defineRule({
4
43
  id: 'no-fstring-sql',
5
44
  language: 'python',
6
45
  severity: 'error',
7
46
  message: 'SQL inside f-string is a SQL injection vector — use parameterized queries.',
8
47
  messageKo: 'f-string으로 SQL 조합은 SQL 주입 위험 — 파라미터 바인딩을 사용하세요.',
48
+ options: {
49
+ schema: optionsSchema,
50
+ defaults: { sqlKeywords: [...DEFAULT_SQL_KEYWORDS] },
51
+ },
9
52
  visitors: {
10
53
  string(node, ctx) {
11
54
  const text = ctx.textOf(node);
12
55
  // Python f-string starts with f" or f' (or rf", fr", etc.)
13
56
  if (!/^[a-zA-Z]*[fF][a-zA-Z]*['"]/.test(text))
14
57
  return;
15
- if (!SQL_KEYWORD_PATTERN.test(text))
58
+ const opts = ctx.options ?? {
59
+ sqlKeywords: DEFAULT_SQL_KEYWORDS,
60
+ };
61
+ if (opts.sqlKeywords.length === 0)
62
+ return;
63
+ const pattern = compileSqlKeywordPattern(opts.sqlKeywords);
64
+ if (!pattern.test(text))
16
65
  return;
17
66
  // Has interpolation `{...}`?
18
67
  if (!/\{[^{}]+\}/.test(text))
@@ -1 +1 @@
1
- {"version":3,"file":"no-fstring-sql.js","sourceRoot":"","sources":["../../src/rules-default/no-fstring-sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,mBAAmB,GAAG,2DAA2D,CAAC;AAExF,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,gBAAgB;IACpB,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,4EAA4E;IACrF,SAAS,EAAE,iDAAiD;IAC5D,QAAQ,EAAE;QACR,MAAM,CAAC,IAAI,EAAE,GAAG;YACd,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,2DAA2D;YAC3D,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACtD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YAC5C,6BAA6B;YAC7B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACrC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvB,CAAC;KACF;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"no-fstring-sql.js","sourceRoot":"","sources":["../../src/rules-default/no-fstring-sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,oBAAoB,GAAsB;IAC9C,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,QAAQ;CACA,CAAC;AAEX,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC;CACpE,CAAC;KACD,MAAM,EAAE,CAAC;AAMZ,SAAS,WAAW,CAAC,CAAS;IAC5B,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,2FAA2F;AAC3F,kDAAkD;AAClD,IAAI,YAAY,GAA6B,IAAI,CAAC;AAClD,IAAI,aAAa,GAAkB,IAAI,CAAC;AAExC,SAAS,wBAAwB,CAAC,MAAyB;IACzD,IAAI,YAAY,KAAK,MAAM,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,aAAa,CAAC;IAC5E,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;IACrF,YAAY,GAAG,MAAM,CAAC;IACtB,aAAa,GAAG,OAAO,CAAC;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,gBAAgB;IACpB,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,4EAA4E;IACrF,SAAS,EAAE,iDAAiD;IAC5D,OAAO,EAAE;QACP,MAAM,EAAE,aAAa;QACrB,QAAQ,EAAE,EAAE,WAAW,EAAE,CAAC,GAAG,oBAAoB,CAAC,EAAE;KACrD;IACD,QAAQ,EAAE;QACR,MAAM,CAAC,IAAI,EAAE,GAAG;YACd,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,2DAA2D;YAC3D,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACtD,MAAM,IAAI,GAAI,GAAG,CAAC,OAA2C,IAAI;gBAC/D,WAAW,EAAE,oBAAoB;aAClC,CAAC;YACF,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC1C,MAAM,OAAO,GAAG,wBAAwB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC3D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YAChC,6BAA6B;YAC7B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO;YACrC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvB,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Forbid assignment to `<obj>.id`. IDs should be immutable after creation.
3
- * Catches the TalkUp class of bugs where conv_* IDs get overwritten with resp_*.
3
+ * Catches a common class of bugs where IDs are overwritten after creation
4
+ * (e.g. a record's id field reassigned to a child entity's id).
4
5
  */
5
6
  declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
6
7
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"no-id-overwrite.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-id-overwrite.ts"],"names":[],"mappings":"AAEA;;;GAGG;;AACH,wBAiBG"}
1
+ {"version":3,"file":"no-id-overwrite.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-id-overwrite.ts"],"names":[],"mappings":"AAEA;;;;GAIG;;AACH,wBAiBG"}
@@ -1,7 +1,8 @@
1
1
  import { defineRule } from '@aicqtools/rule-sdk';
2
2
  /**
3
3
  * Forbid assignment to `<obj>.id`. IDs should be immutable after creation.
4
- * Catches the TalkUp class of bugs where conv_* IDs get overwritten with resp_*.
4
+ * Catches a common class of bugs where IDs are overwritten after creation
5
+ * (e.g. a record's id field reassigned to a child entity's id).
5
6
  */
6
7
  export default defineRule({
7
8
  id: 'no-id-overwrite',
@@ -1 +1 @@
1
- {"version":3,"file":"no-id-overwrite.js","sourceRoot":"","sources":["../../src/rules-default/no-id-overwrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;GAGG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,iBAAiB;IACrB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,0DAA0D;IACnE,SAAS,EAAE,0CAA0C;IACrD,QAAQ,EAAE;QACR,qBAAqB,CAAC,IAAI,EAAE,GAAG;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB;gBAAE,OAAO;YACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YACpD,IAAI,CAAC,QAAQ;gBAAE,OAAO;YACtB,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;gBAClC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;KACF;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"no-id-overwrite.js","sourceRoot":"","sources":["../../src/rules-default/no-id-overwrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;;;GAIG;AACH,eAAe,UAAU,CAAC;IACxB,EAAE,EAAE,iBAAiB;IACrB,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC;IAC7C,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,0DAA0D;IACnE,SAAS,EAAE,0CAA0C;IACrD,QAAQ,EAAE;QACR,qBAAqB,CAAC,IAAI,EAAE,GAAG;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB;gBAAE,OAAO;YACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;YACpD,IAAI,CAAC,QAAQ;gBAAE,OAAO;YACtB,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;gBAClC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;KACF;CACF,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
+ export declare const SKIP_FILE_RE: RegExp;
1
2
  declare const _default: import("@aicqtools/rule-sdk").FunctionRule;
2
3
  export default _default;
3
4
  //# sourceMappingURL=no-magic-number.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"no-magic-number.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":";AA6HA,wBAiBG"}
1
+ {"version":3,"file":"no-magic-number.d.ts","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":"AA0DA,eAAO,MAAM,YAAY,QAA0M,CAAC;;AA6FpO,wBA0BG"}
@@ -1,3 +1,4 @@
1
+ import { z } from 'zod';
1
2
  import { defineRule } from '@aicqtools/rule-sdk';
2
3
  /**
3
4
  * `no-magic-number` — info-severity rule that flags numeric literals appearing inline in
@@ -24,10 +25,30 @@ import { defineRule } from '@aicqtools/rule-sdk';
24
25
  * Allowed-numbers default extended to common-sense values: powers of two, common bases,
25
26
  * time/clock constants, etc.
26
27
  */
27
- const ALLOWED_NUMBERS = new Set([
28
+ /**
29
+ * Default allowed-number literals. Common-sense values: -2..2, base-10 / base-16 / base-2,
30
+ * time/clock constants, plus RFC 7231 / RFC 6585 HTTP status codes (beta.1 — the
31
+ * `res.status(200/404/500)` pattern in Next.js/Express/Hono/Fastify routes is universal
32
+ * and not a magic number in any meaningful sense). Alpha.14 exposes this list as
33
+ * `options.allowedNumbers` so users can extend (`['0', '1', '-1', '2', '60', '3600', '86400']`
34
+ * for time-heavy projects) or shrink the allow-list per project.
35
+ */
36
+ const DEFAULT_ALLOWED_NUMBERS = [
37
+ // -2..2, common bases, time/clock constants
28
38
  '0', '1', '-1', '2', '-2', '10', '16', '24', '60', '100', '1000', '1024',
29
- ]);
30
- const SKIP_FILE_RE = /(\.test\.|\.spec\.|__tests__|fixtures|\.config\.|\.polyfill\.|[/\\]polyfills[/\\]|[/\\]seeders[/\\]|[/\\]migrations[/\\])/;
39
+ // HTTP status codes (RFC 7231 / RFC 6585) — 100 already covered by base-10
40
+ '101',
41
+ '200', '201', '204',
42
+ '301', '302', '304',
43
+ '400', '401', '403', '404', '405', '409', '422', '429',
44
+ '500', '502', '503', '504',
45
+ ];
46
+ const optionsSchema = z
47
+ .object({
48
+ allowedNumbers: z.array(z.string()).default([...DEFAULT_ALLOWED_NUMBERS]),
49
+ })
50
+ .strict();
51
+ export const SKIP_FILE_RE = /(\.test\.|\.spec\.|__tests__|fixtures|\.config\.|\.polyfill\.|[/\\]polyfills[/\\]|[/\\]seeders[/\\]|[/\\]migrations[/\\]|[/\\](scripts|tools|bin)[/\\]|[/\\](native-bridge|service-worker)\.[jt]sx?$)/;
31
52
  // Callee names whose numeric args are almost always intentional, not magic numbers.
32
53
  // Matched on the leaf identifier (last name segment) — covers both `parseInt(...)` and
33
54
  // `Number.parseInt(...)` / `globalThis.setTimeout(...)`.
@@ -125,12 +146,21 @@ export default defineRule({
125
146
  severity: 'info',
126
147
  message: 'Magic number — extract to a named constant for clarity.',
127
148
  messageKo: '매직 넘버 — 명명된 상수로 추출해 의미를 명확히 하세요.',
149
+ skipPatterns: [SKIP_FILE_RE],
150
+ options: {
151
+ schema: optionsSchema,
152
+ defaults: { allowedNumbers: [...DEFAULT_ALLOWED_NUMBERS] },
153
+ },
128
154
  visitors: {
129
155
  number(node, ctx) {
130
- if (isInSkippedFile(ctx.filePath))
156
+ if (!ctx.skipBuiltinSkips && isInSkippedFile(ctx.filePath))
131
157
  return;
158
+ const opts = ctx.options ?? {
159
+ allowedNumbers: DEFAULT_ALLOWED_NUMBERS,
160
+ };
161
+ const allowed = new Set(opts.allowedNumbers);
132
162
  const text = ctx.textOf(node);
133
- if (ALLOWED_NUMBERS.has(text))
163
+ if (allowed.has(text))
134
164
  return;
135
165
  if (hasSkippableAncestor(node))
136
166
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"no-magic-number.js","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"no-magic-number.js","sourceRoot":"","sources":["../../src/rules-default/no-magic-number.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,14 @@ language: python
3
3
  severity: warning
4
4
  message: Avoid bare print() in production code; use the standard `logging` module.
5
5
  messageKo: 운영 코드에서 print() 사용 지양 — 표준 `logging` 모듈을 사용하세요.
6
+ options:
7
+ # Alpha.18 — YAML PatternRule framework consistency demo. The `query` below is static
8
+ # (`print` literal), so `disallowedFunctions` doesn't drive matching today; it's exposed
9
+ # purely so users can see the option via `aicq rules suggest` and override it in their
10
+ # config. Dynamic query substitution is deferred to a v1.0+ release.
11
+ defaults:
12
+ disallowedFunctions:
13
+ - print
6
14
  query: |
7
15
  (call
8
16
  function: (identifier) @fn
@@ -1,39 +1,91 @@
1
- import type { RuleOverride } from '@aicqtools/core';
1
+ import type { RuleEntry, RuleOverride } from '@aicqtools/core';
2
2
  import type { Rule } from '@aicqtools/rule-sdk';
3
+ import { type UnknownRuleOption } from './resolve-rule-options.js';
3
4
  /**
4
- * Resolution of `config.modules.guardrail.rules` (the `{ ruleId: 'off' | 'warn' | 'error' }` map)
5
- * against the loaded rule set. Filters out `off`'d rules, overrides severity for `warn`/`error`
6
- * entries, and reports unknown rule ids back to the caller so the CLI can warn the user once.
5
+ * Resolution of `config.modules.guardrail.rules` (the `{ ruleId: RuleEntry }` map) against the
6
+ * loaded rule set. Filters out `off`'d rules, overrides severity for `warn`/`error` entries,
7
+ * resolves alpha.14 per-rule options, and reports unknown rule ids + unknown option keys back
8
+ * to the caller so the CLI can warn the user once.
7
9
  */
8
10
  export interface ApplyRuleConfigResult {
9
11
  readonly rules: readonly Rule[];
10
- /** rule ids that appeared in the config map but matched no loaded rule */
12
+ /** Rule ids that appeared in the config map but matched no loaded rule. */
11
13
  readonly unknownIds: readonly string[];
14
+ /** Alpha.14 — resolved per-rule options keyed by ruleId. Absent entries = no options. */
15
+ readonly ruleOptions: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
16
+ /** Alpha.14 — unknown option keys per rule (typo surface). One entry per rule with typos. */
17
+ readonly unknownOptions: readonly UnknownRuleOption[];
18
+ /** Alpha.14 — zod schema parse failures keyed by ruleId (caller surfaces via stderr). */
19
+ readonly optionParseErrors: ReadonlyMap<string, string>;
12
20
  }
13
- type RuleLevel = 'off' | 'warn' | 'error';
14
21
  /**
15
22
  * Apply the user-supplied `rules:` map to a loaded rule list.
16
23
  *
17
24
  * - `off` → drop the rule from the returned list
18
25
  * - `warn`/`error` → return a copy of the rule with `severity` overridden
26
+ * - object shape (alpha.14) → optional `severity` override + optional `options` validated
27
+ * against the rule's own zod schema; resolved options attached via `ruleOptions` map.
19
28
  * - missing entry → rule passes through unchanged
20
29
  *
21
- * Map keys that don't correspond to any loaded rule are collected in `unknownIds`. The function
22
- * never throws; an invalid level value (should already be rejected by zod) is treated as "no
23
- * override" rather than crashing the run.
30
+ * Map keys that don't correspond to any loaded rule are collected in `unknownIds`. Unknown
31
+ * option keys (typos inside `options`) land in `unknownOptions`. Zod parse failures land in
32
+ * `optionParseErrors` the rule still runs with its `defaults`, never crashing the scan.
24
33
  */
25
- export declare function applyRuleConfig(rules: readonly Rule[], cfgMap: Readonly<Record<string, RuleLevel>> | undefined): ApplyRuleConfigResult;
34
+ export declare function applyRuleConfig(rules: readonly Rule[], cfgMap: Readonly<Record<string, RuleEntry>> | undefined): ApplyRuleConfigResult;
35
+ /**
36
+ * Auto-anchor a single `overrides.paths` glob (alpha.10).
37
+ *
38
+ * `fast-glob` returns absolute file paths, so a user-written `scripts/**` would silently never
39
+ * match. We prepend `**\/` unless the glob already carries an anchor token, mirroring the
40
+ * ESLint mental model where `paths: ['scripts/**']` means "any `scripts/` in the project":
41
+ *
42
+ * - leading `**` (with or without `/`) — already anchored, leave alone
43
+ * - leading `/` — Unix absolute path, user opted out of auto-anchor
44
+ * - leading `<letter>:/` — Windows drive path, same
45
+ * - leading `!` — negation; preserve the marker, normalize the body
46
+ *
47
+ * The function is pure and never throws. Empty input returns empty.
48
+ */
49
+ export declare function normalizeOverridePath(glob: string): string;
26
50
  /**
27
51
  * Apply per-path `overrides` (alpha.8) on top of an already-globally-resolved rule list.
28
52
  *
29
53
  * For each override entry whose `paths` globs match `filePath`, merge its `rules` map into a
30
- * per-file effective level map. Later matching entries win for the same rule id (ESLint semantics).
54
+ * per-file effective entry map. Later matching entries win for the same rule id (ESLint semantics).
31
55
  * `off` drops the rule for this file; `warn`/`error` copies the rule with overridden severity.
32
56
  *
57
+ * Alpha.14: override entries can also carry the object shape `{ severity?, options? }`. The
58
+ * resolved options override the global ones for the matched files. The function returns an
59
+ * augmented baseline-options map (cloned, never mutates the caller's map) so the runner can
60
+ * thread the per-file options into `RuleContext.options`.
61
+ *
33
62
  * Fast path: if no overrides are configured, returns the input list unchanged so the file loop
34
63
  * stays cheap when this feature is unused.
64
+ *
65
+ * Alpha.10: `paths` globs are auto-anchored via `normalizeOverridePath` so users can write
66
+ * `scripts/**` instead of `**\/scripts/**` and get the expected ESLint semantics. When the
67
+ * optional `matchCounts` array is provided, each matched override entry's slot is incremented;
68
+ * the caller (CLI) reads zero-valued slots to emit "matched no files — ignored." warnings.
35
69
  */
36
- export declare function applyOverridesForFile(baselineRules: readonly Rule[], overrides: readonly RuleOverride[], filePath: string): readonly Rule[];
70
+ /**
71
+ * Alpha.8/10 signature — returns `readonly Rule[]`. Preserved verbatim for back-compat with
72
+ * tests and external callers that don't need per-rule options. For runner usage (which threads
73
+ * options into RuleContext), call `applyOverridesForFileResolved` instead.
74
+ */
75
+ export declare function applyOverridesForFile(baselineRules: readonly Rule[], overrides: readonly RuleOverride[], filePath: string, matchCounts?: number[]): readonly Rule[];
76
+ /**
77
+ * Alpha.14 — extended return shape with per-rule resolved options. The runner calls this so
78
+ * `RuleContext.options` reflects per-file overrides on top of the global baseline.
79
+ */
80
+ export interface ApplyOverridesResult {
81
+ readonly rules: readonly Rule[];
82
+ /**
83
+ * Per-rule resolved options for this file. Always returned (cloned from `baselineRuleOptions`
84
+ * when no override matched, so callers can read it unconditionally).
85
+ */
86
+ readonly ruleOptions: ReadonlyMap<string, Readonly<Record<string, unknown>>>;
87
+ }
88
+ export declare function applyOverridesForFileResolved(baselineRules: readonly Rule[], overrides: readonly RuleOverride[], filePath: string, matchCounts?: number[], baselineRuleOptions?: ReadonlyMap<string, Readonly<Record<string, unknown>>>): ApplyOverridesResult;
37
89
  /**
38
90
  * Collect rule ids referenced by `overrides` entries that don't match any loaded rule, paired
39
91
  * with the index of the offending override entry. The caller (CLI) uses these to emit one
@@ -45,5 +97,19 @@ export interface UnknownOverrideId {
45
97
  readonly paths: readonly string[];
46
98
  }
47
99
  export declare function collectUnknownOverrideIds(baselineRules: readonly Rule[], overrides: readonly RuleOverride[]): readonly UnknownOverrideId[];
48
- export {};
100
+ /**
101
+ * Collect leading-`!` negation globs inside `overrides[i].paths` entries (alpha.11).
102
+ *
103
+ * Background: `applyOverridesForFile` matches a file via `micromatch.isMatch(file, paths)`, and
104
+ * `isMatch` with an array uses any-match (OR) semantics. A `!vendor/**` entry in `paths` therefore
105
+ * does NOT subtract from a sibling positive glob the way ESLint's `ignores` field would — it just
106
+ * silently no-ops. The CLI emits one stderr warning per offending entry so the silent footgun
107
+ * surfaces; users get pointed at the top-level `exclude:` field as the real opt-out path.
108
+ */
109
+ export interface NegationOverridePath {
110
+ readonly index: number;
111
+ /** The negation globs found in this entry (leading `!` preserved). */
112
+ readonly paths: readonly string[];
113
+ }
114
+ export declare function collectNegationPaths(overrides: readonly RuleOverride[]): readonly NegationOverridePath[];
49
115
  //# sourceMappingURL=apply-rule-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apply-rule-config.d.ts","sourceRoot":"","sources":["../../src/runner/apply-rule-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,KAAK,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AAM1C;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,GACtD,qBAAqB,CAgCvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,SAAS,IAAI,EAAE,EAC9B,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,QAAQ,EAAE,MAAM,GACf,SAAS,IAAI,EAAE,CAqCjB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,SAAS,IAAI,EAAE,EAC9B,SAAS,EAAE,SAAS,YAAY,EAAE,GACjC,SAAS,iBAAiB,EAAE,CAY9B"}
1
+ {"version":3,"file":"apply-rule-config.d.ts","sourceRoot":"","sources":["../../src/runner/apply-rule-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAa,YAAY,EAAY,MAAM,iBAAiB,CAAC;AACpF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEvF;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,yFAAyF;IACzF,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7E,6FAA6F;IAC7F,QAAQ,CAAC,cAAc,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtD,yFAAyF;IACzF,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzD;AAiBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,GACtD,qBAAqB,CAyDvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAa1D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,SAAS,IAAI,EAAE,EAC9B,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,EAAE,GACrB,SAAS,IAAI,EAAE,CAEjB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CAC9E;AAED,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,SAAS,IAAI,EAAE,EAC9B,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAC3E,oBAAoB,CAgEtB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,SAAS,IAAI,EAAE,EAC9B,SAAS,EAAE,SAAS,YAAY,EAAE,GACjC,SAAS,iBAAiB,EAAE,CAY9B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,SAAS,YAAY,EAAE,GACjC,SAAS,oBAAoB,EAAE,CAUjC"}