@edictum/core 0.1.0 → 0.2.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/README.md +46 -0
- package/dist/{chunk-IXMXZGJG.mjs → chunk-23XIQZR5.mjs} +1 -1
- package/dist/chunk-23XIQZR5.mjs.map +1 -0
- package/dist/{chunk-CRPQFRYJ.mjs → chunk-2YSBMUK5.mjs} +2 -10
- package/dist/chunk-2YSBMUK5.mjs.map +1 -0
- package/dist/{chunk-X5E2YY35.mjs → chunk-JOBPRXVE.mjs} +44 -110
- package/dist/chunk-JOBPRXVE.mjs.map +1 -0
- package/dist/{dry-run-54PYIM6T.mjs → dry-run-JTRNTZA5.mjs} +3 -3
- package/dist/dry-run-JTRNTZA5.mjs.map +1 -0
- package/dist/index.cjs +413 -224
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -27
- package/dist/index.d.ts +28 -27
- package/dist/index.mjs +370 -118
- package/dist/index.mjs.map +1 -1
- package/dist/runner-JCAQMF6O.mjs +10 -0
- package/package.json +14 -13
- package/dist/chunk-CRPQFRYJ.mjs.map +0 -1
- package/dist/chunk-IXMXZGJG.mjs.map +0 -1
- package/dist/chunk-X5E2YY35.mjs.map +0 -1
- package/dist/dry-run-54PYIM6T.mjs.map +0 -1
- package/dist/runner-ASI4JIW2.mjs +0 -10
- /package/dist/{runner-ASI4JIW2.mjs.map → runner-JCAQMF6O.mjs.map} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @edictum/core
|
|
2
|
+
|
|
3
|
+
Runtime contract enforcement for AI agent tool calls. One runtime dep ([js-yaml](https://github.com/nodeca/js-yaml)).
|
|
4
|
+
|
|
5
|
+
Part of [Edictum](https://github.com/edictum-ai/edictum-ts) -- runtime contract enforcement for AI agent tool calls.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @edictum/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { readFile } from 'node:fs/promises'
|
|
17
|
+
import { Edictum, EdictumDenied } from '@edictum/core'
|
|
18
|
+
|
|
19
|
+
const guard = Edictum.fromYaml('contracts.yaml')
|
|
20
|
+
|
|
21
|
+
const governedReadFile = (args: Record<string, unknown>) => readFile(args.path as string, 'utf8')
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
await guard.run('readFile', { path: '.env' }, governedReadFile)
|
|
25
|
+
} catch (e) {
|
|
26
|
+
if (e instanceof EdictumDenied) console.log(e.reason)
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Key Exports
|
|
31
|
+
|
|
32
|
+
- `Edictum` -- main guard class (`fromYaml`, `fromYamlString`, `run`, `evaluate`)
|
|
33
|
+
- `EdictumDenied`, `EdictumConfigError`, `EdictumToolError` -- error types
|
|
34
|
+
- `GovernancePipeline` -- governance pipeline (used by adapters)
|
|
35
|
+
- `Verdict` -- contract result builder (`pass()`, `fail(reason)`)
|
|
36
|
+
- `Session`, `MemoryBackend` -- session tracking and storage
|
|
37
|
+
- `RedactionPolicy` -- sensitive field redaction for audit events
|
|
38
|
+
- `CollectingAuditSink`, `StdoutAuditSink`, `FileAuditSink`, `CompositeSink` -- audit sinks
|
|
39
|
+
- `createEnvelope`, `BashClassifier`, `SideEffect` -- envelope construction
|
|
40
|
+
- `composeBundles`, `loadBundle`, `compileContracts` -- YAML engine
|
|
41
|
+
|
|
42
|
+
## Links
|
|
43
|
+
|
|
44
|
+
- [Full documentation](https://docs.edictum.ai)
|
|
45
|
+
- [GitHub](https://github.com/edictum-ai/edictum-ts)
|
|
46
|
+
- [All packages](https://github.com/edictum-ai/edictum-ts#packages)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/evaluation.ts"],"sourcesContent":["/** Evaluation result types for dry-run contract evaluation. */\n\n// ---------------------------------------------------------------------------\n// ContractResult\n// ---------------------------------------------------------------------------\n\n/** Result of evaluating a single contract. */\nexport interface ContractResult {\n readonly contractId: string\n readonly contractType: string // \"precondition\" | \"postcondition\" | \"sandbox\"\n readonly passed: boolean\n readonly message: string | null\n readonly tags: readonly string[]\n readonly observed: boolean\n readonly effect: string\n readonly policyError: boolean\n}\n\n/** Create a frozen ContractResult with defaults matching the Python dataclass. */\nexport function createContractResult(\n fields: Pick<ContractResult, 'contractId' | 'contractType' | 'passed'> &\n Partial<Omit<ContractResult, 'contractId' | 'contractType' | 'passed'>>,\n): ContractResult {\n return Object.freeze({\n contractId: fields.contractId,\n contractType: fields.contractType,\n passed: fields.passed,\n message: fields.message ?? null,\n tags: Object.freeze([...(fields.tags ?? [])]),\n observed: fields.observed ?? false,\n effect: fields.effect ?? 'warn',\n policyError: fields.policyError ?? false,\n })\n}\n\n// ---------------------------------------------------------------------------\n// EvaluationResult\n// ---------------------------------------------------------------------------\n\n/** Result of dry-run evaluation of a tool call against contracts. */\nexport interface EvaluationResult {\n readonly verdict: string // \"allow\" | \"deny\" | \"warn\"\n readonly toolName: string\n readonly contracts: readonly ContractResult[]\n readonly denyReasons: readonly string[]\n readonly warnReasons: readonly string[]\n readonly contractsEvaluated: number\n readonly policyError: boolean\n}\n\n/** Create a frozen EvaluationResult with defaults matching the Python dataclass. */\nexport function createEvaluationResult(\n fields: Pick<EvaluationResult, 'verdict' | 'toolName'> &\n Partial<Omit<EvaluationResult, 'verdict' | 'toolName'>>,\n): EvaluationResult {\n return Object.freeze({\n verdict: fields.verdict,\n toolName: fields.toolName,\n contracts: Object.freeze([...(fields.contracts ?? [])]),\n denyReasons: Object.freeze([...(fields.denyReasons ?? [])]),\n warnReasons: Object.freeze([...(fields.warnReasons ?? [])]),\n contractsEvaluated: fields.contractsEvaluated ?? 0,\n policyError: fields.policyError ?? false,\n })\n}\n"],"mappings":";AAmBO,SAAS,qBACd,QAEgB;AAChB,SAAO,OAAO,OAAO;AAAA,IACnB,YAAY,OAAO;AAAA,IACnB,cAAc,OAAO;AAAA,IACrB,QAAQ,OAAO;AAAA,IACf,SAAS,OAAO,WAAW;AAAA,IAC3B,MAAM,OAAO,OAAO,CAAC,GAAI,OAAO,QAAQ,CAAC,CAAE,CAAC;AAAA,IAC5C,UAAU,OAAO,YAAY;AAAA,IAC7B,QAAQ,OAAO,UAAU;AAAA,IACzB,aAAa,OAAO,eAAe;AAAA,EACrC,CAAC;AACH;AAkBO,SAAS,uBACd,QAEkB;AAClB,SAAO,OAAO,OAAO;AAAA,IACnB,SAAS,OAAO;AAAA,IAChB,UAAU,OAAO;AAAA,IACjB,WAAW,OAAO,OAAO,CAAC,GAAI,OAAO,aAAa,CAAC,CAAE,CAAC;AAAA,IACtD,aAAa,OAAO,OAAO,CAAC,GAAI,OAAO,eAAe,CAAC,CAAE,CAAC;AAAA,IAC1D,aAAa,OAAO,OAAO,CAAC,GAAI,OAAO,eAAe,CAAC,CAAE,CAAC;AAAA,IAC1D,oBAAoB,OAAO,sBAAsB;AAAA,IACjD,aAAa,OAAO,eAAe;AAAA,EACrC,CAAC;AACH;","names":[]}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/errors.ts
|
|
9
2
|
var EdictumDenied = class extends Error {
|
|
10
3
|
reason;
|
|
@@ -57,7 +50,7 @@ function _validateToolName(toolName) {
|
|
|
57
50
|
for (let i = 0; i < toolName.length; i++) {
|
|
58
51
|
const code = toolName.charCodeAt(i);
|
|
59
52
|
const ch = toolName[i];
|
|
60
|
-
if (code < 32 || code
|
|
53
|
+
if (code < 32 || code >= 127 && code <= 159 || code === 8232 || code === 8233 || ch === "/" || ch === "\\") {
|
|
61
54
|
throw new EdictumConfigError(`Invalid tool_name: ${JSON.stringify(toolName)}`);
|
|
62
55
|
}
|
|
63
56
|
}
|
|
@@ -223,7 +216,6 @@ function createEnvelope(toolName, toolInput, options = {}) {
|
|
|
223
216
|
}
|
|
224
217
|
|
|
225
218
|
export {
|
|
226
|
-
__require,
|
|
227
219
|
EdictumDenied,
|
|
228
220
|
EdictumConfigError,
|
|
229
221
|
EdictumToolError,
|
|
@@ -235,4 +227,4 @@ export {
|
|
|
235
227
|
BashClassifier,
|
|
236
228
|
createEnvelope
|
|
237
229
|
};
|
|
238
|
-
//# sourceMappingURL=chunk-
|
|
230
|
+
//# sourceMappingURL=chunk-2YSBMUK5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/envelope.ts"],"sourcesContent":["/** Exception classes for Edictum. */\n\n/** Raised when guard.run() denies a tool call in enforce mode. */\nexport class EdictumDenied extends Error {\n readonly reason: string\n readonly decisionSource: string | null\n readonly decisionName: string | null\n\n constructor(\n reason: string,\n decisionSource: string | null = null,\n decisionName: string | null = null,\n ) {\n super(reason)\n this.name = 'EdictumDenied'\n this.reason = reason\n this.decisionSource = decisionSource\n this.decisionName = decisionName\n }\n}\n\n/** Raised for configuration/load-time errors (invalid YAML, schema failures, etc.). */\nexport class EdictumConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'EdictumConfigError'\n }\n}\n\n/** Raised when the governed tool itself fails. */\nexport class EdictumToolError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'EdictumToolError'\n }\n}\n","/** Tool Invocation Envelope — immutable snapshot of a tool call. */\n\nimport { randomUUID } from 'node:crypto'\n\nimport { EdictumConfigError } from './errors.js'\nimport type { ToolConfig } from './types.js'\n\n// ---------------------------------------------------------------------------\n// SideEffect\n// ---------------------------------------------------------------------------\n\n/**\n * Classification of tool side effects.\n *\n * Determines postcondition behavior and retry safety.\n *\n * DEFAULTS:\n * - Unregistered tools -> IRREVERSIBLE (conservative)\n * - Bash -> IRREVERSIBLE unless strict allowlist match\n * - Classification errors always err toward MORE restrictive\n */\nexport const SideEffect = {\n PURE: 'pure',\n READ: 'read',\n WRITE: 'write',\n IRREVERSIBLE: 'irreversible',\n} as const\n\nexport type SideEffect = (typeof SideEffect)[keyof typeof SideEffect]\n\n// ---------------------------------------------------------------------------\n// Principal\n// ---------------------------------------------------------------------------\n\n/**\n * Identity context for audit attribution.\n *\n * NOTE: `claims` is a plain object. The Principal itself is frozen via\n * `Object.freeze()`, making the reference immutable. Callers should treat\n * claims as read-only after construction.\n */\nexport interface Principal {\n readonly userId: string | null\n readonly serviceId: string | null\n readonly orgId: string | null\n readonly role: string | null\n readonly ticketRef: string | null\n readonly claims: Readonly<Record<string, unknown>>\n}\n\n/** Create a frozen Principal with defaults for omitted fields. */\nexport function createPrincipal(partial: Partial<Principal> = {}): Readonly<Principal> {\n const p: Principal = {\n userId: partial.userId ?? null,\n serviceId: partial.serviceId ?? null,\n orgId: partial.orgId ?? null,\n role: partial.role ?? null,\n ticketRef: partial.ticketRef ?? null,\n claims: partial.claims ?? {},\n }\n return deepFreeze(p)\n}\n\n// ---------------------------------------------------------------------------\n// _validateToolName\n// ---------------------------------------------------------------------------\n\n/**\n * Validate tool_name: reject empty, control chars, path separators.\n *\n * Throws EdictumConfigError for:\n * - Empty string\n * - Any C0 control character (code < 0x20), DEL/C1 (U+007F-U+009F)\n * - Unicode line/paragraph separators (U+2028, U+2029)\n * - Forward slash `/`\n * - Backslash `\\`\n */\nexport function _validateToolName(toolName: string): void {\n if (!toolName) {\n throw new EdictumConfigError(`Invalid tool_name: ${JSON.stringify(toolName)}`)\n }\n for (let i = 0; i < toolName.length; i++) {\n const code = toolName.charCodeAt(i)\n const ch = toolName[i]\n if (\n code < 0x20 ||\n (code >= 0x7f && code <= 0x9f) ||\n code === 0x2028 ||\n code === 0x2029 ||\n ch === '/' ||\n ch === '\\\\'\n ) {\n throw new EdictumConfigError(`Invalid tool_name: ${JSON.stringify(toolName)}`)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// ToolEnvelope\n// ---------------------------------------------------------------------------\n\n/**\n * Immutable snapshot of a tool invocation.\n *\n * Prefer `createEnvelope()` factory for deep-copy guarantees.\n * Direct construction validates tool_name but does NOT deep-copy args.\n */\nexport interface ToolEnvelope {\n // Identity\n readonly toolName: string\n readonly args: Readonly<Record<string, unknown>>\n readonly callId: string\n readonly runId: string\n readonly callIndex: number\n readonly parentCallId: string | null\n\n // Classification\n readonly sideEffect: SideEffect\n readonly idempotent: boolean\n\n // Context\n readonly environment: string\n readonly timestamp: Date\n readonly caller: string\n readonly toolUseId: string | null\n\n // Principal\n readonly principal: Readonly<Principal> | null\n\n // Extracted convenience fields\n readonly bashCommand: string | null\n readonly filePath: string | null\n\n // Extensible\n readonly metadata: Readonly<Record<string, unknown>>\n}\n\n// ---------------------------------------------------------------------------\n// deepFreeze\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively freeze an object and all nested objects.\n *\n * Date objects are skipped — Object.freeze() cannot prevent mutation\n * via Date prototype methods (setFullYear, setTime, etc.) because Date\n * stores state in internal slots, not own properties.\n */\nexport function deepFreeze<T>(obj: T): T {\n if (obj === null || obj === undefined || typeof obj !== 'object') {\n return obj\n }\n // Date internal slots are not freezable — skip to avoid false sense of safety\n if (obj instanceof Date) {\n return obj\n }\n // RegExp with global/sticky flags stores mutable lastIndex in internal state.\n // Freezing prevents String.replace() from updating lastIndex → TypeError.\n if (obj instanceof RegExp) {\n return obj\n }\n Object.freeze(obj)\n for (const value of Object.values(obj as Record<string, unknown>)) {\n if (\n value !== null &&\n value !== undefined &&\n typeof value === 'object' &&\n !Object.isFrozen(value)\n ) {\n deepFreeze(value)\n }\n }\n return obj\n}\n\n// ---------------------------------------------------------------------------\n// ToolRegistry\n// ---------------------------------------------------------------------------\n\n/** Maps tool names to governance properties. Unregistered tools default to IRREVERSIBLE. */\nexport class ToolRegistry {\n private readonly _tools: Map<string, ToolConfig> = new Map()\n\n register(\n name: string,\n sideEffect: SideEffect = SideEffect.WRITE,\n idempotent: boolean = false,\n ): void {\n this._tools.set(name, { name, sideEffect, idempotent })\n }\n\n classify(toolName: string, _args: Record<string, unknown>): [SideEffect, boolean] {\n const cfg = this._tools.get(toolName)\n if (cfg) {\n return [cfg.sideEffect as SideEffect, cfg.idempotent]\n }\n return [SideEffect.IRREVERSIBLE, false]\n }\n}\n\n// ---------------------------------------------------------------------------\n// BashClassifier\n// ---------------------------------------------------------------------------\n\n/**\n * Classify bash commands by side-effect level.\n *\n * Default is IRREVERSIBLE. Only downgraded to READ via strict\n * allowlist AND absence of shell operators.\n *\n * This is a heuristic, not a security boundary.\n */\nexport const BashClassifier = {\n READ_ALLOWLIST: [\n 'ls',\n 'cat',\n 'head',\n 'tail',\n 'wc',\n 'find',\n 'grep',\n 'rg',\n 'git status',\n 'git log',\n 'git diff',\n 'git show',\n 'git branch',\n 'git remote',\n 'git tag',\n 'echo',\n 'pwd',\n 'whoami',\n 'date',\n 'which',\n 'file',\n 'stat',\n 'du',\n 'df',\n 'tree',\n 'less',\n 'more',\n ] as const,\n\n SHELL_OPERATORS: [\n '\\n',\n '\\r',\n '<(',\n '<<',\n '$',\n '${',\n '>',\n '>>',\n '|',\n ';',\n '&&',\n '||',\n '$(',\n '`',\n '#{',\n ] as const,\n\n classify(command: string): SideEffect {\n const stripped = command.trim()\n if (!stripped) {\n return SideEffect.READ\n }\n\n for (const op of BashClassifier.SHELL_OPERATORS) {\n if (stripped.includes(op)) {\n return SideEffect.IRREVERSIBLE\n }\n }\n\n for (const allowed of BashClassifier.READ_ALLOWLIST) {\n if (stripped === allowed || stripped.startsWith(allowed + ' ')) {\n return SideEffect.READ\n }\n }\n\n return SideEffect.IRREVERSIBLE\n },\n} as const\n\n// ---------------------------------------------------------------------------\n// safeDeepCopy — structuredClone with JSON roundtrip fallback\n// ---------------------------------------------------------------------------\n\nfunction safeDeepCopy<T>(value: T): T {\n try {\n return structuredClone(value)\n } catch {\n return JSON.parse(JSON.stringify(value)) as T\n }\n}\n\n// ---------------------------------------------------------------------------\n// createEnvelope\n// ---------------------------------------------------------------------------\n\n/** Options for `createEnvelope()` beyond the required positional args. */\nexport interface CreateEnvelopeOptions {\n readonly runId?: string\n readonly callIndex?: number\n readonly callId?: string\n readonly parentCallId?: string | null\n readonly sideEffect?: SideEffect\n readonly idempotent?: boolean\n readonly environment?: string\n readonly timestamp?: Date\n readonly caller?: string\n readonly toolUseId?: string | null\n readonly principal?: Principal | null\n readonly metadata?: Record<string, unknown>\n readonly registry?: ToolRegistry | null\n}\n\n/**\n * Factory that enforces immutability guarantees.\n *\n * Prefer this factory over direct construction — it deep-copies args\n * and metadata to ensure the envelope is a true immutable snapshot.\n */\nexport function createEnvelope(\n toolName: string,\n toolInput: Record<string, unknown>,\n options: CreateEnvelopeOptions = {},\n): Readonly<ToolEnvelope> {\n _validateToolName(toolName)\n\n // Deep-copy for immutability\n const safeArgs = safeDeepCopy(toolInput)\n\n // Deep-copy metadata\n const safeMetadata = options.metadata ? safeDeepCopy(options.metadata) : {}\n\n // Deep-copy Principal to protect claims dict\n let safePrincipal: Readonly<Principal> | null = null\n if (options.principal != null) {\n const p = options.principal\n safePrincipal = createPrincipal({\n userId: p.userId,\n serviceId: p.serviceId,\n orgId: p.orgId,\n role: p.role,\n ticketRef: p.ticketRef,\n claims: p.claims ? safeDeepCopy(p.claims as Record<string, unknown>) : {},\n })\n }\n\n // Classification: explicit options > registry > defaults\n const registry = options.registry ?? null\n let sideEffect: SideEffect = options.sideEffect ?? SideEffect.IRREVERSIBLE\n let idempotent = options.idempotent ?? false\n let bashCommand: string | null = null\n let filePath: string | null = null\n\n // Registry overrides defaults but not explicit options\n if (registry) {\n const [regEffect, regIdempotent] = registry.classify(toolName, safeArgs)\n if (options.sideEffect == null) sideEffect = regEffect\n if (options.idempotent == null) idempotent = regIdempotent\n }\n\n // Extract convenience fields (handle both snake_case and camelCase keys)\n if (toolName === 'Bash') {\n bashCommand = (safeArgs.command as string) ?? ''\n // BashClassifier wins over registry but NOT over explicit caller options\n if (options.sideEffect == null) {\n sideEffect = BashClassifier.classify(bashCommand)\n }\n } else if (toolName === 'Read' || toolName === 'Glob' || toolName === 'Grep') {\n filePath =\n (safeArgs.file_path as string) ??\n (safeArgs.filePath as string) ??\n (safeArgs.path as string) ??\n null\n } else if (toolName === 'Write' || toolName === 'Edit') {\n filePath =\n (safeArgs.file_path as string) ??\n (safeArgs.filePath as string) ??\n (safeArgs.path as string) ??\n null\n }\n\n const envelope: ToolEnvelope = {\n toolName,\n args: safeArgs,\n callId: options.callId ?? randomUUID(),\n runId: options.runId ?? '',\n callIndex: options.callIndex ?? 0,\n parentCallId: options.parentCallId ?? null,\n sideEffect,\n idempotent,\n environment: options.environment ?? 'production',\n timestamp: options.timestamp ?? new Date(),\n caller: options.caller ?? '',\n toolUseId: options.toolUseId ?? null,\n principal: safePrincipal,\n bashCommand,\n filePath,\n metadata: safeMetadata,\n }\n\n return deepFreeze(envelope)\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
EdictumToolError,
|
|
5
5
|
SideEffect,
|
|
6
6
|
createEnvelope
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2YSBMUK5.mjs";
|
|
8
8
|
|
|
9
9
|
// src/approval.ts
|
|
10
10
|
import { randomUUID } from "crypto";
|
|
@@ -34,11 +34,8 @@ var RedactionPolicy = class _RedactionPolicy {
|
|
|
34
34
|
"passphrase"
|
|
35
35
|
]);
|
|
36
36
|
static BASH_REDACTION_PATTERNS = [
|
|
37
|
-
[
|
|
38
|
-
|
|
39
|
-
"$1[REDACTED]"
|
|
40
|
-
],
|
|
41
|
-
[String.raw`(-p\s*|--password[= ])\S+`, "$1[REDACTED]"],
|
|
37
|
+
[String.raw`(export\s+\w*(?:KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL)\w*=)\S+`, "$1[REDACTED]"],
|
|
38
|
+
[String.raw`((?:^|\s)-p\s*|--password[= ])\S+`, "$1[REDACTED]"],
|
|
42
39
|
[String.raw`(://\w+:)\S+(@)`, "$1[REDACTED]$2"]
|
|
43
40
|
];
|
|
44
41
|
static SECRET_VALUE_PATTERNS = [
|
|
@@ -68,25 +65,18 @@ var RedactionPolicy = class _RedactionPolicy {
|
|
|
68
65
|
}
|
|
69
66
|
}
|
|
70
67
|
}
|
|
71
|
-
this._patterns = [
|
|
72
|
-
...customPatterns ?? [],
|
|
73
|
-
..._RedactionPolicy.BASH_REDACTION_PATTERNS
|
|
74
|
-
];
|
|
68
|
+
this._patterns = [...customPatterns ?? [], ..._RedactionPolicy.BASH_REDACTION_PATTERNS];
|
|
75
69
|
this._compiledPatterns = this._patterns.map(
|
|
76
70
|
([pattern, replacement]) => [new RegExp(pattern, "g"), replacement]
|
|
77
71
|
);
|
|
78
|
-
this._compiledSecretPatterns = _RedactionPolicy.SECRET_VALUE_PATTERNS.map(
|
|
79
|
-
(p) => new RegExp(p)
|
|
80
|
-
);
|
|
72
|
+
this._compiledSecretPatterns = _RedactionPolicy.SECRET_VALUE_PATTERNS.map((p) => new RegExp(p));
|
|
81
73
|
this._detectValues = detectSecretValues;
|
|
82
74
|
}
|
|
83
75
|
/** Recursively redact sensitive data from tool arguments. */
|
|
84
76
|
redactArgs(args) {
|
|
85
77
|
if (args !== null && typeof args === "object" && !Array.isArray(args)) {
|
|
86
78
|
const result = {};
|
|
87
|
-
for (const [key, value] of Object.entries(
|
|
88
|
-
args
|
|
89
|
-
)) {
|
|
79
|
+
for (const [key, value] of Object.entries(args)) {
|
|
90
80
|
result[key] = this._isSensitiveKey(key) ? "[REDACTED]" : this.redactArgs(value);
|
|
91
81
|
}
|
|
92
82
|
return result;
|
|
@@ -98,6 +88,18 @@ var RedactionPolicy = class _RedactionPolicy {
|
|
|
98
88
|
if (this._detectValues && this._looksLikeSecret(args)) {
|
|
99
89
|
return "[REDACTED]";
|
|
100
90
|
}
|
|
91
|
+
if (this._detectValues) {
|
|
92
|
+
const capped = args.length > _RedactionPolicy.MAX_REGEX_INPUT ? args.slice(0, _RedactionPolicy.MAX_REGEX_INPUT) : args;
|
|
93
|
+
let redacted = capped;
|
|
94
|
+
for (const [pattern, replacement] of this._compiledPatterns) {
|
|
95
|
+
pattern.lastIndex = 0;
|
|
96
|
+
redacted = redacted.replace(pattern, replacement);
|
|
97
|
+
}
|
|
98
|
+
if (redacted.length > 1e3) {
|
|
99
|
+
return redacted.slice(0, 997) + "...";
|
|
100
|
+
}
|
|
101
|
+
return redacted;
|
|
102
|
+
}
|
|
101
103
|
if (args.length > 1e3) {
|
|
102
104
|
return args.slice(0, 997) + "...";
|
|
103
105
|
}
|
|
@@ -168,7 +170,7 @@ var RedactionPolicy = class _RedactionPolicy {
|
|
|
168
170
|
|
|
169
171
|
// src/approval.ts
|
|
170
172
|
function sanitizeForTerminal(s) {
|
|
171
|
-
return s.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").replace(/[\x00-\x1f\x7f]/g, "");
|
|
173
|
+
return s.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").replace(/[\x00-\x1f\x7f-\x9f\u2028\u2029]/g, "");
|
|
172
174
|
}
|
|
173
175
|
var ApprovalStatus = {
|
|
174
176
|
PENDING: "pending",
|
|
@@ -232,9 +234,7 @@ var LocalApprovalBackend = class {
|
|
|
232
234
|
const effectiveTimeout = timeout ?? (request ? request.timeout : 300);
|
|
233
235
|
try {
|
|
234
236
|
const response = await this._readStdin(approvalId, effectiveTimeout);
|
|
235
|
-
const approved = ["y", "yes", "approve"].includes(
|
|
236
|
-
response.trim().toLowerCase()
|
|
237
|
-
);
|
|
237
|
+
const approved = ["y", "yes", "approve"].includes(response.trim().toLowerCase());
|
|
238
238
|
const status = approved ? ApprovalStatus.APPROVED : ApprovalStatus.DENIED;
|
|
239
239
|
return createApprovalDecision({
|
|
240
240
|
approved,
|
|
@@ -707,10 +707,7 @@ var GovernancePipeline = class {
|
|
|
707
707
|
}
|
|
708
708
|
}
|
|
709
709
|
const pe = hasPolicyError(contractsEvaluated);
|
|
710
|
-
const observeResults = await this._evaluateObserveContracts(
|
|
711
|
-
envelope,
|
|
712
|
-
session
|
|
713
|
-
);
|
|
710
|
+
const observeResults = await this._evaluateObserveContracts(envelope, session);
|
|
714
711
|
return createPreDecision({
|
|
715
712
|
action: "allow",
|
|
716
713
|
hooksEvaluated,
|
|
@@ -765,23 +762,17 @@ var GovernancePipeline = class {
|
|
|
765
762
|
text = policy.redactResult(text, text.length + 100);
|
|
766
763
|
}
|
|
767
764
|
redactedResponse = text;
|
|
768
|
-
warnings.push(
|
|
769
|
-
`\u26A0\uFE0F Content redacted by ${contract.name}.`
|
|
770
|
-
);
|
|
765
|
+
warnings.push(`\u26A0\uFE0F Content redacted by ${contract.name}.`);
|
|
771
766
|
} else if (effect === "deny" && isSafe) {
|
|
772
767
|
redactedResponse = `[OUTPUT SUPPRESSED] ${verdict.message}`;
|
|
773
768
|
outputSuppressed = true;
|
|
774
|
-
warnings.push(
|
|
775
|
-
`\u26A0\uFE0F Output suppressed by ${contract.name}.`
|
|
776
|
-
);
|
|
769
|
+
warnings.push(`\u26A0\uFE0F Output suppressed by ${contract.name}.`);
|
|
777
770
|
} else if ((effect === "redact" || effect === "deny") && !isSafe) {
|
|
778
771
|
warnings.push(
|
|
779
772
|
`\u26A0\uFE0F ${verdict.message} Tool already executed \u2014 assess before proceeding.`
|
|
780
773
|
);
|
|
781
774
|
} else if (isSafe) {
|
|
782
|
-
warnings.push(
|
|
783
|
-
`\u26A0\uFE0F ${verdict.message} Consider retrying.`
|
|
784
|
-
);
|
|
775
|
+
warnings.push(`\u26A0\uFE0F ${verdict.message} Consider retrying.`);
|
|
785
776
|
} else {
|
|
786
777
|
warnings.push(
|
|
787
778
|
`\u26A0\uFE0F ${verdict.message} Tool already executed \u2014 assess before proceeding.`
|
|
@@ -803,10 +794,7 @@ var GovernancePipeline = class {
|
|
|
803
794
|
try {
|
|
804
795
|
verdict = await contract.check(envelope, toolResponse);
|
|
805
796
|
} catch (exc) {
|
|
806
|
-
verdict = Verdict.fail(
|
|
807
|
-
`Observe-mode postcondition error: ${exc}`,
|
|
808
|
-
{ policy_error: true }
|
|
809
|
-
);
|
|
797
|
+
verdict = Verdict.fail(`Observe-mode postcondition error: ${exc}`, { policy_error: true });
|
|
810
798
|
}
|
|
811
799
|
const record = {
|
|
812
800
|
name: contract.name,
|
|
@@ -824,9 +812,7 @@ var GovernancePipeline = class {
|
|
|
824
812
|
warnings.push(`\u26A0\uFE0F [observe] ${verdict.message}`);
|
|
825
813
|
}
|
|
826
814
|
}
|
|
827
|
-
const postconditionsPassed = contractsEvaluated.length > 0 ? contractsEvaluated.every(
|
|
828
|
-
(c) => c["passed"] === true || c["observed"] === true
|
|
829
|
-
) : true;
|
|
815
|
+
const postconditionsPassed = contractsEvaluated.length > 0 ? contractsEvaluated.every((c) => c["passed"] === true || c["observed"] === true) : true;
|
|
830
816
|
const pe = hasPolicyError(contractsEvaluated);
|
|
831
817
|
return createPostDecision({
|
|
832
818
|
toolSuccess,
|
|
@@ -847,17 +833,12 @@ var GovernancePipeline = class {
|
|
|
847
833
|
*/
|
|
848
834
|
async _evaluateObserveContracts(envelope, session) {
|
|
849
835
|
const results = [];
|
|
850
|
-
for (const contract of this._guard.getObservePreconditions(
|
|
851
|
-
envelope
|
|
852
|
-
)) {
|
|
836
|
+
for (const contract of this._guard.getObservePreconditions(envelope)) {
|
|
853
837
|
let verdict;
|
|
854
838
|
try {
|
|
855
839
|
verdict = await contract.check(envelope);
|
|
856
840
|
} catch (exc) {
|
|
857
|
-
verdict = Verdict.fail(
|
|
858
|
-
`Observe-mode precondition error: ${exc}`,
|
|
859
|
-
{ policy_error: true }
|
|
860
|
-
);
|
|
841
|
+
verdict = Verdict.fail(`Observe-mode precondition error: ${exc}`, { policy_error: true });
|
|
861
842
|
}
|
|
862
843
|
results.push({
|
|
863
844
|
name: contract.name,
|
|
@@ -867,17 +848,12 @@ var GovernancePipeline = class {
|
|
|
867
848
|
source: contract.source ?? "yaml_precondition"
|
|
868
849
|
});
|
|
869
850
|
}
|
|
870
|
-
for (const contract of this._guard.getObserveSandboxContracts(
|
|
871
|
-
envelope
|
|
872
|
-
)) {
|
|
851
|
+
for (const contract of this._guard.getObserveSandboxContracts(envelope)) {
|
|
873
852
|
let verdict;
|
|
874
853
|
try {
|
|
875
854
|
verdict = await contract.check(envelope);
|
|
876
855
|
} catch (exc) {
|
|
877
|
-
verdict = Verdict.fail(
|
|
878
|
-
`Observe-mode sandbox error: ${exc}`,
|
|
879
|
-
{ policy_error: true }
|
|
880
|
-
);
|
|
856
|
+
verdict = Verdict.fail(`Observe-mode sandbox error: ${exc}`, { policy_error: true });
|
|
881
857
|
}
|
|
882
858
|
results.push({
|
|
883
859
|
name: contract.name,
|
|
@@ -892,10 +868,9 @@ var GovernancePipeline = class {
|
|
|
892
868
|
try {
|
|
893
869
|
verdict = await contract.check(session);
|
|
894
870
|
} catch (exc) {
|
|
895
|
-
verdict = Verdict.fail(
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
);
|
|
871
|
+
verdict = Verdict.fail(`Observe-mode session contract error: ${exc}`, {
|
|
872
|
+
policy_error: true
|
|
873
|
+
});
|
|
899
874
|
}
|
|
900
875
|
results.push({
|
|
901
876
|
name: contract.name,
|
|
@@ -923,7 +898,7 @@ function _validateStorageKeyComponent(value, label) {
|
|
|
923
898
|
}
|
|
924
899
|
for (let i = 0; i < value.length; i++) {
|
|
925
900
|
const code = value.charCodeAt(i);
|
|
926
|
-
if (code < 32 || code ===
|
|
901
|
+
if (code < 32 || code >= 127 && code <= 159 || code === 8232 || code === 8233) {
|
|
927
902
|
throw new EdictumConfigError(`Invalid ${label}: ${JSON.stringify(value)}`);
|
|
928
903
|
}
|
|
929
904
|
}
|
|
@@ -962,14 +937,10 @@ var Session = class {
|
|
|
962
937
|
}
|
|
963
938
|
async toolExecutionCount(tool) {
|
|
964
939
|
_validateStorageKeyComponent(tool, "tool_name");
|
|
965
|
-
return Number(
|
|
966
|
-
await this._backend.get(`s:${this._sid}:tool:${tool}`) ?? 0
|
|
967
|
-
);
|
|
940
|
+
return Number(await this._backend.get(`s:${this._sid}:tool:${tool}`) ?? 0);
|
|
968
941
|
}
|
|
969
942
|
async consecutiveFailures() {
|
|
970
|
-
return Number(
|
|
971
|
-
await this._backend.get(`s:${this._sid}:consec_fail`) ?? 0
|
|
972
|
-
);
|
|
943
|
+
return Number(await this._backend.get(`s:${this._sid}:consec_fail`) ?? 0);
|
|
973
944
|
}
|
|
974
945
|
/**
|
|
975
946
|
* Pre-fetch multiple session counters in a single backend call.
|
|
@@ -982,10 +953,7 @@ var Session = class {
|
|
|
982
953
|
* backends without batchGet support.
|
|
983
954
|
*/
|
|
984
955
|
async batchGetCounters(options) {
|
|
985
|
-
const keys = [
|
|
986
|
-
`s:${this._sid}:attempts`,
|
|
987
|
-
`s:${this._sid}:execs`
|
|
988
|
-
];
|
|
956
|
+
const keys = [`s:${this._sid}:attempts`, `s:${this._sid}:execs`];
|
|
989
957
|
const keyLabels = ["attempts", "execs"];
|
|
990
958
|
if (options?.includeTool != null) {
|
|
991
959
|
_validateStorageKeyComponent(options.includeTool, "tool_name");
|
|
@@ -1093,46 +1061,22 @@ async function run(guard, toolName, args, toolCallable, options) {
|
|
|
1093
1061
|
principal: principalDict
|
|
1094
1062
|
}
|
|
1095
1063
|
);
|
|
1096
|
-
await _emitRunPreAudit(
|
|
1097
|
-
guard,
|
|
1098
|
-
envelope,
|
|
1099
|
-
session,
|
|
1100
|
-
AuditAction.CALL_APPROVAL_REQUESTED,
|
|
1101
|
-
pre
|
|
1102
|
-
);
|
|
1064
|
+
await _emitRunPreAudit(guard, envelope, session, AuditAction.CALL_APPROVAL_REQUESTED, pre);
|
|
1103
1065
|
const decision = await guard._approvalBackend.waitForDecision(
|
|
1104
1066
|
approvalRequest.approvalId,
|
|
1105
1067
|
pre.approvalTimeout
|
|
1106
1068
|
);
|
|
1107
1069
|
let approved = false;
|
|
1108
1070
|
if (decision.status === ApprovalStatus.TIMEOUT) {
|
|
1109
|
-
await _emitRunPreAudit(
|
|
1110
|
-
guard,
|
|
1111
|
-
envelope,
|
|
1112
|
-
session,
|
|
1113
|
-
AuditAction.CALL_APPROVAL_TIMEOUT,
|
|
1114
|
-
pre
|
|
1115
|
-
);
|
|
1071
|
+
await _emitRunPreAudit(guard, envelope, session, AuditAction.CALL_APPROVAL_TIMEOUT, pre);
|
|
1116
1072
|
if (pre.approvalTimeoutEffect === "allow") {
|
|
1117
1073
|
approved = true;
|
|
1118
1074
|
}
|
|
1119
1075
|
} else if (!decision.approved) {
|
|
1120
|
-
await _emitRunPreAudit(
|
|
1121
|
-
guard,
|
|
1122
|
-
envelope,
|
|
1123
|
-
session,
|
|
1124
|
-
AuditAction.CALL_APPROVAL_DENIED,
|
|
1125
|
-
pre
|
|
1126
|
-
);
|
|
1076
|
+
await _emitRunPreAudit(guard, envelope, session, AuditAction.CALL_APPROVAL_DENIED, pre);
|
|
1127
1077
|
} else {
|
|
1128
1078
|
approved = true;
|
|
1129
|
-
await _emitRunPreAudit(
|
|
1130
|
-
guard,
|
|
1131
|
-
envelope,
|
|
1132
|
-
session,
|
|
1133
|
-
AuditAction.CALL_APPROVAL_GRANTED,
|
|
1134
|
-
pre
|
|
1135
|
-
);
|
|
1079
|
+
await _emitRunPreAudit(guard, envelope, session, AuditAction.CALL_APPROVAL_GRANTED, pre);
|
|
1136
1080
|
}
|
|
1137
1081
|
if (approved) {
|
|
1138
1082
|
if (guard._onAllow) {
|
|
@@ -1168,11 +1112,7 @@ async function run(guard, toolName, args, toolCallable, options) {
|
|
|
1168
1112
|
} catch {
|
|
1169
1113
|
}
|
|
1170
1114
|
}
|
|
1171
|
-
throw new EdictumDenied(
|
|
1172
|
-
pre.reason ?? "denied",
|
|
1173
|
-
pre.decisionSource,
|
|
1174
|
-
pre.decisionName
|
|
1175
|
-
);
|
|
1115
|
+
throw new EdictumDenied(pre.reason ?? "denied", pre.decisionSource, pre.decisionName);
|
|
1176
1116
|
}
|
|
1177
1117
|
} else {
|
|
1178
1118
|
for (const cr of pre.contractsEvaluated) {
|
|
@@ -1196,13 +1136,7 @@ async function run(guard, toolName, args, toolCallable, options) {
|
|
|
1196
1136
|
await guard.auditSink.emit(observedEvent);
|
|
1197
1137
|
}
|
|
1198
1138
|
}
|
|
1199
|
-
await _emitRunPreAudit(
|
|
1200
|
-
guard,
|
|
1201
|
-
envelope,
|
|
1202
|
-
session,
|
|
1203
|
-
AuditAction.CALL_ALLOWED,
|
|
1204
|
-
pre
|
|
1205
|
-
);
|
|
1139
|
+
await _emitRunPreAudit(guard, envelope, session, AuditAction.CALL_ALLOWED, pre);
|
|
1206
1140
|
if (guard._onAllow) {
|
|
1207
1141
|
try {
|
|
1208
1142
|
guard._onAllow(envelope);
|
|
@@ -1296,4 +1230,4 @@ export {
|
|
|
1296
1230
|
defaultSuccessCheck,
|
|
1297
1231
|
run
|
|
1298
1232
|
};
|
|
1299
|
-
//# sourceMappingURL=chunk-
|
|
1233
|
+
//# sourceMappingURL=chunk-JOBPRXVE.mjs.map
|