@occ-core/policy-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ import type { AgentPolicy, PolicyCommitment } from "./types.js";
2
+ /**
3
+ * Hash a policy to a base64 SHA-256 digest using OCC canonical serialization.
4
+ */
5
+ export declare function hashPolicy(policy: AgentPolicy): string;
6
+ /**
7
+ * Commit a policy to the OCC commit service.
8
+ *
9
+ * Validates the policy, hashes it, sends the digest to /commit,
10
+ * and returns the PolicyCommitment with the OCC proof.
11
+ */
12
+ export declare function commitPolicy(policy: AgentPolicy, config: {
13
+ apiUrl: string;
14
+ apiKey?: string | undefined;
15
+ }): Promise<PolicyCommitment>;
16
+ //# sourceMappingURL=commitment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitment.d.ts","sourceRoot":"","sources":["../src/commitment.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAIhE;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAItD;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAqD3B"}
@@ -0,0 +1,66 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+ import { sha256 } from "@noble/hashes/sha256";
4
+ import { canonicalize } from "occproof";
5
+ import { PolicyCommitmentError } from "./errors.js";
6
+ import { validatePolicy } from "./schema.js";
7
+ /**
8
+ * Hash a policy to a base64 SHA-256 digest using OCC canonical serialization.
9
+ */
10
+ export function hashPolicy(policy) {
11
+ const bytes = canonicalize(policy);
12
+ const digest = sha256(bytes);
13
+ return Buffer.from(digest).toString("base64");
14
+ }
15
+ /**
16
+ * Commit a policy to the OCC commit service.
17
+ *
18
+ * Validates the policy, hashes it, sends the digest to /commit,
19
+ * and returns the PolicyCommitment with the OCC proof.
20
+ */
21
+ export async function commitPolicy(policy, config) {
22
+ // Validate first
23
+ validatePolicy(policy);
24
+ const digestB64 = hashPolicy(policy);
25
+ const headers = {
26
+ "Content-Type": "application/json",
27
+ };
28
+ if (config.apiKey) {
29
+ headers["Authorization"] = `Bearer ${config.apiKey}`;
30
+ }
31
+ let response;
32
+ try {
33
+ response = await fetch(config.apiUrl, {
34
+ method: "POST",
35
+ headers,
36
+ body: JSON.stringify({
37
+ digests: [{ digestB64, hashAlg: "sha256" }],
38
+ metadata: {
39
+ kind: "policy-commitment",
40
+ adapter: "occ-agent",
41
+ policyName: policy.name,
42
+ policyVersion: policy.version,
43
+ },
44
+ }),
45
+ });
46
+ }
47
+ catch (err) {
48
+ throw new PolicyCommitmentError(`Failed to reach OCC commit service: ${err instanceof Error ? err.message : String(err)}`);
49
+ }
50
+ if (!response.ok) {
51
+ const body = await response.text();
52
+ throw new PolicyCommitmentError(`OCC policy commit failed (${response.status}): ${body}`);
53
+ }
54
+ const proofs = (await response.json());
55
+ const proof = proofs[0];
56
+ if (!proof) {
57
+ throw new PolicyCommitmentError("OCC commit returned empty proof array");
58
+ }
59
+ return {
60
+ policy,
61
+ policyDigestB64: digestB64,
62
+ occProof: proof,
63
+ committedAt: Date.now(),
64
+ };
65
+ }
66
+ //# sourceMappingURL=commitment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitment.js","sourceRoot":"","sources":["../src/commitment.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,mCAAmC;AAEnC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAmB;IAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAmB,EACnB,MAAuD;IAEvD,iBAAiB;IACjB,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAErC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,CAAC,MAAM,EAAE,CAAC;IACvD,CAAC;IAED,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE;YACpC,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;gBAC3C,QAAQ,EAAE;oBACR,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,WAAW;oBACpB,UAAU,EAAE,MAAM,CAAC,IAAI;oBACvB,aAAa,EAAE,MAAM,CAAC,OAAO;iBAC9B;aACF,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,qBAAqB,CAC7B,uCAAuC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC1F,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,qBAAqB,CAC7B,6BAA6B,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAe,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,qBAAqB,CAAC,uCAAuC,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO;QACL,MAAM;QACN,eAAe,EAAE,SAAS;QAC1B,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { AuditEntry, EnforcementDecision, ExecutionContextState } from "./types.js";
2
+ /**
3
+ * Mutable execution context tracking cumulative state for policy enforcement.
4
+ * One instance per agent session.
5
+ */
6
+ export declare class ExecutionContext {
7
+ #private;
8
+ constructor(initial?: Partial<ExecutionContextState>);
9
+ /** Record a completed tool call. */
10
+ recordCall(tool: string, skill: string | undefined, costCents: number, timestamp?: number): void;
11
+ /** Start a skill invocation (for concurrency tracking). */
12
+ startSkill(skill: string): void;
13
+ /** End a skill invocation. */
14
+ endSkill(skill: string): void;
15
+ /** Add an audit entry and return its ID. */
16
+ addAudit(tool: string, decision: EnforcementDecision, opts?: {
17
+ skill?: string;
18
+ costCents?: number;
19
+ proofDigestB64?: string;
20
+ }): string;
21
+ /** Prune timestamps outside all rate limit windows (memory hygiene). */
22
+ prune(maxAgeMs: number, now?: number): void;
23
+ /** Snapshot the current state (read-only copy). */
24
+ snapshot(): Readonly<ExecutionContextState>;
25
+ /** Get audit log entries. */
26
+ getAuditLog(opts?: {
27
+ offset?: number;
28
+ limit?: number;
29
+ }): readonly AuditEntry[];
30
+ /** Get a specific audit entry by ID. */
31
+ getAuditEntry(id: string): AuditEntry | undefined;
32
+ /** Total audit entries. */
33
+ get auditCount(): number;
34
+ }
35
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEzF;;;GAGG;AACH,qBAAa,gBAAgB;;gBAIf,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAkBpD,oCAAoC;IACpC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAYhG,2DAA2D;IAC3D,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI/B,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,4CAA4C;IAC5C,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GACrE,MAAM;IAeT,wEAAwE;IACxE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ3C,mDAAmD;IACnD,QAAQ,IAAI,QAAQ,CAAC,qBAAqB,CAAC;IAI3C,6BAA6B;IAC7B,WAAW,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,UAAU,EAAE;IAO9E,wCAAwC;IACxC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIjD,2BAA2B;IAC3B,IAAI,UAAU,IAAI,MAAM,CAEvB;CACF"}
@@ -0,0 +1,90 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+ /**
4
+ * Mutable execution context tracking cumulative state for policy enforcement.
5
+ * One instance per agent session.
6
+ */
7
+ export class ExecutionContext {
8
+ #state;
9
+ #nextAuditId;
10
+ constructor(initial) {
11
+ this.#state = {
12
+ totalSpendCents: initial?.totalSpendCents ?? 0,
13
+ toolCallCounts: { ...initial?.toolCallCounts },
14
+ toolCallTimestamps: {},
15
+ globalCallTimestamps: [...(initial?.globalCallTimestamps ?? [])],
16
+ activeSkills: { ...initial?.activeSkills },
17
+ auditLog: [...(initial?.auditLog ?? [])],
18
+ };
19
+ // Deep-copy timestamp arrays
20
+ if (initial?.toolCallTimestamps) {
21
+ for (const [k, v] of Object.entries(initial.toolCallTimestamps)) {
22
+ this.#state.toolCallTimestamps[k] = [...v];
23
+ }
24
+ }
25
+ this.#nextAuditId = this.#state.auditLog.length + 1;
26
+ }
27
+ /** Record a completed tool call. */
28
+ recordCall(tool, skill, costCents, timestamp) {
29
+ const now = timestamp ?? Date.now();
30
+ this.#state.totalSpendCents += costCents;
31
+ this.#state.toolCallCounts[tool] = (this.#state.toolCallCounts[tool] ?? 0) + 1;
32
+ if (!this.#state.toolCallTimestamps[tool]) {
33
+ this.#state.toolCallTimestamps[tool] = [];
34
+ }
35
+ this.#state.toolCallTimestamps[tool].push(now);
36
+ this.#state.globalCallTimestamps.push(now);
37
+ }
38
+ /** Start a skill invocation (for concurrency tracking). */
39
+ startSkill(skill) {
40
+ this.#state.activeSkills[skill] = (this.#state.activeSkills[skill] ?? 0) + 1;
41
+ }
42
+ /** End a skill invocation. */
43
+ endSkill(skill) {
44
+ const current = this.#state.activeSkills[skill] ?? 0;
45
+ this.#state.activeSkills[skill] = Math.max(0, current - 1);
46
+ }
47
+ /** Add an audit entry and return its ID. */
48
+ addAudit(tool, decision, opts) {
49
+ const id = `audit-${this.#nextAuditId++}`;
50
+ const entry = {
51
+ id,
52
+ timestamp: Date.now(),
53
+ tool,
54
+ skill: opts?.skill,
55
+ decision,
56
+ costCents: opts?.costCents,
57
+ proofDigestB64: opts?.proofDigestB64,
58
+ };
59
+ this.#state.auditLog.push(entry);
60
+ return id;
61
+ }
62
+ /** Prune timestamps outside all rate limit windows (memory hygiene). */
63
+ prune(maxAgeMs, now) {
64
+ const cutoff = (now ?? Date.now()) - maxAgeMs;
65
+ this.#state.globalCallTimestamps = this.#state.globalCallTimestamps.filter((t) => t > cutoff);
66
+ for (const [tool, ts] of Object.entries(this.#state.toolCallTimestamps)) {
67
+ this.#state.toolCallTimestamps[tool] = ts.filter((t) => t > cutoff);
68
+ }
69
+ }
70
+ /** Snapshot the current state (read-only copy). */
71
+ snapshot() {
72
+ return structuredClone(this.#state);
73
+ }
74
+ /** Get audit log entries. */
75
+ getAuditLog(opts) {
76
+ const log = this.#state.auditLog;
77
+ const offset = opts?.offset ?? 0;
78
+ const limit = opts?.limit ?? log.length;
79
+ return log.slice(offset, offset + limit);
80
+ }
81
+ /** Get a specific audit entry by ID. */
82
+ getAuditEntry(id) {
83
+ return this.#state.auditLog.find((e) => e.id === id);
84
+ }
85
+ /** Total audit entries. */
86
+ get auditCount() {
87
+ return this.#state.auditLog.length;
88
+ }
89
+ }
90
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { AgentPolicy, EnforcementDecision, EnforcementRequest, ExecutionContextState } from "./types.js";
2
+ /**
3
+ * Stateless policy enforcement. Checks a proposed tool call against
4
+ * the committed policy and current execution context.
5
+ *
6
+ * Check order: blocked → allowed → time windows → global rate limit →
7
+ * global spend → per-tool constraints → argument restrictions → skill constraints.
8
+ */
9
+ export declare function enforcePolicy(policy: AgentPolicy, context: ExecutionContextState, request: EnforcementRequest): EnforcementDecision;
10
+ //# sourceMappingURL=enforcer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enforcer.d.ts","sourceRoot":"","sources":["../src/enforcer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,mBAAmB,CA0JrB"}
@@ -0,0 +1,216 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+ /**
4
+ * Stateless policy enforcement. Checks a proposed tool call against
5
+ * the committed policy and current execution context.
6
+ *
7
+ * Check order: blocked → allowed → time windows → global rate limit →
8
+ * global spend → per-tool constraints → argument restrictions → skill constraints.
9
+ */
10
+ export function enforcePolicy(policy, context, request) {
11
+ const now = request.timestamp ?? Date.now();
12
+ const gc = policy.globalConstraints;
13
+ // 1. Blocked tools (always reject)
14
+ if (gc.blockedTools && gc.blockedTools.includes(request.tool)) {
15
+ return {
16
+ allowed: false,
17
+ reason: `Tool "${request.tool}" is blocked by policy`,
18
+ constraint: "globalConstraints.blockedTools",
19
+ };
20
+ }
21
+ // 2. Allowed tools (default-deny: if no allowedTools specified, deny all)
22
+ if (!gc.allowedTools || gc.allowedTools.length === 0) {
23
+ return {
24
+ allowed: false,
25
+ reason: `Tool "${request.tool}" is not allowed — no tools enabled`,
26
+ constraint: "globalConstraints.allowedTools",
27
+ };
28
+ }
29
+ if (!gc.allowedTools.includes(request.tool)) {
30
+ return {
31
+ allowed: false,
32
+ reason: `Tool "${request.tool}" is not in the allowed tools list`,
33
+ constraint: "globalConstraints.allowedTools",
34
+ };
35
+ }
36
+ // 3. Time windows
37
+ if (gc.allowedTimeWindows && gc.allowedTimeWindows.length > 0) {
38
+ const inWindow = gc.allowedTimeWindows.some((tw) => isInTimeWindow(now, tw));
39
+ if (!inWindow) {
40
+ return {
41
+ allowed: false,
42
+ reason: "Current time is outside all allowed time windows",
43
+ constraint: "globalConstraints.allowedTimeWindows",
44
+ };
45
+ }
46
+ }
47
+ // 4. Global rate limit
48
+ if (gc.rateLimit) {
49
+ const windowStart = now - gc.rateLimit.windowMs;
50
+ const recentCalls = context.globalCallTimestamps.filter((t) => t > windowStart).length;
51
+ if (recentCalls >= gc.rateLimit.maxCalls) {
52
+ return {
53
+ allowed: false,
54
+ reason: `Global rate limit exceeded: ${recentCalls}/${gc.rateLimit.maxCalls} calls in ${gc.rateLimit.windowMs}ms window`,
55
+ constraint: "globalConstraints.rateLimit",
56
+ };
57
+ }
58
+ }
59
+ // 5. Global spend
60
+ if (gc.maxSpendCents !== undefined) {
61
+ const projectedSpend = context.totalSpendCents + (request.estimatedCostCents ?? 0);
62
+ if (projectedSpend > gc.maxSpendCents) {
63
+ return {
64
+ allowed: false,
65
+ reason: `Would exceed global spend limit: ${projectedSpend}c > ${gc.maxSpendCents}c`,
66
+ constraint: "globalConstraints.maxSpendCents",
67
+ };
68
+ }
69
+ }
70
+ // 6. Per-tool constraints
71
+ const tc = policy.toolConstraints?.[request.tool];
72
+ if (tc) {
73
+ // Per-tool rate limit
74
+ if (tc.rateLimit) {
75
+ const toolTimestamps = context.toolCallTimestamps[request.tool] ?? [];
76
+ const windowStart = now - tc.rateLimit.windowMs;
77
+ const recentCalls = toolTimestamps.filter((t) => t > windowStart).length;
78
+ if (recentCalls >= tc.rateLimit.maxCalls) {
79
+ return {
80
+ allowed: false,
81
+ reason: `Rate limit for "${request.tool}": ${recentCalls}/${tc.rateLimit.maxCalls} calls in ${tc.rateLimit.windowMs}ms`,
82
+ constraint: `toolConstraints.${request.tool}.rateLimit`,
83
+ };
84
+ }
85
+ }
86
+ // Per-call spend cap
87
+ if (tc.maxSpendPerCallCents !== undefined && request.estimatedCostCents !== undefined) {
88
+ if (request.estimatedCostCents > tc.maxSpendPerCallCents) {
89
+ return {
90
+ allowed: false,
91
+ reason: `Tool "${request.tool}" call cost ${request.estimatedCostCents}c exceeds per-call limit of ${tc.maxSpendPerCallCents}c`,
92
+ constraint: `toolConstraints.${request.tool}.maxSpendPerCallCents`,
93
+ };
94
+ }
95
+ }
96
+ // Argument restrictions
97
+ if (tc.argumentRestrictions) {
98
+ const argCheck = checkArgumentRestrictions(request.tool, request.arguments, tc.argumentRestrictions);
99
+ if (!argCheck.allowed)
100
+ return argCheck;
101
+ }
102
+ }
103
+ // 7. Skill constraints
104
+ if (request.skill) {
105
+ const skill = policy.skills[request.skill];
106
+ if (skill?.constraints) {
107
+ const sc = skill.constraints;
108
+ // Require approval
109
+ if (sc.requireApproval) {
110
+ return {
111
+ allowed: false,
112
+ reason: `Skill "${request.skill}" requires human approval`,
113
+ constraint: `skills.${request.skill}.constraints.requireApproval`,
114
+ };
115
+ }
116
+ // Max concurrent
117
+ if (sc.maxConcurrent !== undefined) {
118
+ const active = context.activeSkills[request.skill] ?? 0;
119
+ if (active >= sc.maxConcurrent) {
120
+ return {
121
+ allowed: false,
122
+ reason: `Skill "${request.skill}" at max concurrency: ${active}/${sc.maxConcurrent}`,
123
+ constraint: `skills.${request.skill}.constraints.maxConcurrent`,
124
+ };
125
+ }
126
+ }
127
+ // Skill rate limit
128
+ if (sc.rateLimit) {
129
+ // Use global timestamps filtered to this skill's tools as a proxy
130
+ // (ExecutionContext tracks per-tool, so sum up the skill's tools)
131
+ const windowStart = now - sc.rateLimit.windowMs;
132
+ let skillCalls = 0;
133
+ for (const toolName of skill.tools) {
134
+ const ts = context.toolCallTimestamps[toolName] ?? [];
135
+ skillCalls += ts.filter((t) => t > windowStart).length;
136
+ }
137
+ if (skillCalls >= sc.rateLimit.maxCalls) {
138
+ return {
139
+ allowed: false,
140
+ reason: `Skill "${request.skill}" rate limit exceeded: ${skillCalls}/${sc.rateLimit.maxCalls}`,
141
+ constraint: `skills.${request.skill}.constraints.rateLimit`,
142
+ };
143
+ }
144
+ }
145
+ }
146
+ }
147
+ return { allowed: true };
148
+ }
149
+ function isInTimeWindow(now, tw) {
150
+ const d = new Date(now);
151
+ const day = d.getUTCDay();
152
+ if (tw.daysOfWeek && tw.daysOfWeek.length > 0 && !tw.daysOfWeek.includes(day)) {
153
+ return false;
154
+ }
155
+ const nowMinutes = d.getUTCHours() * 60 + d.getUTCMinutes();
156
+ const startMinutes = parseTimeToMinutes(tw.startUtc);
157
+ const endMinutes = parseTimeToMinutes(tw.endUtc);
158
+ if (startMinutes <= endMinutes) {
159
+ return nowMinutes >= startMinutes && nowMinutes < endMinutes;
160
+ }
161
+ // Wraps midnight
162
+ return nowMinutes >= startMinutes || nowMinutes < endMinutes;
163
+ }
164
+ function parseTimeToMinutes(time) {
165
+ const parts = time.split(":");
166
+ return Number(parts[0]) * 60 + Number(parts[1]);
167
+ }
168
+ function checkArgumentRestrictions(tool, args, restrictions) {
169
+ for (const [argName, restriction] of Object.entries(restrictions)) {
170
+ const value = args[argName];
171
+ if (value === undefined)
172
+ continue;
173
+ if (restriction.allowedValues && !restriction.allowedValues.includes(value)) {
174
+ return {
175
+ allowed: false,
176
+ reason: `Argument "${argName}" value not in allowed values for tool "${tool}"`,
177
+ constraint: `toolConstraints.${tool}.argumentRestrictions.${argName}.allowedValues`,
178
+ };
179
+ }
180
+ if (restriction.blockedValues && restriction.blockedValues.includes(value)) {
181
+ return {
182
+ allowed: false,
183
+ reason: `Argument "${argName}" value is blocked for tool "${tool}"`,
184
+ constraint: `toolConstraints.${tool}.argumentRestrictions.${argName}.blockedValues`,
185
+ };
186
+ }
187
+ if (typeof value === "number") {
188
+ if (restriction.max !== undefined && value > restriction.max) {
189
+ return {
190
+ allowed: false,
191
+ reason: `Argument "${argName}" value ${value} exceeds max ${restriction.max} for tool "${tool}"`,
192
+ constraint: `toolConstraints.${tool}.argumentRestrictions.${argName}.max`,
193
+ };
194
+ }
195
+ if (restriction.min !== undefined && value < restriction.min) {
196
+ return {
197
+ allowed: false,
198
+ reason: `Argument "${argName}" value ${value} below min ${restriction.min} for tool "${tool}"`,
199
+ constraint: `toolConstraints.${tool}.argumentRestrictions.${argName}.min`,
200
+ };
201
+ }
202
+ }
203
+ if (typeof value === "string" && restriction.pattern) {
204
+ const re = new RegExp(restriction.pattern);
205
+ if (!re.test(value)) {
206
+ return {
207
+ allowed: false,
208
+ reason: `Argument "${argName}" does not match pattern /${restriction.pattern}/ for tool "${tool}"`,
209
+ constraint: `toolConstraints.${tool}.argumentRestrictions.${argName}.pattern`,
210
+ };
211
+ }
212
+ }
213
+ }
214
+ return { allowed: true };
215
+ }
216
+ //# sourceMappingURL=enforcer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enforcer.js","sourceRoot":"","sources":["../src/enforcer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { EnforcementDecision } from "./types.js";
2
+ export declare class PolicyViolationError extends Error {
3
+ readonly decision: EnforcementDecision & {
4
+ allowed: false;
5
+ };
6
+ readonly tool: string;
7
+ readonly skill: string | undefined;
8
+ constructor(decision: EnforcementDecision & {
9
+ allowed: false;
10
+ }, tool: string, skill?: string);
11
+ }
12
+ export declare class PolicyCommitmentError extends Error {
13
+ constructor(message: string);
14
+ }
15
+ export declare class PolicyValidationError extends Error {
16
+ readonly issues: string[];
17
+ constructor(issues: string[]);
18
+ }
19
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAgB,QAAQ,EAAE,mBAAmB,GAAG;QAAE,OAAO,EAAE,KAAK,CAAA;KAAE,CAAC;IACnE,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;gBAGxC,QAAQ,EAAE,mBAAmB,GAAG;QAAE,OAAO,EAAE,KAAK,CAAA;KAAE,EAClD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM;CAQjB;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAgB,MAAM,EAAE,MAAM,EAAE,CAAC;gBAErB,MAAM,EAAE,MAAM,EAAE;CAK7B"}
package/dist/errors.js ADDED
@@ -0,0 +1,29 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+ export class PolicyViolationError extends Error {
4
+ decision;
5
+ tool;
6
+ skill;
7
+ constructor(decision, tool, skill) {
8
+ super(`Policy violation on tool "${tool}": ${decision.reason}`);
9
+ this.name = "PolicyViolationError";
10
+ this.decision = decision;
11
+ this.tool = tool;
12
+ this.skill = skill;
13
+ }
14
+ }
15
+ export class PolicyCommitmentError extends Error {
16
+ constructor(message) {
17
+ super(message);
18
+ this.name = "PolicyCommitmentError";
19
+ }
20
+ }
21
+ export class PolicyValidationError extends Error {
22
+ issues;
23
+ constructor(issues) {
24
+ super(`Invalid policy: ${issues.join("; ")}`);
25
+ this.name = "PolicyValidationError";
26
+ this.issues = issues;
27
+ }
28
+ }
29
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,mCAAmC;AAInC,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7B,QAAQ,CAA2C;IACnD,IAAI,CAAS;IACb,KAAK,CAAqB;IAE1C,YACE,QAAkD,EAClD,IAAY,EACZ,KAAc;QAEd,KAAK,CAAC,6BAA6B,IAAI,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9B,MAAM,CAAW;IAEjC,YAAY,MAAgB;QAC1B,KAAK,CAAC,mBAAmB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ export type { AgentPolicy, GlobalConstraints, RateLimit, TimeWindow, SkillDefinition, SkillConstraints, ToolConstraints, ArgumentRestriction, EnforcementDecision, EnforcementRequest, ExecutionContextState, AuditEntry, AgentInstance, PolicyCommitment, } from "./types.js";
2
+ export { enforcePolicy } from "./enforcer.js";
3
+ export { ExecutionContext } from "./context.js";
4
+ export { commitPolicy, hashPolicy } from "./commitment.js";
5
+ export { validatePolicy } from "./schema.js";
6
+ export { PolicyViolationError, PolicyCommitmentError, PolicyValidationError, } from "./errors.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,aAAa,EACb,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+ // Enforcement
4
+ export { enforcePolicy } from "./enforcer.js";
5
+ // Context
6
+ export { ExecutionContext } from "./context.js";
7
+ // Commitment
8
+ export { commitPolicy, hashPolicy } from "./commitment.js";
9
+ // Validation
10
+ export { validatePolicy } from "./schema.js";
11
+ // Errors
12
+ export { PolicyViolationError, PolicyCommitmentError, PolicyValidationError, } from "./errors.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,mCAAmC;AAoBnC,cAAc;AACd,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,UAAU;AACV,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,aAAa;AACb,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE3D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,SAAS;AACT,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { AgentPolicy } from "./types.js";
2
+ /**
3
+ * Validate an AgentPolicy at runtime. Throws PolicyValidationError if invalid.
4
+ */
5
+ export declare function validatePolicy(obj: unknown): asserts obj is AgentPolicy;
6
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,WAAW,CA6CvE"}
package/dist/schema.js ADDED
@@ -0,0 +1,103 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+ import { PolicyValidationError } from "./errors.js";
4
+ /**
5
+ * Validate an AgentPolicy at runtime. Throws PolicyValidationError if invalid.
6
+ */
7
+ export function validatePolicy(obj) {
8
+ const issues = [];
9
+ if (typeof obj !== "object" || obj === null) {
10
+ throw new PolicyValidationError(["Policy must be an object"]);
11
+ }
12
+ const p = obj;
13
+ if (p["version"] !== "occ/policy/1" && p["version"] !== "occ/policy/1") {
14
+ issues.push('version must be "occ/policy/1" or "occ/policy/1"');
15
+ }
16
+ if (typeof p["name"] !== "string" || p["name"].length === 0) {
17
+ issues.push("name must be a non-empty string");
18
+ }
19
+ if (typeof p["createdAt"] !== "number") {
20
+ issues.push("createdAt must be a number (Unix ms)");
21
+ }
22
+ if (typeof p["globalConstraints"] !== "object" || p["globalConstraints"] === null) {
23
+ issues.push("globalConstraints must be an object");
24
+ }
25
+ else {
26
+ validateGlobalConstraints(p["globalConstraints"], issues);
27
+ }
28
+ if (typeof p["skills"] !== "object" || p["skills"] === null) {
29
+ issues.push("skills must be an object");
30
+ }
31
+ else {
32
+ const skills = p["skills"];
33
+ for (const [key, skill] of Object.entries(skills)) {
34
+ validateSkill(key, skill, issues);
35
+ }
36
+ }
37
+ if (p["toolConstraints"] !== undefined) {
38
+ if (typeof p["toolConstraints"] !== "object" || p["toolConstraints"] === null) {
39
+ issues.push("toolConstraints must be an object if provided");
40
+ }
41
+ }
42
+ if (issues.length > 0) {
43
+ throw new PolicyValidationError(issues);
44
+ }
45
+ }
46
+ function validateGlobalConstraints(gc, issues) {
47
+ if (gc["maxSpendCents"] !== undefined && typeof gc["maxSpendCents"] !== "number") {
48
+ issues.push("globalConstraints.maxSpendCents must be a number");
49
+ }
50
+ if (gc["rateLimit"] !== undefined) {
51
+ validateRateLimit(gc["rateLimit"], "globalConstraints.rateLimit", issues);
52
+ }
53
+ if (gc["allowedTools"] !== undefined && !Array.isArray(gc["allowedTools"])) {
54
+ issues.push("globalConstraints.allowedTools must be an array");
55
+ }
56
+ if (gc["blockedTools"] !== undefined && !Array.isArray(gc["blockedTools"])) {
57
+ issues.push("globalConstraints.blockedTools must be an array");
58
+ }
59
+ if (gc["allowedTimeWindows"] !== undefined) {
60
+ if (!Array.isArray(gc["allowedTimeWindows"])) {
61
+ issues.push("globalConstraints.allowedTimeWindows must be an array");
62
+ }
63
+ else {
64
+ for (const tw of gc["allowedTimeWindows"]) {
65
+ if (typeof tw !== "object" || tw === null) {
66
+ issues.push("Each time window must be an object");
67
+ }
68
+ else {
69
+ const w = tw;
70
+ if (typeof w["startUtc"] !== "string")
71
+ issues.push("TimeWindow.startUtc must be a string");
72
+ if (typeof w["endUtc"] !== "string")
73
+ issues.push("TimeWindow.endUtc must be a string");
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ function validateSkill(key, skill, issues) {
80
+ if (typeof skill !== "object" || skill === null) {
81
+ issues.push(`skills.${key} must be an object`);
82
+ return;
83
+ }
84
+ const s = skill;
85
+ if (typeof s["name"] !== "string") {
86
+ issues.push(`skills.${key}.name must be a string`);
87
+ }
88
+ if (!Array.isArray(s["tools"])) {
89
+ issues.push(`skills.${key}.tools must be an array`);
90
+ }
91
+ }
92
+ function validateRateLimit(rl, path, issues) {
93
+ if (typeof rl !== "object" || rl === null) {
94
+ issues.push(`${path} must be an object`);
95
+ return;
96
+ }
97
+ const r = rl;
98
+ if (typeof r["maxCalls"] !== "number")
99
+ issues.push(`${path}.maxCalls must be a number`);
100
+ if (typeof r["windowMs"] !== "number")
101
+ issues.push(`${path}.windowMs must be a number`);
102
+ }
103
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import type { OCCProof } from "occproof";
2
+ /** Top-level agent policy document. Committed to OCC before agent runs. */
3
+ export interface AgentPolicy {
4
+ version: "occ/policy/1" | "occ/policy/1";
5
+ name: string;
6
+ description?: string | undefined;
7
+ createdAt: number;
8
+ /** Global constraints that apply to ALL tool calls. */
9
+ globalConstraints: GlobalConstraints;
10
+ /** Named skills — groups of tools with skill-level constraints. */
11
+ skills: Record<string, SkillDefinition>;
12
+ /** Per-tool overrides. */
13
+ toolConstraints?: Record<string, ToolConstraints> | undefined;
14
+ }
15
+ /** Constraints that apply across all tools/skills. */
16
+ export interface GlobalConstraints {
17
+ /** Max total spend (cumulative, in cents to avoid float issues). */
18
+ maxSpendCents?: number | undefined;
19
+ /** Max tool calls per time window. */
20
+ rateLimit?: RateLimit | undefined;
21
+ /** Time windows when agent is allowed to operate (UTC). */
22
+ allowedTimeWindows?: TimeWindow[] | undefined;
23
+ /** If set, only these tools are permitted (allowlist). */
24
+ allowedTools?: string[] | undefined;
25
+ /** These tools are never permitted (blocklist, overrides allowedTools). */
26
+ blockedTools?: string[] | undefined;
27
+ }
28
+ export interface RateLimit {
29
+ maxCalls: number;
30
+ windowMs: number;
31
+ }
32
+ export interface TimeWindow {
33
+ /** Day-of-week filter (0=Sun). Empty/undefined = every day. */
34
+ daysOfWeek?: number[] | undefined;
35
+ /** Start time "HH:MM" in UTC. */
36
+ startUtc: string;
37
+ /** End time "HH:MM" in UTC. */
38
+ endUtc: string;
39
+ }
40
+ /** A skill groups related tool calls with skill-level constraints. */
41
+ export interface SkillDefinition {
42
+ name: string;
43
+ /** Ordered list of tool names this skill orchestrates. */
44
+ tools: string[];
45
+ constraints?: SkillConstraints | undefined;
46
+ }
47
+ export interface SkillConstraints {
48
+ /** Per-invocation spend limit for this skill (cents). */
49
+ maxSpendPerInvocationCents?: number | undefined;
50
+ /** Max concurrent executions of this skill. */
51
+ maxConcurrent?: number | undefined;
52
+ /** Skill-specific rate limit. */
53
+ rateLimit?: RateLimit | undefined;
54
+ /** If true, requires human approval before execution. */
55
+ requireApproval?: boolean | undefined;
56
+ }
57
+ /** Per-tool constraint overrides. */
58
+ export interface ToolConstraints {
59
+ rateLimit?: RateLimit | undefined;
60
+ /** Per-call spend cap for this tool (cents). */
61
+ maxSpendPerCallCents?: number | undefined;
62
+ /** Specific argument value restrictions. */
63
+ argumentRestrictions?: Record<string, ArgumentRestriction> | undefined;
64
+ }
65
+ export interface ArgumentRestriction {
66
+ allowedValues?: unknown[] | undefined;
67
+ blockedValues?: unknown[] | undefined;
68
+ max?: number | undefined;
69
+ min?: number | undefined;
70
+ /** Regex pattern the string value must match. */
71
+ pattern?: string | undefined;
72
+ }
73
+ export type EnforcementDecision = {
74
+ allowed: true;
75
+ } | {
76
+ allowed: false;
77
+ reason: string;
78
+ constraint: string;
79
+ };
80
+ export interface EnforcementRequest {
81
+ tool: string;
82
+ skill?: string | undefined;
83
+ arguments: Record<string, unknown>;
84
+ estimatedCostCents?: number | undefined;
85
+ timestamp?: number | undefined;
86
+ }
87
+ export interface ExecutionContextState {
88
+ totalSpendCents: number;
89
+ toolCallCounts: Record<string, number>;
90
+ toolCallTimestamps: Record<string, number[]>;
91
+ globalCallTimestamps: number[];
92
+ activeSkills: Record<string, number>;
93
+ auditLog: AuditEntry[];
94
+ }
95
+ export interface AuditEntry {
96
+ id: string;
97
+ timestamp: number;
98
+ tool: string;
99
+ skill?: string | undefined;
100
+ decision: EnforcementDecision;
101
+ costCents?: number | undefined;
102
+ proofDigestB64?: string | undefined;
103
+ }
104
+ /** An agent instance with its own policy and execution context. */
105
+ export interface AgentInstance {
106
+ id: string;
107
+ name: string;
108
+ policy: AgentPolicy;
109
+ createdAt: number;
110
+ status: "active" | "paused";
111
+ }
112
+ export interface PolicyCommitment {
113
+ policy: AgentPolicy;
114
+ policyDigestB64: string;
115
+ occProof: OCCProof;
116
+ committedAt: number;
117
+ }
118
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,mCAAmC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@occ-core/policy-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Policy definition and enforcement for OCC Agent",
5
+ "author": "Mike Argento",
6
+ "license": "Apache-2.0",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "typecheck": "tsc --noEmit"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/mikeargento/occ",
27
+ "directory": "packages/policy-sdk"
28
+ },
29
+ "keywords": [
30
+ "occ",
31
+ "policy",
32
+ "enforcement",
33
+ "occ-agent",
34
+ "agent",
35
+ "constraints"
36
+ ],
37
+ "dependencies": {
38
+ "@noble/hashes": "^1.4.0",
39
+ "occproof": "^1.0.2"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^20.0.0",
43
+ "typescript": "^5.4.0"
44
+ },
45
+ "engines": {
46
+ "node": ">=20.0.0"
47
+ }
48
+ }