@runhalo/engine 0.4.0 → 0.6.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.
- package/dist/ast-engine.d.ts +60 -0
- package/dist/ast-engine.js +653 -0
- package/dist/ast-engine.js.map +1 -0
- package/dist/context-analyzer.d.ts +209 -0
- package/dist/context-analyzer.js +408 -0
- package/dist/context-analyzer.js.map +1 -0
- package/dist/data-flow-tracer.d.ts +106 -0
- package/dist/data-flow-tracer.js +506 -0
- package/dist/data-flow-tracer.js.map +1 -0
- package/dist/fp-patterns.d.ts +36 -0
- package/dist/fp-patterns.js +426 -0
- package/dist/fp-patterns.js.map +1 -0
- package/dist/frameworks/angular.d.ts +11 -0
- package/dist/frameworks/angular.js +41 -0
- package/dist/frameworks/angular.js.map +1 -0
- package/dist/frameworks/django.d.ts +11 -0
- package/dist/frameworks/django.js +57 -0
- package/dist/frameworks/django.js.map +1 -0
- package/dist/frameworks/index.d.ts +59 -0
- package/dist/frameworks/index.js +99 -0
- package/dist/frameworks/index.js.map +1 -0
- package/dist/frameworks/nextjs.d.ts +11 -0
- package/dist/frameworks/nextjs.js +59 -0
- package/dist/frameworks/nextjs.js.map +1 -0
- package/dist/frameworks/rails.d.ts +11 -0
- package/dist/frameworks/rails.js +58 -0
- package/dist/frameworks/rails.js.map +1 -0
- package/dist/frameworks/react.d.ts +13 -0
- package/dist/frameworks/react.js +36 -0
- package/dist/frameworks/react.js.map +1 -0
- package/dist/frameworks/types.d.ts +29 -0
- package/dist/frameworks/types.js +11 -0
- package/dist/frameworks/types.js.map +1 -0
- package/dist/frameworks/vue.d.ts +9 -0
- package/dist/frameworks/vue.js +39 -0
- package/dist/frameworks/vue.js.map +1 -0
- package/dist/graduation/fp-verdict-logger.d.ts +81 -0
- package/dist/graduation/fp-verdict-logger.js +130 -0
- package/dist/graduation/fp-verdict-logger.js.map +1 -0
- package/dist/graduation/graduation-codifier.d.ts +37 -0
- package/dist/graduation/graduation-codifier.js +205 -0
- package/dist/graduation/graduation-codifier.js.map +1 -0
- package/dist/graduation/graduation-validator.d.ts +73 -0
- package/dist/graduation/graduation-validator.js +204 -0
- package/dist/graduation/graduation-validator.js.map +1 -0
- package/dist/graduation/index.d.ts +71 -0
- package/dist/graduation/index.js +105 -0
- package/dist/graduation/index.js.map +1 -0
- package/dist/graduation/pattern-aggregator.d.ts +77 -0
- package/dist/graduation/pattern-aggregator.js +154 -0
- package/dist/graduation/pattern-aggregator.js.map +1 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.js +718 -61
- package/dist/index.js.map +1 -1
- package/dist/review-board/two-agent-review.d.ts +152 -0
- package/dist/review-board/two-agent-review.js +463 -0
- package/dist/review-board/two-agent-review.js.map +1 -0
- package/dist/scope-analyzer.d.ts +91 -0
- package/dist/scope-analyzer.js +300 -0
- package/dist/scope-analyzer.js.map +1 -0
- package/package.json +9 -2
- package/rules/coppa-tier-1.yaml +17 -10
- package/rules/rules.json +2094 -99
- package/rules/validation-report.json +58 -0
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
const react_1 = require("./react");
|
|
25
|
+
const vue_1 = require("./vue");
|
|
26
|
+
const angular_1 = require("./angular");
|
|
27
|
+
/** Registry of all built-in framework profiles keyed by id. */
|
|
28
|
+
const FRAMEWORK_REGISTRY = {
|
|
29
|
+
nextjs: nextjs_1.nextjsProfile,
|
|
30
|
+
django: django_1.djangoProfile,
|
|
31
|
+
rails: rails_1.railsProfile,
|
|
32
|
+
react: react_1.reactProfile,
|
|
33
|
+
vue: vue_1.vueProfile,
|
|
34
|
+
angular: angular_1.angularProfile,
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Look up a framework profile by its id.
|
|
38
|
+
*
|
|
39
|
+
* @param id - Framework identifier (e.g. "nextjs", "django", "rails")
|
|
40
|
+
* @returns The matching FrameworkProfile, or null if not found
|
|
41
|
+
*/
|
|
42
|
+
function getFrameworkProfile(id) {
|
|
43
|
+
return FRAMEWORK_REGISTRY[id] ?? null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* List all registered framework ids.
|
|
47
|
+
*
|
|
48
|
+
* @returns Sorted array of framework id strings
|
|
49
|
+
*/
|
|
50
|
+
function listFrameworks() {
|
|
51
|
+
return Object.keys(FRAMEWORK_REGISTRY).sort();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Apply a framework's rule overrides to a set of violations.
|
|
55
|
+
*
|
|
56
|
+
* For each violation whose ruleId appears in the framework's handled_rules:
|
|
57
|
+
* - "suppress" removes the violation from the output entirely
|
|
58
|
+
* - "downgrade" reduces the violation's severity to the specified level
|
|
59
|
+
*
|
|
60
|
+
* Violations whose ruleId is NOT in the framework's profile are passed
|
|
61
|
+
* through unchanged.
|
|
62
|
+
*
|
|
63
|
+
* @param violations - Array of violation objects to filter
|
|
64
|
+
* @param frameworkId - Framework identifier to look up
|
|
65
|
+
* @returns Object with the filtered violations array and counts
|
|
66
|
+
*/
|
|
67
|
+
function applyFrameworkOverrides(violations, frameworkId) {
|
|
68
|
+
const profile = getFrameworkProfile(frameworkId);
|
|
69
|
+
if (!profile) {
|
|
70
|
+
return { violations: [...violations], suppressedCount: 0, downgradedCount: 0 };
|
|
71
|
+
}
|
|
72
|
+
// Build a lookup map from rule_id to override for O(1) access
|
|
73
|
+
const overrideMap = new Map(profile.handled_rules.map((override) => [override.rule_id, override]));
|
|
74
|
+
let suppressedCount = 0;
|
|
75
|
+
let downgradedCount = 0;
|
|
76
|
+
const filtered = [];
|
|
77
|
+
for (const violation of violations) {
|
|
78
|
+
const override = overrideMap.get(violation.ruleId);
|
|
79
|
+
if (!override) {
|
|
80
|
+
filtered.push(violation);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (override.action === 'suppress') {
|
|
84
|
+
suppressedCount++;
|
|
85
|
+
// Violation is removed from output
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (override.action === 'downgrade' && override.downgrade_to) {
|
|
89
|
+
downgradedCount++;
|
|
90
|
+
// Create a shallow copy with the new severity to avoid mutating the original
|
|
91
|
+
filtered.push({ ...violation, severity: override.downgrade_to });
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
// Fallback: pass through if action is unrecognized
|
|
95
|
+
filtered.push(violation);
|
|
96
|
+
}
|
|
97
|
+
return { violations: filtered, suppressedCount, downgradedCount };
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/frameworks/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AAuCH,kDAEC;AAOD,wCAEC;AAgBD,0DA6CC;AA1GD,qCAAyC;AACzC,qCAAyC;AACzC,mCAAuC;AACvC,mCAAuC;AACvC,+BAAmC;AACnC,uCAA2C;AAa3C,+DAA+D;AAC/D,MAAM,kBAAkB,GAAqC;IAC3D,MAAM,EAAE,sBAAa;IACrB,MAAM,EAAE,sBAAa;IACrB,KAAK,EAAE,oBAAY;IACnB,KAAK,EAAE,oBAAY;IACnB,GAAG,EAAE,gBAAU;IACf,OAAO,EAAE,wBAAc;CACxB,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,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Framework Profile
|
|
3
|
+
*
|
|
4
|
+
* React provides JSX auto-escaping which mitigates most XSS vectors.
|
|
5
|
+
* Unlike Next.js, React does NOT provide:
|
|
6
|
+
* - HTTPS enforcement (deployment-dependent)
|
|
7
|
+
* - Safe link component (no built-in <Link> with rel attributes)
|
|
8
|
+
* - Cookie middleware (client-side only)
|
|
9
|
+
*
|
|
10
|
+
* This profile is deliberately narrower than the Next.js profile.
|
|
11
|
+
*/
|
|
12
|
+
import { FrameworkProfile } from './types';
|
|
13
|
+
export declare const reactProfile: FrameworkProfile;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* React Framework Profile
|
|
4
|
+
*
|
|
5
|
+
* React provides JSX auto-escaping which mitigates most XSS vectors.
|
|
6
|
+
* Unlike Next.js, React does NOT provide:
|
|
7
|
+
* - HTTPS enforcement (deployment-dependent)
|
|
8
|
+
* - Safe link component (no built-in <Link> with rel attributes)
|
|
9
|
+
* - Cookie middleware (client-side only)
|
|
10
|
+
*
|
|
11
|
+
* This profile is deliberately narrower than the Next.js profile.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.reactProfile = void 0;
|
|
15
|
+
exports.reactProfile = {
|
|
16
|
+
id: 'react',
|
|
17
|
+
name: 'React',
|
|
18
|
+
ecosystem: 'javascript',
|
|
19
|
+
handled_rules: [
|
|
20
|
+
{
|
|
21
|
+
rule_id: 'coppa-sec-015',
|
|
22
|
+
action: 'downgrade',
|
|
23
|
+
downgrade_to: 'low',
|
|
24
|
+
reason: 'React auto-escapes JSX output by default. dangerouslySetInnerHTML is the only XSS vector.',
|
|
25
|
+
documentation_url: 'https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
safe_patterns: [
|
|
29
|
+
{
|
|
30
|
+
description: 'React JSX auto-escaping protects against reflected XSS',
|
|
31
|
+
patterns: [/React/, /jsx/, /createElement/],
|
|
32
|
+
applies_to_rules: ['coppa-sec-015'],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/frameworks/react.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAIU,QAAA,YAAY,GAAqB;IAC5C,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,OAAO;IACb,SAAS,EAAE,YAAY;IACvB,aAAa,EAAE;QACb;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,2FAA2F;YACnG,iBAAiB,EAAE,4FAA4F;SAChH;KACF;IACD,aAAa,EAAE;QACb;YACE,WAAW,EAAE,wDAAwD;YACrE,QAAQ,EAAE,CAAC,OAAO,EAAE,KAAK,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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue.js Framework Profile
|
|
3
|
+
*
|
|
4
|
+
* Vue provides template auto-escaping which mitigates XSS vectors.
|
|
5
|
+
* v-html is the explicit escape hatch (similar to React's dangerouslySetInnerHTML).
|
|
6
|
+
* Vue Router provides safe navigation handling.
|
|
7
|
+
*/
|
|
8
|
+
import { FrameworkProfile } from './types';
|
|
9
|
+
export declare const vueProfile: FrameworkProfile;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vue.js Framework Profile
|
|
4
|
+
*
|
|
5
|
+
* Vue provides template auto-escaping which mitigates XSS vectors.
|
|
6
|
+
* v-html is the explicit escape hatch (similar to React's dangerouslySetInnerHTML).
|
|
7
|
+
* Vue Router provides safe navigation handling.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.vueProfile = void 0;
|
|
11
|
+
exports.vueProfile = {
|
|
12
|
+
id: 'vue',
|
|
13
|
+
name: 'Vue.js',
|
|
14
|
+
ecosystem: 'javascript',
|
|
15
|
+
handled_rules: [
|
|
16
|
+
{
|
|
17
|
+
rule_id: 'coppa-sec-015',
|
|
18
|
+
action: 'downgrade',
|
|
19
|
+
downgrade_to: 'low',
|
|
20
|
+
reason: 'Vue auto-escapes template interpolation by default. v-html is the only XSS vector.',
|
|
21
|
+
documentation_url: 'https://vuejs.org/guide/best-practices/security.html#rule-no-1-never-use-non-trusted-templates',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
rule_id: 'coppa-ext-017',
|
|
25
|
+
action: 'downgrade',
|
|
26
|
+
downgrade_to: 'low',
|
|
27
|
+
reason: 'Vue Router can be configured to handle external navigation with guards.',
|
|
28
|
+
documentation_url: 'https://router.vuejs.org/guide/advanced/navigation-guards.html',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
safe_patterns: [
|
|
32
|
+
{
|
|
33
|
+
description: 'Vue template auto-escaping protects against XSS',
|
|
34
|
+
patterns: [/Vue/, /createApp/, /\.vue$/],
|
|
35
|
+
applies_to_rules: ['coppa-sec-015'],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.js","sourceRoot":"","sources":["../../src/frameworks/vue.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAIU,QAAA,UAAU,GAAqB;IAC1C,EAAE,EAAE,KAAK;IACT,IAAI,EAAE,QAAQ;IACd,SAAS,EAAE,YAAY;IACvB,aAAa,EAAE;QACb;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,oFAAoF;YAC5F,iBAAiB,EAAE,gGAAgG;SACpH;QACD;YACE,OAAO,EAAE,eAAe;YACxB,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,yEAAyE;YACjF,iBAAiB,EAAE,gEAAgE;SACpF;KACF;IACD,aAAa,EAAE;QACb;YACE,WAAW,EAAE,iDAAiD;YAC9D,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC;YACxC,gBAAgB,EAAE,CAAC,eAAe,CAAC;SACpC;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sprint 13a Week 2: FP Verdict Logger
|
|
3
|
+
*
|
|
4
|
+
* Stage 1 of the Graduation Pipeline.
|
|
5
|
+
* Logs each AI Review Board verdict to a structured JSONL file.
|
|
6
|
+
* Captures the fpPatternId, confidence, and context needed for
|
|
7
|
+
* downstream aggregation.
|
|
8
|
+
*
|
|
9
|
+
* Output: One JSONL file per scan, written to a configurable directory.
|
|
10
|
+
* Each line is a complete VerdictLogEntry.
|
|
11
|
+
*/
|
|
12
|
+
export interface VerdictLogEntry {
|
|
13
|
+
/** Timestamp of the verdict */
|
|
14
|
+
timestamp: string;
|
|
15
|
+
/** Scan identifier (for grouping entries from the same scan) */
|
|
16
|
+
scanId: string;
|
|
17
|
+
/** The rule that was evaluated */
|
|
18
|
+
ruleId: string;
|
|
19
|
+
/** File where the violation was found */
|
|
20
|
+
filePath: string;
|
|
21
|
+
/** Line number */
|
|
22
|
+
line: number;
|
|
23
|
+
/** The verdict from the Review Board */
|
|
24
|
+
verdict: 'confirmed' | 'downgraded' | 'escalated' | 'dismissed';
|
|
25
|
+
/** Confidence score (1-10) */
|
|
26
|
+
confidence: number;
|
|
27
|
+
/** FP pattern ID if dismissed */
|
|
28
|
+
fpPatternId?: string;
|
|
29
|
+
/** Human-readable FP reason */
|
|
30
|
+
fpReason?: string;
|
|
31
|
+
/** Code snippet for pattern analysis */
|
|
32
|
+
codeSnippet?: string;
|
|
33
|
+
/** File metadata flags at time of scan */
|
|
34
|
+
fileMetadata?: {
|
|
35
|
+
language: string;
|
|
36
|
+
isVendor: boolean;
|
|
37
|
+
isTest: boolean;
|
|
38
|
+
isAdmin: boolean;
|
|
39
|
+
isConsent: boolean;
|
|
40
|
+
isDocGenerator: boolean;
|
|
41
|
+
};
|
|
42
|
+
/** Whether this was from multi-agent review */
|
|
43
|
+
multiAgent?: boolean;
|
|
44
|
+
/** If multi-agent, the agreement level */
|
|
45
|
+
agreementLevel?: 'full' | 'partial' | 'split';
|
|
46
|
+
/** Model used for the review */
|
|
47
|
+
modelUsed?: string;
|
|
48
|
+
/** Prompt version identifier */
|
|
49
|
+
promptVersion?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare class FPVerdictLogger {
|
|
52
|
+
private logDir;
|
|
53
|
+
private scanId;
|
|
54
|
+
private logPath;
|
|
55
|
+
private promptVersion;
|
|
56
|
+
constructor(options: {
|
|
57
|
+
logDir: string;
|
|
58
|
+
scanId: string;
|
|
59
|
+
promptVersion?: string;
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Log a single verdict entry.
|
|
63
|
+
*/
|
|
64
|
+
log(entry: Omit<VerdictLogEntry, 'timestamp' | 'scanId' | 'promptVersion'>): void;
|
|
65
|
+
/**
|
|
66
|
+
* Log a batch of verdict entries (from a Review Board response).
|
|
67
|
+
*/
|
|
68
|
+
logBatch(entries: Array<Omit<VerdictLogEntry, 'timestamp' | 'scanId' | 'promptVersion'>>): void;
|
|
69
|
+
/**
|
|
70
|
+
* Get the path to the current log file.
|
|
71
|
+
*/
|
|
72
|
+
getLogPath(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Read all entries from a log file.
|
|
75
|
+
*/
|
|
76
|
+
static readLog(logPath: string): VerdictLogEntry[];
|
|
77
|
+
/**
|
|
78
|
+
* Read all log files from a directory.
|
|
79
|
+
*/
|
|
80
|
+
static readAllLogs(logDir: string): VerdictLogEntry[];
|
|
81
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sprint 13a Week 2: FP Verdict Logger
|
|
4
|
+
*
|
|
5
|
+
* Stage 1 of the Graduation Pipeline.
|
|
6
|
+
* Logs each AI Review Board verdict to a structured JSONL file.
|
|
7
|
+
* Captures the fpPatternId, confidence, and context needed for
|
|
8
|
+
* downstream aggregation.
|
|
9
|
+
*
|
|
10
|
+
* Output: One JSONL file per scan, written to a configurable directory.
|
|
11
|
+
* Each line is a complete VerdictLogEntry.
|
|
12
|
+
*/
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
+
var ownKeys = function(o) {
|
|
31
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
+
var ar = [];
|
|
33
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
+
return ar;
|
|
35
|
+
};
|
|
36
|
+
return ownKeys(o);
|
|
37
|
+
};
|
|
38
|
+
return function (mod) {
|
|
39
|
+
if (mod && mod.__esModule) return mod;
|
|
40
|
+
var result = {};
|
|
41
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
+
__setModuleDefault(result, mod);
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
})();
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.FPVerdictLogger = void 0;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
// ─── Logger ─────────────────────────────────────────────────────────────────
|
|
51
|
+
class FPVerdictLogger {
|
|
52
|
+
constructor(options) {
|
|
53
|
+
this.logDir = options.logDir;
|
|
54
|
+
this.scanId = options.scanId;
|
|
55
|
+
this.promptVersion = options.promptVersion || 'v1.0';
|
|
56
|
+
this.logPath = path.join(this.logDir, `verdicts-${this.scanId}.jsonl`);
|
|
57
|
+
// Ensure log directory exists
|
|
58
|
+
if (!fs.existsSync(this.logDir)) {
|
|
59
|
+
fs.mkdirSync(this.logDir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Log a single verdict entry.
|
|
64
|
+
*/
|
|
65
|
+
log(entry) {
|
|
66
|
+
const fullEntry = {
|
|
67
|
+
...entry,
|
|
68
|
+
timestamp: new Date().toISOString(),
|
|
69
|
+
scanId: this.scanId,
|
|
70
|
+
promptVersion: this.promptVersion,
|
|
71
|
+
};
|
|
72
|
+
fs.appendFileSync(this.logPath, JSON.stringify(fullEntry) + '\n', 'utf-8');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Log a batch of verdict entries (from a Review Board response).
|
|
76
|
+
*/
|
|
77
|
+
logBatch(entries) {
|
|
78
|
+
const lines = entries.map(entry => {
|
|
79
|
+
const fullEntry = {
|
|
80
|
+
...entry,
|
|
81
|
+
timestamp: new Date().toISOString(),
|
|
82
|
+
scanId: this.scanId,
|
|
83
|
+
promptVersion: this.promptVersion,
|
|
84
|
+
};
|
|
85
|
+
return JSON.stringify(fullEntry);
|
|
86
|
+
});
|
|
87
|
+
fs.appendFileSync(this.logPath, lines.join('\n') + '\n', 'utf-8');
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get the path to the current log file.
|
|
91
|
+
*/
|
|
92
|
+
getLogPath() {
|
|
93
|
+
return this.logPath;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Read all entries from a log file.
|
|
97
|
+
*/
|
|
98
|
+
static readLog(logPath) {
|
|
99
|
+
if (!fs.existsSync(logPath))
|
|
100
|
+
return [];
|
|
101
|
+
return fs.readFileSync(logPath, 'utf-8')
|
|
102
|
+
.split('\n')
|
|
103
|
+
.filter(line => line.trim())
|
|
104
|
+
.map(line => {
|
|
105
|
+
try {
|
|
106
|
+
return JSON.parse(line);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
.filter((entry) => entry !== null);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Read all log files from a directory.
|
|
116
|
+
*/
|
|
117
|
+
static readAllLogs(logDir) {
|
|
118
|
+
if (!fs.existsSync(logDir))
|
|
119
|
+
return [];
|
|
120
|
+
const files = fs.readdirSync(logDir)
|
|
121
|
+
.filter(f => f.startsWith('verdicts-') && f.endsWith('.jsonl'));
|
|
122
|
+
const allEntries = [];
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
allEntries.push(...FPVerdictLogger.readLog(path.join(logDir, file)));
|
|
125
|
+
}
|
|
126
|
+
return allEntries;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.FPVerdictLogger = FPVerdictLogger;
|
|
130
|
+
//# sourceMappingURL=fp-verdict-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fp-verdict-logger.js","sourceRoot":"","sources":["../../src/graduation/fp-verdict-logger.ts"],"names":[],"mappings":"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"}
|