@runhalo/engine 0.3.1 → 0.5.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.
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * Django Framework Profile
4
+ *
5
+ * Django provides built-in protections that overlap with several COPPA rules:
6
+ * - Template engine auto-escapes all variables by default
7
+ * - SecurityMiddleware enforces HTTPS when configured
8
+ * - Built-in password validators enforce complexity requirements
9
+ * - django-lifecycle and django-reversion can handle data retention externally
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.djangoProfile = void 0;
13
+ exports.djangoProfile = {
14
+ id: 'django',
15
+ name: 'Django',
16
+ ecosystem: 'python',
17
+ handled_rules: [
18
+ {
19
+ rule_id: 'coppa-sec-015',
20
+ action: 'suppress',
21
+ reason: 'Django templates auto-escape all variables by default.',
22
+ documentation_url: 'https://docs.djangoproject.com/en/stable/ref/templates/language/#automatic-html-escaping',
23
+ },
24
+ {
25
+ rule_id: 'coppa-retention-005',
26
+ action: 'downgrade',
27
+ downgrade_to: 'low',
28
+ reason: 'Django models with django-lifecycle or django-reversion may handle retention externally.',
29
+ documentation_url: 'https://docs.djangoproject.com/en/stable/topics/db/models/',
30
+ },
31
+ {
32
+ rule_id: 'coppa-sec-006',
33
+ action: 'suppress',
34
+ reason: 'Django SecurityMiddleware enforces HTTPS when configured.',
35
+ documentation_url: 'https://docs.djangoproject.com/en/stable/ref/middleware/#module-django.middleware.security',
36
+ },
37
+ {
38
+ rule_id: 'coppa-sec-010',
39
+ action: 'suppress',
40
+ reason: 'Django built-in password validators enforce complexity.',
41
+ documentation_url: 'https://docs.djangoproject.com/en/stable/topics/auth/passwords/#module-django.contrib.auth.password_validation',
42
+ },
43
+ ],
44
+ safe_patterns: [
45
+ {
46
+ description: 'Django CSRF middleware for cross-site request forgery protection',
47
+ patterns: [/CsrfViewMiddleware/, /csrf_token/],
48
+ applies_to_rules: ['coppa-sec-015'],
49
+ },
50
+ {
51
+ description: 'Django admin interface with built-in auth and access controls',
52
+ patterns: [/admin\.site\.register/, /class.*Admin\(/, /admin\.py/],
53
+ applies_to_rules: ['coppa-auth-001', 'coppa-ui-008', 'coppa-default-020'],
54
+ },
55
+ ],
56
+ };
57
+ //# sourceMappingURL=django.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"django.js","sourceRoot":"","sources":["../../src/frameworks/django.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAIU,QAAA,aAAa,GAAqB;IAC7C,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,QAAQ;IACd,SAAS,EAAE,QAAQ;IACnB,aAAa,EAAE;QACb;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,wDAAwD;YAChE,iBAAiB,EAAE,0FAA0F;SAC9G;QACD;YACE,OAAO,EAAE,qBAAqB;YAC9B,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,0FAA0F;YAClG,iBAAiB,EAAE,4DAA4D;SAChF;QACD;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,2DAA2D;YACnE,iBAAiB,EAAE,4FAA4F;SAChH;QACD;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,yDAAyD;YACjE,iBAAiB,EAAE,gHAAgH;SACpI;KACF;IACD,aAAa,EAAE;QACb;YACE,WAAW,EAAE,kEAAkE;YAC/E,QAAQ,EAAE,CAAC,oBAAoB,EAAE,YAAY,CAAC;YAC9C,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;QACD;YACE,WAAW,EAAE,+DAA+D;YAC5E,QAAQ,EAAE,CAAC,uBAAuB,EAAE,gBAAgB,EAAE,WAAW,CAAC;YAClE,gBAAgB,EAAE,CAAC,gBAAgB,EAAE,cAAc,EAAE,mBAAmB,CAAC;SAC1E;KACF;CACF,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Framework Allowlisting System
3
+ *
4
+ * Entry point for Halo's framework-aware rule management. When a developer
5
+ * declares their framework in .halorc.json (e.g. { "framework": "nextjs" }),
6
+ * Halo loads the corresponding profile and automatically suppresses or
7
+ * downgrades rules that the framework already handles natively.
8
+ *
9
+ * Usage:
10
+ * import { applyFrameworkOverrides } from './frameworks';
11
+ * const result = applyFrameworkOverrides(violations, 'nextjs');
12
+ * // result.violations — filtered/downgraded violations
13
+ * // result.suppressedCount — number of violations removed
14
+ * // result.downgradedCount — number of violations with reduced severity
15
+ */
16
+ export type { FrameworkAction, FrameworkRuleOverride, FrameworkSafePattern, FrameworkProfile } from './types';
17
+ import { FrameworkProfile } from './types';
18
+ /**
19
+ * Minimal violation shape used by the framework system to avoid circular
20
+ * imports with the engine's Violation type. Any object with at least ruleId
21
+ * and severity will work.
22
+ */
23
+ interface ViolationLike {
24
+ ruleId: string;
25
+ severity: string;
26
+ [key: string]: any;
27
+ }
28
+ /**
29
+ * Look up a framework profile by its id.
30
+ *
31
+ * @param id - Framework identifier (e.g. "nextjs", "django", "rails")
32
+ * @returns The matching FrameworkProfile, or null if not found
33
+ */
34
+ export declare function getFrameworkProfile(id: string): FrameworkProfile | null;
35
+ /**
36
+ * List all registered framework ids.
37
+ *
38
+ * @returns Sorted array of framework id strings
39
+ */
40
+ export declare function listFrameworks(): string[];
41
+ /**
42
+ * Apply a framework's rule overrides to a set of violations.
43
+ *
44
+ * For each violation whose ruleId appears in the framework's handled_rules:
45
+ * - "suppress" removes the violation from the output entirely
46
+ * - "downgrade" reduces the violation's severity to the specified level
47
+ *
48
+ * Violations whose ruleId is NOT in the framework's profile are passed
49
+ * through unchanged.
50
+ *
51
+ * @param violations - Array of violation objects to filter
52
+ * @param frameworkId - Framework identifier to look up
53
+ * @returns Object with the filtered violations array and counts
54
+ */
55
+ export declare function applyFrameworkOverrides<T extends ViolationLike>(violations: T[], frameworkId: string): {
56
+ violations: T[];
57
+ suppressedCount: number;
58
+ downgradedCount: number;
59
+ };
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ /**
3
+ * Framework Allowlisting System
4
+ *
5
+ * Entry point for Halo's framework-aware rule management. When a developer
6
+ * declares their framework in .halorc.json (e.g. { "framework": "nextjs" }),
7
+ * Halo loads the corresponding profile and automatically suppresses or
8
+ * downgrades rules that the framework already handles natively.
9
+ *
10
+ * Usage:
11
+ * import { applyFrameworkOverrides } from './frameworks';
12
+ * const result = applyFrameworkOverrides(violations, 'nextjs');
13
+ * // result.violations — filtered/downgraded violations
14
+ * // result.suppressedCount — number of violations removed
15
+ * // result.downgradedCount — number of violations with reduced severity
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.getFrameworkProfile = getFrameworkProfile;
19
+ exports.listFrameworks = listFrameworks;
20
+ exports.applyFrameworkOverrides = applyFrameworkOverrides;
21
+ const nextjs_1 = require("./nextjs");
22
+ const django_1 = require("./django");
23
+ const rails_1 = require("./rails");
24
+ /** Registry of all built-in framework profiles keyed by id. */
25
+ const FRAMEWORK_REGISTRY = {
26
+ nextjs: nextjs_1.nextjsProfile,
27
+ django: django_1.djangoProfile,
28
+ rails: rails_1.railsProfile,
29
+ };
30
+ /**
31
+ * Look up a framework profile by its id.
32
+ *
33
+ * @param id - Framework identifier (e.g. "nextjs", "django", "rails")
34
+ * @returns The matching FrameworkProfile, or null if not found
35
+ */
36
+ function getFrameworkProfile(id) {
37
+ return FRAMEWORK_REGISTRY[id] ?? null;
38
+ }
39
+ /**
40
+ * List all registered framework ids.
41
+ *
42
+ * @returns Sorted array of framework id strings
43
+ */
44
+ function listFrameworks() {
45
+ return Object.keys(FRAMEWORK_REGISTRY).sort();
46
+ }
47
+ /**
48
+ * Apply a framework's rule overrides to a set of violations.
49
+ *
50
+ * For each violation whose ruleId appears in the framework's handled_rules:
51
+ * - "suppress" removes the violation from the output entirely
52
+ * - "downgrade" reduces the violation's severity to the specified level
53
+ *
54
+ * Violations whose ruleId is NOT in the framework's profile are passed
55
+ * through unchanged.
56
+ *
57
+ * @param violations - Array of violation objects to filter
58
+ * @param frameworkId - Framework identifier to look up
59
+ * @returns Object with the filtered violations array and counts
60
+ */
61
+ function applyFrameworkOverrides(violations, frameworkId) {
62
+ const profile = getFrameworkProfile(frameworkId);
63
+ if (!profile) {
64
+ return { violations: [...violations], suppressedCount: 0, downgradedCount: 0 };
65
+ }
66
+ // Build a lookup map from rule_id to override for O(1) access
67
+ const overrideMap = new Map(profile.handled_rules.map((override) => [override.rule_id, override]));
68
+ let suppressedCount = 0;
69
+ let downgradedCount = 0;
70
+ const filtered = [];
71
+ for (const violation of violations) {
72
+ const override = overrideMap.get(violation.ruleId);
73
+ if (!override) {
74
+ filtered.push(violation);
75
+ continue;
76
+ }
77
+ if (override.action === 'suppress') {
78
+ suppressedCount++;
79
+ // Violation is removed from output
80
+ continue;
81
+ }
82
+ if (override.action === 'downgrade' && override.downgrade_to) {
83
+ downgradedCount++;
84
+ // Create a shallow copy with the new severity to avoid mutating the original
85
+ filtered.push({ ...violation, severity: override.downgrade_to });
86
+ continue;
87
+ }
88
+ // Fallback: pass through if action is unrecognized
89
+ filtered.push(violation);
90
+ }
91
+ return { violations: filtered, suppressedCount, downgradedCount };
92
+ }
93
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/frameworks/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AAiCH,kDAEC;AAOD,wCAEC;AAgBD,0DA6CC;AApGD,qCAAyC;AACzC,qCAAyC;AACzC,mCAAuC;AAavC,+DAA+D;AAC/D,MAAM,kBAAkB,GAAqC;IAC3D,MAAM,EAAE,sBAAa;IACrB,MAAM,EAAE,sBAAa;IACrB,KAAK,EAAE,oBAAY;CACpB,CAAC;AAEF;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,EAAU;IAC5C,OAAO,kBAAkB,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,SAAgB,cAAc;IAC5B,OAAO,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,uBAAuB,CACrC,UAAe,EACf,WAAmB;IAEnB,MAAM,OAAO,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAEjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,UAAU,EAAE,CAAC,GAAG,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC;IAED,8DAA8D;IAC9D,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CACtE,CAAC;IAEF,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,MAAM,QAAQ,GAAQ,EAAE,CAAC;IAEzB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAEnD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzB,SAAS;QACX,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACnC,eAAe,EAAE,CAAC;YAClB,mCAAmC;YACnC,SAAS;QACX,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;YAC7D,eAAe,EAAE,CAAC;YAClB,6EAA6E;YAC7E,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;YACjE,SAAS;QACX,CAAC;QAED,mDAAmD;QACnD,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC;AACpE,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Next.js Framework Profile
3
+ *
4
+ * Next.js provides built-in protections that overlap with several COPPA rules:
5
+ * - React JSX auto-escaping mitigates most XSS vectors
6
+ * - HTTPS enforcement in production covers unencrypted PII transmission
7
+ * - Next.js Link component handles external navigation safely
8
+ * - Middleware provides centralized cookie management
9
+ */
10
+ import { FrameworkProfile } from './types';
11
+ export declare const nextjsProfile: FrameworkProfile;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /**
3
+ * Next.js Framework Profile
4
+ *
5
+ * Next.js provides built-in protections that overlap with several COPPA rules:
6
+ * - React JSX auto-escaping mitigates most XSS vectors
7
+ * - HTTPS enforcement in production covers unencrypted PII transmission
8
+ * - Next.js Link component handles external navigation safely
9
+ * - Middleware provides centralized cookie management
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.nextjsProfile = void 0;
13
+ exports.nextjsProfile = {
14
+ id: 'nextjs',
15
+ name: 'Next.js',
16
+ ecosystem: 'javascript',
17
+ handled_rules: [
18
+ {
19
+ rule_id: 'coppa-sec-015',
20
+ action: 'downgrade',
21
+ downgrade_to: 'low',
22
+ reason: 'React auto-escapes JSX output by default. dangerouslySetInnerHTML is the only XSS vector and is flagged separately.',
23
+ documentation_url: 'https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html',
24
+ },
25
+ {
26
+ rule_id: 'coppa-sec-006',
27
+ action: 'suppress',
28
+ reason: 'Next.js enforces HTTPS in production. API routes run server-side. Development HTTP is expected.',
29
+ documentation_url: 'https://nextjs.org/docs/app/api-reference/next-config-js/headers',
30
+ },
31
+ {
32
+ rule_id: 'coppa-ext-017',
33
+ action: 'downgrade',
34
+ downgrade_to: 'low',
35
+ reason: "Next.js Link component handles external navigation. rel='noopener noreferrer' is auto-added.",
36
+ documentation_url: 'https://nextjs.org/docs/app/api-reference/components/link',
37
+ },
38
+ {
39
+ rule_id: 'coppa-cookies-016',
40
+ action: 'downgrade',
41
+ downgrade_to: 'low',
42
+ reason: 'Next.js middleware can intercept and manage cookies centrally.',
43
+ documentation_url: 'https://nextjs.org/docs/app/building-your-application/routing/middleware',
44
+ },
45
+ ],
46
+ safe_patterns: [
47
+ {
48
+ description: 'Next.js Image component for optimized, safe image handling',
49
+ patterns: [/next\/image/, /<Image\s/],
50
+ applies_to_rules: ['coppa-ugc-014'],
51
+ },
52
+ {
53
+ description: 'Next.js middleware for centralized request/response interception',
54
+ patterns: [/middleware\.(ts|js)/, /NextResponse/],
55
+ applies_to_rules: ['coppa-sec-015'],
56
+ },
57
+ ],
58
+ };
59
+ //# sourceMappingURL=nextjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../../src/frameworks/nextjs.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAIU,QAAA,aAAa,GAAqB;IAC7C,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,YAAY;IACvB,aAAa,EAAE;QACb;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,qHAAqH;YAC7H,iBAAiB,EAAE,4FAA4F;SAChH;QACD;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,iGAAiG;YACzG,iBAAiB,EAAE,kEAAkE;SACtF;QACD;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,8FAA8F;YACtG,iBAAiB,EAAE,2DAA2D;SAC/E;QACD;YACE,OAAO,EAAE,mBAAmB;YAC5B,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,gEAAgE;YACxE,iBAAiB,EAAE,0EAA0E;SAC9F;KACF;IACD,aAAa,EAAE;QACb;YACE,WAAW,EAAE,4DAA4D;YACzE,QAAQ,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC;YACrC,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;QACD;YACE,WAAW,EAAE,kEAAkE;YAC/E,QAAQ,EAAE,CAAC,qBAAqB,EAAE,cAAc,CAAC;YACjD,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;KACF;CACF,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Ruby on Rails Framework Profile
3
+ *
4
+ * Rails provides built-in protections that overlap with several COPPA rules:
5
+ * - ERB templates auto-escape all output by default
6
+ * - Strong parameters filter mass assignment (mitigates PII leaks)
7
+ * - ActiveRecord supports soft delete via acts_as_paranoid or discard gem
8
+ * - force_ssl config enforces HTTPS application-wide
9
+ */
10
+ import { FrameworkProfile } from './types';
11
+ export declare const railsProfile: FrameworkProfile;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Ruby on Rails Framework Profile
4
+ *
5
+ * Rails provides built-in protections that overlap with several COPPA rules:
6
+ * - ERB templates auto-escape all output by default
7
+ * - Strong parameters filter mass assignment (mitigates PII leaks)
8
+ * - ActiveRecord supports soft delete via acts_as_paranoid or discard gem
9
+ * - force_ssl config enforces HTTPS application-wide
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.railsProfile = void 0;
13
+ exports.railsProfile = {
14
+ id: 'rails',
15
+ name: 'Ruby on Rails',
16
+ ecosystem: 'ruby',
17
+ handled_rules: [
18
+ {
19
+ rule_id: 'coppa-sec-015',
20
+ action: 'suppress',
21
+ reason: 'ERB templates auto-escape all output by default.',
22
+ documentation_url: 'https://guides.rubyonrails.org/security.html#cross-site-scripting-xss',
23
+ },
24
+ {
25
+ rule_id: 'coppa-data-002',
26
+ action: 'downgrade',
27
+ downgrade_to: 'low',
28
+ reason: 'Rails strong parameters filter mass assignment.',
29
+ documentation_url: 'https://guides.rubyonrails.org/action_controller_overview.html#strong-parameters',
30
+ },
31
+ {
32
+ rule_id: 'coppa-retention-005',
33
+ action: 'downgrade',
34
+ downgrade_to: 'low',
35
+ reason: 'ActiveRecord supports soft delete via acts_as_paranoid or discard gem.',
36
+ documentation_url: 'https://github.com/jhawthorn/discard',
37
+ },
38
+ {
39
+ rule_id: 'coppa-sec-006',
40
+ action: 'suppress',
41
+ reason: 'Rails force_ssl config enforces HTTPS.',
42
+ documentation_url: 'https://guides.rubyonrails.org/configuring.html#config-force-ssl',
43
+ },
44
+ ],
45
+ safe_patterns: [
46
+ {
47
+ description: 'Rails CSRF protection via protect_from_forgery and authenticity tokens',
48
+ patterns: [/protect_from_forgery/, /authenticity_token/],
49
+ applies_to_rules: ['coppa-sec-015'],
50
+ },
51
+ {
52
+ description: 'Rails ActiveRecord encryption for sensitive attributes',
53
+ patterns: [/encrypts\s+:/, /has_encrypted/],
54
+ applies_to_rules: ['coppa-sec-006'],
55
+ },
56
+ ],
57
+ };
58
+ //# sourceMappingURL=rails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rails.js","sourceRoot":"","sources":["../../src/frameworks/rails.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAIU,QAAA,YAAY,GAAqB;IAC5C,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,eAAe;IACrB,SAAS,EAAE,MAAM;IACjB,aAAa,EAAE;QACb;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,kDAAkD;YAC1D,iBAAiB,EAAE,uEAAuE;SAC3F;QACD;YACE,OAAO,EAAE,gBAAgB;YACzB,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,iDAAiD;YACzD,iBAAiB,EAAE,kFAAkF;SACtG;QACD;YACE,OAAO,EAAE,qBAAqB;YAC9B,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,wEAAwE;YAChF,iBAAiB,EAAE,sCAAsC;SAC1D;QACD;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,wCAAwC;YAChD,iBAAiB,EAAE,kEAAkE;SACtF;KACF;IACD,aAAa,EAAE;QACb;YACE,WAAW,EAAE,wEAAwE;YACrF,QAAQ,EAAE,CAAC,sBAAsB,EAAE,oBAAoB,CAAC;YACxD,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;QACD;YACE,WAAW,EAAE,wDAAwD;YACrE,QAAQ,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;YAC3C,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;KACF;CACF,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Framework Allowlisting Type Definitions
3
+ *
4
+ * Defines the type contracts for framework profiles that declare which
5
+ * COPPA/ethical rules a framework already handles natively. When a developer
6
+ * declares their framework in .halorc.json, Halo uses these profiles to
7
+ * suppress or downgrade rules the framework covers automatically.
8
+ */
9
+ export type FrameworkAction = 'suppress' | 'downgrade';
10
+ export interface FrameworkRuleOverride {
11
+ rule_id: string;
12
+ action: FrameworkAction;
13
+ downgrade_to?: 'critical' | 'high' | 'medium' | 'low';
14
+ condition?: string;
15
+ reason: string;
16
+ documentation_url?: string;
17
+ }
18
+ export interface FrameworkSafePattern {
19
+ description: string;
20
+ patterns: RegExp[];
21
+ applies_to_rules: string[];
22
+ }
23
+ export interface FrameworkProfile {
24
+ id: string;
25
+ name: string;
26
+ ecosystem: 'javascript' | 'python' | 'ruby';
27
+ handled_rules: FrameworkRuleOverride[];
28
+ safe_patterns: FrameworkSafePattern[];
29
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ /**
3
+ * Framework Allowlisting Type Definitions
4
+ *
5
+ * Defines the type contracts for framework profiles that declare which
6
+ * COPPA/ethical rules a framework already handles natively. When a developer
7
+ * declares their framework in .halorc.json, Halo uses these profiles to
8
+ * suppress or downgrade rules the framework covers automatically.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/frameworks/types.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG"}
package/dist/index.d.ts CHANGED
@@ -7,7 +7,10 @@
7
7
  * Sprint 1 Fixes: Added tree-sitter for AST analysis, YAML rule loading
8
8
  */
9
9
  import Parser from 'tree-sitter';
10
+ import { ConfidenceResult, ConfidenceSignals, ConfidenceInterpretation, ViolationInput } from './context-analyzer';
11
+ export type { ConfidenceResult, ConfidenceSignals, ConfidenceInterpretation, ViolationInput };
10
12
  export type Severity = 'critical' | 'high' | 'medium' | 'low';
13
+ export type ASTVerdict = 'confirmed' | 'suppressed' | 'regex_only';
11
14
  export type Fixability = 'auto' | 'guided' | 'flag-only';
12
15
  export interface RemediationSpec {
13
16
  fixability: Fixability;
@@ -34,6 +37,20 @@ export interface Violation {
34
37
  matchType?: 'regex' | 'ast' | 'hybrid';
35
38
  fixability?: Fixability;
36
39
  remediation?: RemediationSpec;
40
+ /** AST analysis verdict: confirmed, suppressed, or regex_only */
41
+ astVerdict?: ASTVerdict;
42
+ /** AST analysis confidence: 0.0 to 1.0 */
43
+ astConfidence?: number;
44
+ /** Reason for AST verdict */
45
+ astReason?: string;
46
+ /** Whether this violation was suppressed by framework profile */
47
+ frameworkSuppressed?: boolean;
48
+ /** ContextAnalyzer confidence score (0.0-1.0) */
49
+ confidence?: number;
50
+ /** ContextAnalyzer interpretation */
51
+ confidenceInterpretation?: ConfidenceInterpretation;
52
+ /** ContextAnalyzer reason string */
53
+ confidenceReason?: string;
37
54
  }
38
55
  export interface Rule {
39
56
  id: string;
@@ -51,6 +68,43 @@ export interface SuppressionConfig {
51
68
  commentPattern: string;
52
69
  }
53
70
  export declare function loadRulesFromYAML(yamlPath: string): Rule[];
71
+ export interface JSONRuleConfig {
72
+ version: string;
73
+ generated_at: string;
74
+ packs: Record<string, {
75
+ id: string;
76
+ name: string;
77
+ description: string;
78
+ jurisdiction: string;
79
+ jurisdiction_level: string;
80
+ is_free: boolean;
81
+ effective_date: string | null;
82
+ source_url: string;
83
+ }>;
84
+ rules: JSONRule[];
85
+ }
86
+ export interface JSONRule {
87
+ id: string;
88
+ name: string;
89
+ severity: Severity;
90
+ category: string;
91
+ description: string;
92
+ patterns: Array<{
93
+ pattern: string;
94
+ flags: string;
95
+ }>;
96
+ fix_suggestion: string;
97
+ penalty: string;
98
+ languages: string[];
99
+ packs: string[];
100
+ fixability: string;
101
+ transform_type: string | null;
102
+ scaffold_id: string | null;
103
+ guidance_url: string | null;
104
+ }
105
+ export declare function loadRulesFromJSON(jsonPath: string): Rule[];
106
+ export declare function loadRulesFromJSONByPack(jsonPath: string, packIds: string[]): Rule[];
107
+ export declare function compileRawRules(rawRules: JSONRule[]): Rule[];
54
108
  export declare class TreeSitterParser {
55
109
  private parser;
56
110
  constructor();
@@ -124,6 +178,13 @@ export interface EngineConfig {
124
178
  ethical?: boolean;
125
179
  aiAudit?: boolean;
126
180
  sectorAuSbd?: boolean;
181
+ sectorAuOsa?: boolean;
182
+ packs?: string[];
183
+ loadedRules?: Rule[];
184
+ framework?: string;
185
+ astAnalysis?: boolean;
186
+ historicalFPRates?: Record<string, number>;
187
+ suppressionRates?: Record<string, number>;
127
188
  }
128
189
  export interface ScanResult {
129
190
  filePath: string;
@@ -137,7 +198,20 @@ export declare class HaloEngine {
137
198
  private config;
138
199
  private rules;
139
200
  private treeSitter;
201
+ private astEngine;
202
+ private contextAnalyzer;
140
203
  constructor(config?: EngineConfig);
204
+ /**
205
+ * Load rules from the bundled rules.json file, filtered by pack IDs.
206
+ * Falls back to empty array if rules.json not found.
207
+ */
208
+ private loadBundledRulesByPack;
209
+ /**
210
+ * Resolve legacy boolean flags to pack IDs.
211
+ * Maps ethical/aiAudit/sectorAuSbd booleans to their pack ID equivalents.
212
+ * Always includes 'coppa' as the base pack.
213
+ */
214
+ static resolvePacks(config: EngineConfig): string[];
141
215
  /**
142
216
  * Get the tree-sitter parser for advanced AST analysis
143
217
  */