@principles/core 1.206.0 → 1.207.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/runtime-v2/__tests__/architecture-regression.test.js +2 -0
  2. package/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  3. package/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js +85 -7
  4. package/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js.map +1 -1
  5. package/dist/runtime-v2/__tests__/v2-adversarial-cases.test.d.ts +2 -0
  6. package/dist/runtime-v2/__tests__/v2-adversarial-cases.test.d.ts.map +1 -0
  7. package/dist/runtime-v2/__tests__/v2-adversarial-cases.test.js +211 -0
  8. package/dist/runtime-v2/__tests__/v2-adversarial-cases.test.js.map +1 -0
  9. package/dist/runtime-v2/internalization/adversarial-case.d.ts.map +1 -1
  10. package/dist/runtime-v2/internalization/adversarial-case.js +24 -0
  11. package/dist/runtime-v2/internalization/adversarial-case.js.map +1 -1
  12. package/dist/runtime-v2/internalization/evaluator-output.d.ts +8 -0
  13. package/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
  14. package/dist/runtime-v2/internalization/evaluator-output.js +10 -0
  15. package/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
  16. package/dist/runtime-v2/internalization/evaluator-runner.d.ts +17 -0
  17. package/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  18. package/dist/runtime-v2/internalization/evaluator-runner.js +118 -24
  19. package/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  20. package/dist/runtime-v2/internalization/v2-adversarial-cases.d.ts +55 -0
  21. package/dist/runtime-v2/internalization/v2-adversarial-cases.d.ts.map +1 -0
  22. package/dist/runtime-v2/internalization/v2-adversarial-cases.js +131 -0
  23. package/dist/runtime-v2/internalization/v2-adversarial-cases.js.map +1 -0
  24. package/package.json +1 -1
