@armoriq/policy-ir 0.1.2 → 0.1.4
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/README.md +1 -0
- package/dist/document-entry-CDOQVeis.d.cts +229 -0
- package/dist/document-entry-CDOQVeis.d.ts +229 -0
- package/dist/document.cjs +722 -0
- package/dist/document.cjs.map +1 -0
- package/dist/document.d.cts +1 -0
- package/dist/document.d.ts +1 -0
- package/dist/document.js +688 -0
- package/dist/document.js.map +1 -0
- package/dist/index.cjs +136 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -228
- package/dist/index.d.ts +3 -228
- package/dist/index.js +136 -15
- package/dist/index.js.map +1 -1
- package/dist/vectors.cjs +44 -1
- package/dist/vectors.cjs.map +1 -1
- package/dist/vectors.js +44 -1
- package/dist/vectors.js.map +1 -1
- package/package.json +33 -11
- package/vectors/compile.json +1 -0
- package/vectors/document.json +6 -0
- package/vectors/evaluate.json +37 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,105 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Data, never a program: the same JSON is evaluated by conmap, the Armor CLI
|
|
5
|
-
* daemon, the SDK pre-check and OPA. The document is the hashing and signing
|
|
6
|
-
* boundary, so every field here is part of `policyHash` except `policyHash`.
|
|
7
|
-
*/
|
|
8
|
-
declare const SCHEMA_VERSION: "armor.policy.v2";
|
|
9
|
-
type Verdict = 'allow' | 'hold' | 'block';
|
|
10
|
-
/** Where a document sits in the layering ladder. A boundary is a floor: it can only tighten. */
|
|
11
|
-
type Layer = 'floor' | 'group' | 'agent' | 'member' | 'local';
|
|
12
|
-
type PolicyTarget = {
|
|
13
|
-
org: '*';
|
|
14
|
-
} | {
|
|
15
|
-
group: string;
|
|
16
|
-
} | {
|
|
17
|
-
agent: string;
|
|
18
|
-
mcpServers?: string[];
|
|
19
|
-
} | {
|
|
20
|
-
device: 'local';
|
|
21
|
-
products?: string[];
|
|
22
|
-
};
|
|
23
|
-
interface Defaults {
|
|
24
|
-
tools: Verdict;
|
|
25
|
-
network: Verdict;
|
|
26
|
-
files: Verdict;
|
|
27
|
-
skills: Verdict;
|
|
28
|
-
}
|
|
29
|
-
interface Capture {
|
|
30
|
-
arguments: boolean;
|
|
31
|
-
redact: string[];
|
|
32
|
-
maxBytesPerCall: number;
|
|
33
|
-
sample: number;
|
|
34
|
-
}
|
|
35
|
-
type KeyTier = 'exact' | 'glob';
|
|
36
|
-
type StatementMatch = {
|
|
37
|
-
tool: string;
|
|
38
|
-
keyTier: KeyTier;
|
|
39
|
-
order: number;
|
|
40
|
-
} | {
|
|
41
|
-
capability: string;
|
|
42
|
-
};
|
|
43
|
-
type ConditionOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'glob' | 'regex' | 'notRegex' | 'startsWith' | 'exists';
|
|
44
|
-
interface SchemaBinding {
|
|
45
|
-
/** `sha256:` of the tool's canonical input schema at compile time; null when the inventory had none. */
|
|
46
|
-
schemaHash: string | null;
|
|
47
|
-
}
|
|
48
|
-
interface Condition {
|
|
49
|
-
/** Dotpath into the call: `args.amount`, `args.command.program`, `path`. */
|
|
50
|
-
field: string;
|
|
51
|
-
op: ConditionOp;
|
|
52
|
-
value?: unknown;
|
|
53
|
-
schemaBinding?: SchemaBinding;
|
|
54
|
-
}
|
|
55
|
-
interface Approval {
|
|
56
|
-
approvers: number;
|
|
57
|
-
roles?: string[];
|
|
58
|
-
members?: string[];
|
|
59
|
-
anyMember?: boolean;
|
|
60
|
-
}
|
|
61
|
-
/** Who a statement applies to. Absent means everyone the document targets. */
|
|
62
|
-
type Subject = {
|
|
63
|
-
membershipId: string;
|
|
64
|
-
} | {
|
|
65
|
-
email: string;
|
|
66
|
-
} | {
|
|
67
|
-
group: string;
|
|
68
|
-
} | {
|
|
69
|
-
product: string;
|
|
70
|
-
};
|
|
71
|
-
interface Provenance {
|
|
72
|
-
ruleKey: string;
|
|
73
|
-
variant: number;
|
|
74
|
-
source: 'yaml' | 'converter' | 'compose' | 'settings-import';
|
|
75
|
-
layer: Layer;
|
|
76
|
-
}
|
|
77
|
-
interface Statement {
|
|
78
|
-
id: string;
|
|
79
|
-
subject: Subject | null;
|
|
80
|
-
match: StatementMatch;
|
|
81
|
-
effect: Verdict;
|
|
82
|
-
conditions: Condition[];
|
|
83
|
-
approval?: Approval;
|
|
84
|
-
/** ISO date-time, or the literal `never`. Always present. */
|
|
85
|
-
expiresAt: string | 'never';
|
|
86
|
-
controls?: string[];
|
|
87
|
-
provenance: Provenance;
|
|
88
|
-
}
|
|
89
|
-
interface PolicyDocument {
|
|
90
|
-
schemaVersion: typeof SCHEMA_VERSION;
|
|
91
|
-
policyId: string;
|
|
92
|
-
/** `sha256:` over the canonical document without this field. */
|
|
93
|
-
policyHash?: string;
|
|
94
|
-
target: PolicyTarget;
|
|
95
|
-
layer: Layer;
|
|
96
|
-
defaults: Defaults;
|
|
97
|
-
capture: Capture;
|
|
98
|
-
/** ISO date-time, or the literal `never`. Always present. */
|
|
99
|
-
expiresAt: string | 'never';
|
|
100
|
-
statements: Statement[];
|
|
101
|
-
}
|
|
102
|
-
declare function layerOfTarget(target: PolicyTarget): Layer;
|
|
1
|
+
import { P as PolicyDocument, V as Verdict, A as Approval, L as Layer, C as Condition, S as Statement, a as SourceTarget, b as PolicySource, D as Diagnostics } from './document-entry-CDOQVeis.cjs';
|
|
2
|
+
export { c as Capture, d as ConditionOp, e as ConditionSpec, f as Defaults, g as Diagnostic, K as KeyTier, N as NEVER, h as NetworkEntry, O as Overlay, i as ParseResult, j as PolicySpec, k as PolicyTarget, l as Provenance, R as RuleValue, m as RuleVariant, n as SCHEMA_VERSION, o as SOURCE_OPERATORS, p as SchemaBinding, q as Severity, r as SourceOperator, s as StatementMatch, t as Subject, T as ToolsSection, u as VERDICTS, v as layerOfTarget, w as parseDocument, x as parseYaml, y as serialize, z as validate } from './document-entry-CDOQVeis.cjs';
|
|
103
3
|
|
|
104
4
|
/**
|
|
105
5
|
* Canonical JSON: sorted keys, no whitespace, ASCII escapes for anything
|
|
@@ -228,123 +128,6 @@ declare function conditionHolds(input: CallInput, condition: Condition): boolean
|
|
|
228
128
|
*/
|
|
229
129
|
declare function selectRuleKey(statements: Statement[], tool: string): string | null;
|
|
230
130
|
|
|
231
|
-
type Severity = 'error' | 'warning';
|
|
232
|
-
interface Diagnostic {
|
|
233
|
-
code: string;
|
|
234
|
-
severity: Severity;
|
|
235
|
-
/** JSON-pointer-like path into the source document, `/spec/tools/rules/Bash/0`. */
|
|
236
|
-
path: string;
|
|
237
|
-
message: string;
|
|
238
|
-
}
|
|
239
|
-
declare class Diagnostics {
|
|
240
|
-
readonly items: Diagnostic[];
|
|
241
|
-
error(code: string, path: string, message: string): void;
|
|
242
|
-
warning(code: string, path: string, message: string): void;
|
|
243
|
-
get hasErrors(): boolean;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/** The `armor.io/v2` source document after strict parsing, before lowering. */
|
|
247
|
-
interface PolicySource {
|
|
248
|
-
apiVersion: 'armor.io/v2';
|
|
249
|
-
kind: 'Policy';
|
|
250
|
-
metadata: {
|
|
251
|
-
name: string;
|
|
252
|
-
description?: string;
|
|
253
|
-
orgId?: string;
|
|
254
|
-
labels?: Record<string, string>;
|
|
255
|
-
};
|
|
256
|
-
target: SourceTarget;
|
|
257
|
-
precedence?: 'device-first' | 'agent-first';
|
|
258
|
-
spec: PolicySpec;
|
|
259
|
-
}
|
|
260
|
-
type SourceTarget = {
|
|
261
|
-
agent: string;
|
|
262
|
-
mcpServers?: string[];
|
|
263
|
-
} | {
|
|
264
|
-
group: string;
|
|
265
|
-
} | {
|
|
266
|
-
org: '*';
|
|
267
|
-
} | {
|
|
268
|
-
device: 'local';
|
|
269
|
-
};
|
|
270
|
-
interface PolicySpec {
|
|
271
|
-
tools: ToolsSection;
|
|
272
|
-
files?: {
|
|
273
|
-
deny?: string[];
|
|
274
|
-
allowOutsideWorkspace?: boolean;
|
|
275
|
-
};
|
|
276
|
-
network?: {
|
|
277
|
-
default?: Verdict;
|
|
278
|
-
allow?: NetworkEntry[];
|
|
279
|
-
deny?: NetworkEntry[];
|
|
280
|
-
};
|
|
281
|
-
skills?: {
|
|
282
|
-
default?: Verdict;
|
|
283
|
-
hold?: string[];
|
|
284
|
-
block?: string[];
|
|
285
|
-
};
|
|
286
|
-
secrets?: {
|
|
287
|
-
envBlocklist?: string[];
|
|
288
|
-
};
|
|
289
|
-
members?: Record<string, Overlay>;
|
|
290
|
-
products?: Record<string, Overlay>;
|
|
291
|
-
capture?: {
|
|
292
|
-
arguments?: boolean;
|
|
293
|
-
redact?: string[];
|
|
294
|
-
maxBytesPerCall?: number;
|
|
295
|
-
sample?: number;
|
|
296
|
-
};
|
|
297
|
-
approvalDefaults?: Approval;
|
|
298
|
-
expiresAt: string;
|
|
299
|
-
}
|
|
300
|
-
type NetworkEntry = string | {
|
|
301
|
-
host: string;
|
|
302
|
-
reason?: string;
|
|
303
|
-
};
|
|
304
|
-
interface ToolsSection {
|
|
305
|
-
default: Verdict;
|
|
306
|
-
rules?: Record<string, RuleValue>;
|
|
307
|
-
}
|
|
308
|
-
interface Overlay {
|
|
309
|
-
tools?: {
|
|
310
|
-
default?: Verdict;
|
|
311
|
-
rules?: Record<string, RuleValue>;
|
|
312
|
-
};
|
|
313
|
-
expiresAt: string;
|
|
314
|
-
}
|
|
315
|
-
/** A scalar verdict is shorthand for one unconditional variant. */
|
|
316
|
-
type RuleValue = Verdict | RuleVariant[];
|
|
317
|
-
interface RuleVariant {
|
|
318
|
-
action: Verdict;
|
|
319
|
-
when?: Record<string, ConditionSpec>;
|
|
320
|
-
approval?: Approval;
|
|
321
|
-
reason?: string;
|
|
322
|
-
controls?: string[];
|
|
323
|
-
expiresAt: string;
|
|
324
|
-
}
|
|
325
|
-
/** `{gt: 5000}`, `{in: [a, b]}`, `{matches: '^x'}`, `{exists: true}`. Exactly one operator. */
|
|
326
|
-
type ConditionSpec = Partial<Record<SourceOperator, unknown>>;
|
|
327
|
-
declare const SOURCE_OPERATORS: readonly ["eq", "neq", "in", "notIn", "gt", "gte", "lt", "lte", "matches", "notMatches", "startsWith", "glob", "withinWorkspace", "exists"];
|
|
328
|
-
type SourceOperator = (typeof SOURCE_OPERATORS)[number];
|
|
329
|
-
declare const VERDICTS: readonly Verdict[];
|
|
330
|
-
declare const NEVER = "never";
|
|
331
|
-
|
|
332
|
-
interface ParseResult {
|
|
333
|
-
source: PolicySource | null;
|
|
334
|
-
diagnostics: Diagnostics;
|
|
335
|
-
}
|
|
336
|
-
/** Parse `armor.io/v2` YAML text strictly. */
|
|
337
|
-
declare function parseYaml(text: string): ParseResult;
|
|
338
|
-
/** Parse an already-loaded YAML/JSON value strictly. */
|
|
339
|
-
declare function parseDocument(value: unknown): ParseResult;
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Everything that can be checked without an inventory. Inventory-dependent
|
|
343
|
-
* checks (roster clamp, glob collisions on real tools, schema binding) live in
|
|
344
|
-
* the compiler.
|
|
345
|
-
*/
|
|
346
|
-
declare function validate(source: PolicySource): Diagnostics;
|
|
347
|
-
|
|
348
131
|
/** One tool the target can reach, as the inventory knows it. */
|
|
349
132
|
interface InventoryTool {
|
|
350
133
|
/** The wire name the model sees; for an MCP tool the host may also supply the qualified `mcp__<server>__<tool>` form as `qualifiedName`. */
|
|
@@ -394,14 +177,6 @@ interface CompileResult {
|
|
|
394
177
|
declare function compile(source: PolicySource, inventory: InventoryTool[], options: CompileOptions): CompileResult;
|
|
395
178
|
declare function compileWithPort(source: PolicySource, port: InventoryPort, options: CompileOptions): Promise<CompileResult>;
|
|
396
179
|
|
|
397
|
-
/**
|
|
398
|
-
* PolicySource back to YAML such that `parse(serialize(x))` equals `x`
|
|
399
|
-
* (VC-10). A single unconditional variant with no other fields is written as
|
|
400
|
-
* the scalar shorthand; `expiresAt: never` is written only where the parser
|
|
401
|
-
* would not materialize it identically anyway (everywhere), so it is kept.
|
|
402
|
-
*/
|
|
403
|
-
declare function serialize(source: PolicySource): string;
|
|
404
|
-
|
|
405
180
|
type KeyKind = 'exact' | 'glob' | 'capability';
|
|
406
181
|
interface ResolvedKey {
|
|
407
182
|
kind: KeyKind;
|
|
@@ -423,4 +198,4 @@ declare function checkArgumentKeys(fields: string[], tool: InventoryTool, diag:
|
|
|
423
198
|
|
|
424
199
|
declare const KNOWN_CONTROLS: ReadonlySet<string>;
|
|
425
200
|
|
|
426
|
-
export {
|
|
201
|
+
export { Approval, type BoundDocuments, CAPABILITY_KEYS, type CallInput, type CompileOptions, type CompileResult, Condition, Diagnostics, type Enforceability, type EnforceabilityReport, type Evaluation, HASH_PREFIX, type InventoryPort, type InventoryTool, KNOWN_CONTROLS, Layer, type Obligation, PolicyDocument, PolicySource, type Principal, type SchemaDriftObligation, type Section, SourceTarget, Statement, VERDICT_RANK, Verdict, type VerdictProvenance, canonicalJson, checkArgumentKeys, checkGlobCollisions, compile, compileWithPort, conditionHolds, conditionsHold, enforceabilityReport, evaluate, globToRegExp, isGlob, matchGlob, policyHash, resolveField, resolveKey, schemaHash, selectRuleKey, sha256Canonical, stricter, verifyPolicyHash };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,105 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Data, never a program: the same JSON is evaluated by conmap, the Armor CLI
|
|
5
|
-
* daemon, the SDK pre-check and OPA. The document is the hashing and signing
|
|
6
|
-
* boundary, so every field here is part of `policyHash` except `policyHash`.
|
|
7
|
-
*/
|
|
8
|
-
declare const SCHEMA_VERSION: "armor.policy.v2";
|
|
9
|
-
type Verdict = 'allow' | 'hold' | 'block';
|
|
10
|
-
/** Where a document sits in the layering ladder. A boundary is a floor: it can only tighten. */
|
|
11
|
-
type Layer = 'floor' | 'group' | 'agent' | 'member' | 'local';
|
|
12
|
-
type PolicyTarget = {
|
|
13
|
-
org: '*';
|
|
14
|
-
} | {
|
|
15
|
-
group: string;
|
|
16
|
-
} | {
|
|
17
|
-
agent: string;
|
|
18
|
-
mcpServers?: string[];
|
|
19
|
-
} | {
|
|
20
|
-
device: 'local';
|
|
21
|
-
products?: string[];
|
|
22
|
-
};
|
|
23
|
-
interface Defaults {
|
|
24
|
-
tools: Verdict;
|
|
25
|
-
network: Verdict;
|
|
26
|
-
files: Verdict;
|
|
27
|
-
skills: Verdict;
|
|
28
|
-
}
|
|
29
|
-
interface Capture {
|
|
30
|
-
arguments: boolean;
|
|
31
|
-
redact: string[];
|
|
32
|
-
maxBytesPerCall: number;
|
|
33
|
-
sample: number;
|
|
34
|
-
}
|
|
35
|
-
type KeyTier = 'exact' | 'glob';
|
|
36
|
-
type StatementMatch = {
|
|
37
|
-
tool: string;
|
|
38
|
-
keyTier: KeyTier;
|
|
39
|
-
order: number;
|
|
40
|
-
} | {
|
|
41
|
-
capability: string;
|
|
42
|
-
};
|
|
43
|
-
type ConditionOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'glob' | 'regex' | 'notRegex' | 'startsWith' | 'exists';
|
|
44
|
-
interface SchemaBinding {
|
|
45
|
-
/** `sha256:` of the tool's canonical input schema at compile time; null when the inventory had none. */
|
|
46
|
-
schemaHash: string | null;
|
|
47
|
-
}
|
|
48
|
-
interface Condition {
|
|
49
|
-
/** Dotpath into the call: `args.amount`, `args.command.program`, `path`. */
|
|
50
|
-
field: string;
|
|
51
|
-
op: ConditionOp;
|
|
52
|
-
value?: unknown;
|
|
53
|
-
schemaBinding?: SchemaBinding;
|
|
54
|
-
}
|
|
55
|
-
interface Approval {
|
|
56
|
-
approvers: number;
|
|
57
|
-
roles?: string[];
|
|
58
|
-
members?: string[];
|
|
59
|
-
anyMember?: boolean;
|
|
60
|
-
}
|
|
61
|
-
/** Who a statement applies to. Absent means everyone the document targets. */
|
|
62
|
-
type Subject = {
|
|
63
|
-
membershipId: string;
|
|
64
|
-
} | {
|
|
65
|
-
email: string;
|
|
66
|
-
} | {
|
|
67
|
-
group: string;
|
|
68
|
-
} | {
|
|
69
|
-
product: string;
|
|
70
|
-
};
|
|
71
|
-
interface Provenance {
|
|
72
|
-
ruleKey: string;
|
|
73
|
-
variant: number;
|
|
74
|
-
source: 'yaml' | 'converter' | 'compose' | 'settings-import';
|
|
75
|
-
layer: Layer;
|
|
76
|
-
}
|
|
77
|
-
interface Statement {
|
|
78
|
-
id: string;
|
|
79
|
-
subject: Subject | null;
|
|
80
|
-
match: StatementMatch;
|
|
81
|
-
effect: Verdict;
|
|
82
|
-
conditions: Condition[];
|
|
83
|
-
approval?: Approval;
|
|
84
|
-
/** ISO date-time, or the literal `never`. Always present. */
|
|
85
|
-
expiresAt: string | 'never';
|
|
86
|
-
controls?: string[];
|
|
87
|
-
provenance: Provenance;
|
|
88
|
-
}
|
|
89
|
-
interface PolicyDocument {
|
|
90
|
-
schemaVersion: typeof SCHEMA_VERSION;
|
|
91
|
-
policyId: string;
|
|
92
|
-
/** `sha256:` over the canonical document without this field. */
|
|
93
|
-
policyHash?: string;
|
|
94
|
-
target: PolicyTarget;
|
|
95
|
-
layer: Layer;
|
|
96
|
-
defaults: Defaults;
|
|
97
|
-
capture: Capture;
|
|
98
|
-
/** ISO date-time, or the literal `never`. Always present. */
|
|
99
|
-
expiresAt: string | 'never';
|
|
100
|
-
statements: Statement[];
|
|
101
|
-
}
|
|
102
|
-
declare function layerOfTarget(target: PolicyTarget): Layer;
|
|
1
|
+
import { P as PolicyDocument, V as Verdict, A as Approval, L as Layer, C as Condition, S as Statement, a as SourceTarget, b as PolicySource, D as Diagnostics } from './document-entry-CDOQVeis.js';
|
|
2
|
+
export { c as Capture, d as ConditionOp, e as ConditionSpec, f as Defaults, g as Diagnostic, K as KeyTier, N as NEVER, h as NetworkEntry, O as Overlay, i as ParseResult, j as PolicySpec, k as PolicyTarget, l as Provenance, R as RuleValue, m as RuleVariant, n as SCHEMA_VERSION, o as SOURCE_OPERATORS, p as SchemaBinding, q as Severity, r as SourceOperator, s as StatementMatch, t as Subject, T as ToolsSection, u as VERDICTS, v as layerOfTarget, w as parseDocument, x as parseYaml, y as serialize, z as validate } from './document-entry-CDOQVeis.js';
|
|
103
3
|
|
|
104
4
|
/**
|
|
105
5
|
* Canonical JSON: sorted keys, no whitespace, ASCII escapes for anything
|
|
@@ -228,123 +128,6 @@ declare function conditionHolds(input: CallInput, condition: Condition): boolean
|
|
|
228
128
|
*/
|
|
229
129
|
declare function selectRuleKey(statements: Statement[], tool: string): string | null;
|
|
230
130
|
|
|
231
|
-
type Severity = 'error' | 'warning';
|
|
232
|
-
interface Diagnostic {
|
|
233
|
-
code: string;
|
|
234
|
-
severity: Severity;
|
|
235
|
-
/** JSON-pointer-like path into the source document, `/spec/tools/rules/Bash/0`. */
|
|
236
|
-
path: string;
|
|
237
|
-
message: string;
|
|
238
|
-
}
|
|
239
|
-
declare class Diagnostics {
|
|
240
|
-
readonly items: Diagnostic[];
|
|
241
|
-
error(code: string, path: string, message: string): void;
|
|
242
|
-
warning(code: string, path: string, message: string): void;
|
|
243
|
-
get hasErrors(): boolean;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/** The `armor.io/v2` source document after strict parsing, before lowering. */
|
|
247
|
-
interface PolicySource {
|
|
248
|
-
apiVersion: 'armor.io/v2';
|
|
249
|
-
kind: 'Policy';
|
|
250
|
-
metadata: {
|
|
251
|
-
name: string;
|
|
252
|
-
description?: string;
|
|
253
|
-
orgId?: string;
|
|
254
|
-
labels?: Record<string, string>;
|
|
255
|
-
};
|
|
256
|
-
target: SourceTarget;
|
|
257
|
-
precedence?: 'device-first' | 'agent-first';
|
|
258
|
-
spec: PolicySpec;
|
|
259
|
-
}
|
|
260
|
-
type SourceTarget = {
|
|
261
|
-
agent: string;
|
|
262
|
-
mcpServers?: string[];
|
|
263
|
-
} | {
|
|
264
|
-
group: string;
|
|
265
|
-
} | {
|
|
266
|
-
org: '*';
|
|
267
|
-
} | {
|
|
268
|
-
device: 'local';
|
|
269
|
-
};
|
|
270
|
-
interface PolicySpec {
|
|
271
|
-
tools: ToolsSection;
|
|
272
|
-
files?: {
|
|
273
|
-
deny?: string[];
|
|
274
|
-
allowOutsideWorkspace?: boolean;
|
|
275
|
-
};
|
|
276
|
-
network?: {
|
|
277
|
-
default?: Verdict;
|
|
278
|
-
allow?: NetworkEntry[];
|
|
279
|
-
deny?: NetworkEntry[];
|
|
280
|
-
};
|
|
281
|
-
skills?: {
|
|
282
|
-
default?: Verdict;
|
|
283
|
-
hold?: string[];
|
|
284
|
-
block?: string[];
|
|
285
|
-
};
|
|
286
|
-
secrets?: {
|
|
287
|
-
envBlocklist?: string[];
|
|
288
|
-
};
|
|
289
|
-
members?: Record<string, Overlay>;
|
|
290
|
-
products?: Record<string, Overlay>;
|
|
291
|
-
capture?: {
|
|
292
|
-
arguments?: boolean;
|
|
293
|
-
redact?: string[];
|
|
294
|
-
maxBytesPerCall?: number;
|
|
295
|
-
sample?: number;
|
|
296
|
-
};
|
|
297
|
-
approvalDefaults?: Approval;
|
|
298
|
-
expiresAt: string;
|
|
299
|
-
}
|
|
300
|
-
type NetworkEntry = string | {
|
|
301
|
-
host: string;
|
|
302
|
-
reason?: string;
|
|
303
|
-
};
|
|
304
|
-
interface ToolsSection {
|
|
305
|
-
default: Verdict;
|
|
306
|
-
rules?: Record<string, RuleValue>;
|
|
307
|
-
}
|
|
308
|
-
interface Overlay {
|
|
309
|
-
tools?: {
|
|
310
|
-
default?: Verdict;
|
|
311
|
-
rules?: Record<string, RuleValue>;
|
|
312
|
-
};
|
|
313
|
-
expiresAt: string;
|
|
314
|
-
}
|
|
315
|
-
/** A scalar verdict is shorthand for one unconditional variant. */
|
|
316
|
-
type RuleValue = Verdict | RuleVariant[];
|
|
317
|
-
interface RuleVariant {
|
|
318
|
-
action: Verdict;
|
|
319
|
-
when?: Record<string, ConditionSpec>;
|
|
320
|
-
approval?: Approval;
|
|
321
|
-
reason?: string;
|
|
322
|
-
controls?: string[];
|
|
323
|
-
expiresAt: string;
|
|
324
|
-
}
|
|
325
|
-
/** `{gt: 5000}`, `{in: [a, b]}`, `{matches: '^x'}`, `{exists: true}`. Exactly one operator. */
|
|
326
|
-
type ConditionSpec = Partial<Record<SourceOperator, unknown>>;
|
|
327
|
-
declare const SOURCE_OPERATORS: readonly ["eq", "neq", "in", "notIn", "gt", "gte", "lt", "lte", "matches", "notMatches", "startsWith", "glob", "withinWorkspace", "exists"];
|
|
328
|
-
type SourceOperator = (typeof SOURCE_OPERATORS)[number];
|
|
329
|
-
declare const VERDICTS: readonly Verdict[];
|
|
330
|
-
declare const NEVER = "never";
|
|
331
|
-
|
|
332
|
-
interface ParseResult {
|
|
333
|
-
source: PolicySource | null;
|
|
334
|
-
diagnostics: Diagnostics;
|
|
335
|
-
}
|
|
336
|
-
/** Parse `armor.io/v2` YAML text strictly. */
|
|
337
|
-
declare function parseYaml(text: string): ParseResult;
|
|
338
|
-
/** Parse an already-loaded YAML/JSON value strictly. */
|
|
339
|
-
declare function parseDocument(value: unknown): ParseResult;
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Everything that can be checked without an inventory. Inventory-dependent
|
|
343
|
-
* checks (roster clamp, glob collisions on real tools, schema binding) live in
|
|
344
|
-
* the compiler.
|
|
345
|
-
*/
|
|
346
|
-
declare function validate(source: PolicySource): Diagnostics;
|
|
347
|
-
|
|
348
131
|
/** One tool the target can reach, as the inventory knows it. */
|
|
349
132
|
interface InventoryTool {
|
|
350
133
|
/** The wire name the model sees; for an MCP tool the host may also supply the qualified `mcp__<server>__<tool>` form as `qualifiedName`. */
|
|
@@ -394,14 +177,6 @@ interface CompileResult {
|
|
|
394
177
|
declare function compile(source: PolicySource, inventory: InventoryTool[], options: CompileOptions): CompileResult;
|
|
395
178
|
declare function compileWithPort(source: PolicySource, port: InventoryPort, options: CompileOptions): Promise<CompileResult>;
|
|
396
179
|
|
|
397
|
-
/**
|
|
398
|
-
* PolicySource back to YAML such that `parse(serialize(x))` equals `x`
|
|
399
|
-
* (VC-10). A single unconditional variant with no other fields is written as
|
|
400
|
-
* the scalar shorthand; `expiresAt: never` is written only where the parser
|
|
401
|
-
* would not materialize it identically anyway (everywhere), so it is kept.
|
|
402
|
-
*/
|
|
403
|
-
declare function serialize(source: PolicySource): string;
|
|
404
|
-
|
|
405
180
|
type KeyKind = 'exact' | 'glob' | 'capability';
|
|
406
181
|
interface ResolvedKey {
|
|
407
182
|
kind: KeyKind;
|
|
@@ -423,4 +198,4 @@ declare function checkArgumentKeys(fields: string[], tool: InventoryTool, diag:
|
|
|
423
198
|
|
|
424
199
|
declare const KNOWN_CONTROLS: ReadonlySet<string>;
|
|
425
200
|
|
|
426
|
-
export {
|
|
201
|
+
export { Approval, type BoundDocuments, CAPABILITY_KEYS, type CallInput, type CompileOptions, type CompileResult, Condition, Diagnostics, type Enforceability, type EnforceabilityReport, type Evaluation, HASH_PREFIX, type InventoryPort, type InventoryTool, KNOWN_CONTROLS, Layer, type Obligation, PolicyDocument, PolicySource, type Principal, type SchemaDriftObligation, type Section, SourceTarget, Statement, VERDICT_RANK, Verdict, type VerdictProvenance, canonicalJson, checkArgumentKeys, checkGlobCollisions, compile, compileWithPort, conditionHolds, conditionsHold, enforceabilityReport, evaluate, globToRegExp, isGlob, matchGlob, policyHash, resolveField, resolveKey, schemaHash, selectRuleKey, sha256Canonical, stricter, verifyPolicyHash };
|
package/dist/index.js
CHANGED
|
@@ -173,11 +173,11 @@ function escapeRegExp(ch) {
|
|
|
173
173
|
// src/evaluate/conditions.ts
|
|
174
174
|
function resolveField(input, field) {
|
|
175
175
|
const [root, ...rest] = field.split(".");
|
|
176
|
-
const base = root === "args" ? input.arguments : input.derived
|
|
176
|
+
const base = root === "args" ? input.arguments : childOf2(input.derived, root ?? "");
|
|
177
177
|
return rest.reduce(childOf2, base);
|
|
178
178
|
}
|
|
179
179
|
function childOf2(node, key) {
|
|
180
|
-
if (node === null || typeof node !== "object") return void 0;
|
|
180
|
+
if (node === null || typeof node !== "object" || !Object.hasOwn(node, key)) return void 0;
|
|
181
181
|
return node[key];
|
|
182
182
|
}
|
|
183
183
|
function conditionsHold(input, conditions) {
|
|
@@ -769,6 +769,119 @@ function parseCapture(r, value) {
|
|
|
769
769
|
return out;
|
|
770
770
|
}
|
|
771
771
|
|
|
772
|
+
// src/document/portable-regex.ts
|
|
773
|
+
function isPortablePattern(pattern) {
|
|
774
|
+
if (typeof pattern !== "string") return false;
|
|
775
|
+
try {
|
|
776
|
+
new RegExp(pattern);
|
|
777
|
+
} catch {
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
const parser = new Parser(pattern);
|
|
781
|
+
return parser.alternatives() && parser.done();
|
|
782
|
+
}
|
|
783
|
+
var ESCAPED_PUNCTUATION = new Set("\\/.*+?()[]{}|^$-");
|
|
784
|
+
var CONTROL_ESCAPES = new Set("tnrfv");
|
|
785
|
+
var SET_ESCAPES = new Set("dwsDWS");
|
|
786
|
+
var CLASS_SET_ESCAPES = new Set("dws");
|
|
787
|
+
var BARE_SPECIALS = new Set("]{}*+?");
|
|
788
|
+
var QUANTIFIER = /^\{\d+(,\d*)?\}/;
|
|
789
|
+
var Parser = class {
|
|
790
|
+
constructor(p) {
|
|
791
|
+
this.p = p;
|
|
792
|
+
}
|
|
793
|
+
p;
|
|
794
|
+
i = 0;
|
|
795
|
+
done() {
|
|
796
|
+
return this.i === this.p.length;
|
|
797
|
+
}
|
|
798
|
+
alternatives() {
|
|
799
|
+
while (!this.done() && this.p[this.i] !== ")") {
|
|
800
|
+
if (this.p[this.i] === "|") this.i++;
|
|
801
|
+
else if (!this.term()) return false;
|
|
802
|
+
}
|
|
803
|
+
return true;
|
|
804
|
+
}
|
|
805
|
+
term() {
|
|
806
|
+
const atom = this.atom();
|
|
807
|
+
return atom !== null && this.quantifier(atom === "quantifiable");
|
|
808
|
+
}
|
|
809
|
+
atom() {
|
|
810
|
+
const c = this.p[this.i++];
|
|
811
|
+
if (c === "^" || c === "$") return "assertion";
|
|
812
|
+
if (c === "\\") return this.escape();
|
|
813
|
+
if (c === "[") return this.charClass() ? "quantifiable" : null;
|
|
814
|
+
if (c === "(") return this.group() ? "quantifiable" : null;
|
|
815
|
+
return BARE_SPECIALS.has(c) ? null : "quantifiable";
|
|
816
|
+
}
|
|
817
|
+
escape() {
|
|
818
|
+
const e = this.p[this.i++] ?? "";
|
|
819
|
+
if (e === "b" || e === "B") return "assertion";
|
|
820
|
+
if (SET_ESCAPES.has(e) || CONTROL_ESCAPES.has(e) || ESCAPED_PUNCTUATION.has(e)) return "quantifiable";
|
|
821
|
+
return this.hexEscape(e) ? "quantifiable" : null;
|
|
822
|
+
}
|
|
823
|
+
hexEscape(e) {
|
|
824
|
+
const width = e === "x" ? 2 : e === "u" ? 4 : 0;
|
|
825
|
+
const digits = this.p.slice(this.i, this.i + width);
|
|
826
|
+
if (width === 0 || !/^[0-9a-fA-F]+$/.test(digits) || digits.length !== width) return false;
|
|
827
|
+
this.i += width;
|
|
828
|
+
return true;
|
|
829
|
+
}
|
|
830
|
+
group() {
|
|
831
|
+
if (this.p[this.i] === "?") {
|
|
832
|
+
if (this.p[this.i + 1] !== ":") return false;
|
|
833
|
+
this.i += 2;
|
|
834
|
+
}
|
|
835
|
+
if (!this.alternatives() || this.p[this.i] !== ")") return false;
|
|
836
|
+
this.i++;
|
|
837
|
+
return true;
|
|
838
|
+
}
|
|
839
|
+
charClass() {
|
|
840
|
+
if (this.p[this.i] === "^") this.i++;
|
|
841
|
+
if (this.p[this.i] === "]") return false;
|
|
842
|
+
while (!this.done() && this.p[this.i] !== "]") {
|
|
843
|
+
if (!this.classItem()) return false;
|
|
844
|
+
}
|
|
845
|
+
if (this.done()) return false;
|
|
846
|
+
this.i++;
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
849
|
+
classItem() {
|
|
850
|
+
const start = this.classAtom();
|
|
851
|
+
if (start === null) return false;
|
|
852
|
+
if (this.p[this.i] !== "-" || this.p[this.i + 1] === "]") return true;
|
|
853
|
+
this.i++;
|
|
854
|
+
return start === "char" && this.classAtom() === "char";
|
|
855
|
+
}
|
|
856
|
+
classAtom() {
|
|
857
|
+
const c = this.p[this.i++];
|
|
858
|
+
if (c === "[") return null;
|
|
859
|
+
if (c !== "\\") return isSurrogate(c) ? null : "char";
|
|
860
|
+
const e = this.p[this.i++] ?? "";
|
|
861
|
+
if (CLASS_SET_ESCAPES.has(e)) return "set";
|
|
862
|
+
if (CONTROL_ESCAPES.has(e) || ESCAPED_PUNCTUATION.has(e)) return "char";
|
|
863
|
+
return this.hexEscape(e) ? "char" : null;
|
|
864
|
+
}
|
|
865
|
+
quantifier(quantifiable) {
|
|
866
|
+
const length = this.quantifierLength();
|
|
867
|
+
if (length === 0) return true;
|
|
868
|
+
if (length < 0 || !quantifiable) return false;
|
|
869
|
+
this.i += length;
|
|
870
|
+
if (this.p[this.i] === "?") this.i++;
|
|
871
|
+
return true;
|
|
872
|
+
}
|
|
873
|
+
quantifierLength() {
|
|
874
|
+
const c = this.p[this.i];
|
|
875
|
+
if (c === "*" || c === "+" || c === "?") return 1;
|
|
876
|
+
if (c !== "{") return 0;
|
|
877
|
+
return QUANTIFIER.exec(this.p.slice(this.i))?.[0].length ?? -1;
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
function isSurrogate(c) {
|
|
881
|
+
const code = c.charCodeAt(0);
|
|
882
|
+
return code >= 55296 && code <= 57343;
|
|
883
|
+
}
|
|
884
|
+
|
|
772
885
|
// src/document/validate.ts
|
|
773
886
|
function validate(source) {
|
|
774
887
|
const diag = new Diagnostics();
|
|
@@ -835,8 +948,8 @@ var OPERANDS = {
|
|
|
835
948
|
gte: [isNumber, "a number"],
|
|
836
949
|
lt: [isNumber, "a number"],
|
|
837
950
|
lte: [isNumber, "a number"],
|
|
838
|
-
matches: [
|
|
839
|
-
notMatches: [
|
|
951
|
+
matches: [isPortablePattern, "a regular expression in the portable subset"],
|
|
952
|
+
notMatches: [isPortablePattern, "a regular expression in the portable subset"],
|
|
840
953
|
startsWith: [isString, "a string"],
|
|
841
954
|
glob: [isString, "a glob"],
|
|
842
955
|
withinWorkspace: [isBoolean, "true or false"],
|
|
@@ -856,16 +969,6 @@ function isString(v) {
|
|
|
856
969
|
function isBoolean(v) {
|
|
857
970
|
return typeof v === "boolean";
|
|
858
971
|
}
|
|
859
|
-
function isRe2Pattern(v) {
|
|
860
|
-
if (typeof v !== "string") return false;
|
|
861
|
-
if (/\\[1-9]|\(\?[=!<]/.test(v)) return false;
|
|
862
|
-
try {
|
|
863
|
-
new RegExp(v);
|
|
864
|
-
return true;
|
|
865
|
-
} catch {
|
|
866
|
-
return false;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
972
|
function validateOverlays(ctx, overlays2, path) {
|
|
870
973
|
for (const [key, overlay] of Object.entries(overlays2 ?? {})) {
|
|
871
974
|
const opath = `${path}/${key}`;
|
|
@@ -1108,7 +1211,25 @@ var HIPAA = [
|
|
|
1108
1211
|
"164.312(d)",
|
|
1109
1212
|
"164.312(e)(1)"
|
|
1110
1213
|
].map((c) => `HIPAA-${c}`);
|
|
1111
|
-
var
|
|
1214
|
+
var FERPA = ["99.10", "99.20", "99.30", "99.31", "99.32", "99.33", "99.34", "99.35", "99.36", "99.37"].map((c) => `FERPA-${c}`);
|
|
1215
|
+
var ITAR = [
|
|
1216
|
+
"120.11",
|
|
1217
|
+
"120.31",
|
|
1218
|
+
"120.32",
|
|
1219
|
+
"120.33",
|
|
1220
|
+
"120.34",
|
|
1221
|
+
"120.43",
|
|
1222
|
+
"120.50",
|
|
1223
|
+
"120.51",
|
|
1224
|
+
"120.52",
|
|
1225
|
+
"120.54",
|
|
1226
|
+
"120.55",
|
|
1227
|
+
"120.56",
|
|
1228
|
+
"120.62",
|
|
1229
|
+
"120.63"
|
|
1230
|
+
].map((c) => `ITAR-${c}`);
|
|
1231
|
+
var EAR = ["734.3", "734.7", "734.8", "734.9", "734.13", "734.14", "734.15", "734.16", "734.17", "734.18", "734.19", "734.20"].map((c) => `EAR-${c}`);
|
|
1232
|
+
var KNOWN_CONTROLS = /* @__PURE__ */ new Set([...SOC2, ...HIPAA, ...FERPA, ...ITAR, ...EAR]);
|
|
1112
1233
|
|
|
1113
1234
|
// src/compile/lower-rules.ts
|
|
1114
1235
|
function lowerRules(rules, ctx, path, subject, scopeExpiry) {
|