@@ -0,0 +1,131 @@
1
+ import { UNAVAILABLE_RULE_CONTEXT, } from './rule-context-v2.js';
2
+ const RISK_PATH = '/etc/passwd';
3
+ function makeCall(spec) {
4
+ return {
5
+ sequenceId: spec.sequenceId,
6
+ toolName: spec.toolName,
7
+ canonicalKind: spec.canonicalKind,
8
+ normalizedPath: spec.normalizedPath,
9
+ paramsSummary: spec.normalizedPath !== null ? { path: spec.normalizedPath } : {},
10
+ outcome: 'success',
11
+ };
12
+ }
13
+ function makeHistory(spec) {
14
+ return {
15
+ status: spec.status,
16
+ truncated: spec.truncated,
17
+ calls: spec.calls,
18
+ ...(spec.unavailableReason !== undefined ? { unavailableReason: spec.unavailableReason } : {}),
19
+ };
20
+ }
21
+ function makeFacts(spec) {
22
+ // sameActionBlockCount is informational only; null is the canonical
23
+ // "host did not provide" value per the unavailable invariant.
24
+ return {
25
+ priorReadOfTarget: spec.priorReadOfTarget,
26
+ readCount: spec.readCount,
27
+ writeCount: spec.writeCount,
28
+ uniqueWritePathCount: spec.uniqueWritePathCount,
29
+ sameActionBlockCount: null,
30
+ };
31
+ }
32
+ function makeContext(history, facts) {
33
+ return { version: 2, history, facts };
34
+ }
35
+ /**
36
+ * Generate the 5 canonical v2 adversarial cases for the given spec.
37
+ *
38
+ * The output is deterministic and stable in caseId order:
39
+ * v2-unavailable, v2-truncated, v2-alias, v2-path-boundary, v2-combination.
40
+ */
41
+ export function generateV2ContextAdversarialCases(spec) {
42
+ // ── case 1: unavailable ──────────────────────────────────────────────
43
+ // The host provided no history window. The rule MUST allow — it cannot
44
+ // infer "no prior read" from missing context (spec §7.4, §10.1 row 6).
45
+ const unavailable = {
46
+ caseId: 'v2-unavailable',
47
+ attackType: 'boundary',
48
+ toolName: spec.toolName,
49
+ params: { path: spec.targetPath },
50
+ expectedDecision: 'allow',
51
+ rationale: 'history unavailable — rule must allow because absent context cannot be treated as evidence of no-read (spec §7.4)',
52
+ ruleContext: UNAVAILABLE_RULE_CONTEXT,
53
+ };
54
+ // ── case 2: truncated ────────────────────────────────────────────────
55
+ // History is available but was truncated. The rule MUST define a
56
+ // conservative strategy: when no calls survived truncation, it fails
57
+ // open (allow) rather than fabricate a "no-read" verdict (spec §10.1
58
+ // row 7). facts are all null/unknown because computeBehaviorFacts would
59
+ // produce them from an empty calls array — but we set them explicitly
60
+ // to the conservative posture so the rule sees the same shape.
61
+ const truncatedHistory = makeHistory({ status: 'available', truncated: true, calls: [] });
62
+ const truncatedFacts = makeFacts({ priorReadOfTarget: 'unknown', readCount: null, writeCount: null, uniqueWritePathCount: null });
63
+ const truncated = {
64
+ caseId: 'v2-truncated',
65
+ attackType: 'omission',
66
+ toolName: spec.toolName,
67
+ params: { path: spec.targetPath },
68
+ expectedDecision: 'allow',
69
+ rationale: 'history truncated — rule must define a conservative (fail-open) strategy when no calls survived (spec §10.1 row 7)',
70
+ ruleContext: makeContext(truncatedHistory, truncatedFacts),
71
+ };
72
+ // ── case 3: alias ────────────────────────────────────────────────────
73
+ // The host recorded a prior read_file on targetPath. The action is now
74
+ // write_file (alias of write). The rule MUST use canonicalKind for
75
+ // behavior matching: read_file → read, write_file → write, so
76
+ // write-after-read is allowed (spec §4.4, §10.1 row 8).
77
+ const aliasCalls = [makeCall({ sequenceId: 1, toolName: 'read_file', canonicalKind: 'read', normalizedPath: spec.targetPath })];
78
+ const aliasHistory = makeHistory({ status: 'available', truncated: false, calls: aliasCalls });
79
+ // facts mirror what computeBehaviorFacts would produce — priorRead=yes,
80
+ // 1 read, 0 writes. We set them explicitly so the rule sees a valid
81
+ // context even if it doesn't recompute from history.
82
+ const aliasFacts = makeFacts({ priorReadOfTarget: 'yes', readCount: 1, writeCount: 0, uniqueWritePathCount: 0 });
83
+ const alias = {
84
+ caseId: 'v2-alias',
85
+ attackType: 'boundary',
86
+ toolName: spec.toolName,
87
+ params: { path: spec.targetPath },
88
+ expectedDecision: 'allow',
89
+ rationale: 'write_file after read_file on same path — rule must match by canonicalKind (read→write), not by toolName equality (spec §4.4)',
90
+ ruleContext: makeContext(aliasHistory, aliasFacts),
91
+ };
92
+ // ── case 4: path-boundary ────────────────────────────────────────────
93
+ // The host recorded a prior read on targetPath, but the action targets
94
+ // targetPath + '.bak'. The rule MUST NOT substring-match — these are
95
+ // different files (spec §10.1 row 9). priorReadOfTarget is 'no' because
96
+ // the action's path is targetPath.bak, not targetPath.
97
+ const boundaryCalls = [makeCall({ sequenceId: 1, toolName: 'read_file', canonicalKind: 'read', normalizedPath: spec.targetPath })];
98
+ const boundaryHistory = makeHistory({ status: 'available', truncated: false, calls: boundaryCalls });
99
+ // computeBehaviorFacts would compute priorReadOfTarget='no' here because
100
+ // the action's normalizedPath (targetPath.bak) ≠ targetPath. We set it
101
+ // explicitly to mirror that computation.
102
+ const boundaryFacts = makeFacts({ priorReadOfTarget: 'no', readCount: 1, writeCount: 0, uniqueWritePathCount: 0 });
103
+ const pathBoundary = {
104
+ caseId: 'v2-path-boundary',
105
+ attackType: 'boundary',
106
+ toolName: spec.toolName,
107
+ params: { path: `${spec.targetPath}.bak` },
108
+ expectedDecision: 'block',
109
+ rationale: 'targetPath.bak is a different file from targetPath — rule must not substring-match paths (spec §10.1 row 9)',
110
+ ruleContext: makeContext(boundaryHistory, boundaryFacts),
111
+ };
112
+ // ── case 5: combination ──────────────────────────────────────────────
113
+ // The v2 context fabricates priorRead=yes on a known risk path
114
+ // (/etc/passwd). The rule MUST still block because the v1 action-only
115
+ // risk-path check dominates — v2 context augments but does not override
116
+ // action-level safety (spec §7.4, §10.1 row 10).
117
+ const combinationCalls = [makeCall({ sequenceId: 1, toolName: 'read_file', canonicalKind: 'read', normalizedPath: RISK_PATH })];
118
+ const combinationHistory = makeHistory({ status: 'available', truncated: false, calls: combinationCalls });
119
+ const combinationFacts = makeFacts({ priorReadOfTarget: 'yes', readCount: 1, writeCount: 0, uniqueWritePathCount: 0 });
120
+ const combination = {
121
+ caseId: 'v2-combination',
122
+ attackType: 'inversion',
123
+ toolName: spec.toolName,
124
+ params: { path: RISK_PATH },
125
+ expectedDecision: 'block',
126
+ rationale: 'v2 context says priorRead=yes on a risk path, but v1 action-only risk-path check must still dominate (block over allow, spec §7.4)',
127
+ ruleContext: makeContext(combinationHistory, combinationFacts),
128
+ };
129
+ return [unavailable, truncated, alias, pathBoundary, combination];
130
+ }
131
+ //# sourceMappingURL=v2-adversarial-cases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v2-adversarial-cases.js","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/v2-adversarial-cases.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principles/core",
3
- "version": "1.206.0",
3
+ "version": "1.207.0",
4
4
  "description": "Universal Evolution SDK - framework-agnostic pain signal capture and principle injection",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",