@guilz-dev/belay 0.3.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/README.md +7 -1
  2. package/dist/adapters/cursor/runtime-entry.js +1 -0
  3. package/dist/adapters/layouts/scope.js +3 -2
  4. package/dist/adapters/shared/gate-runtime.d.ts +12 -16
  5. package/dist/adapters/shared/gate-runtime.js +499 -43
  6. package/dist/bundle/claude-runtime.mjs +8004 -2676
  7. package/dist/bundle/codex-runtime.mjs +8021 -2683
  8. package/dist/bundle/cursor-runtime.mjs +7993 -2667
  9. package/dist/cli.js +180 -6
  10. package/dist/commands/approve.d.ts +1 -0
  11. package/dist/commands/approve.js +45 -26
  12. package/dist/commands/classify-for-report.js +1 -1
  13. package/dist/commands/config.d.ts +8 -0
  14. package/dist/commands/config.js +264 -58
  15. package/dist/commands/doctor.js +47 -2
  16. package/dist/commands/explain.js +17 -2
  17. package/dist/commands/harvest.d.ts +29 -0
  18. package/dist/commands/harvest.js +72 -0
  19. package/dist/commands/judge.d.ts +11 -1
  20. package/dist/commands/judge.js +24 -4
  21. package/dist/commands/metrics.js +34 -2
  22. package/dist/commands/quality.d.ts +38 -0
  23. package/dist/commands/quality.js +105 -0
  24. package/dist/commands/session.d.ts +20 -0
  25. package/dist/commands/session.js +51 -0
  26. package/dist/commands/simulate.d.ts +1 -0
  27. package/dist/commands/simulate.js +7 -2
  28. package/dist/commands/standing-allow.d.ts +10 -0
  29. package/dist/commands/standing-allow.js +26 -0
  30. package/dist/commands/tui.d.ts +48 -0
  31. package/dist/commands/tui.js +150 -0
  32. package/dist/config-io.js +59 -17
  33. package/dist/conformance/guarantee-posture.d.ts +21 -0
  34. package/dist/conformance/guarantee-posture.js +46 -0
  35. package/dist/conformance/guarantee-table.d.ts +1 -0
  36. package/dist/conformance/guarantee-table.js +14 -9
  37. package/dist/core/approval-replay-cli.d.ts +7 -0
  38. package/dist/core/approval-replay-cli.js +36 -0
  39. package/dist/core/approval-replay.d.ts +45 -0
  40. package/dist/core/approval-replay.js +141 -0
  41. package/dist/core/approval-service.d.ts +15 -0
  42. package/dist/core/approval-service.js +53 -4
  43. package/dist/core/approval.d.ts +26 -3
  44. package/dist/core/approval.js +61 -7
  45. package/dist/core/audit-analysis.d.ts +7 -1
  46. package/dist/core/audit-analysis.js +111 -0
  47. package/dist/core/audit-metrics.d.ts +7 -0
  48. package/dist/core/audit-metrics.js +24 -4
  49. package/dist/core/audit-query.d.ts +1 -0
  50. package/dist/core/audit-query.js +3 -0
  51. package/dist/core/audit-replay-context.d.ts +35 -0
  52. package/dist/core/audit-replay-context.js +88 -0
  53. package/dist/core/audit-types.d.ts +24 -1
  54. package/dist/core/audit-types.js +1 -1
  55. package/dist/core/capability/approval-state-mutation.d.ts +13 -0
  56. package/dist/core/capability/approval-state-mutation.js +92 -0
  57. package/dist/core/capability/approval-v3.d.ts +15 -0
  58. package/dist/core/capability/approval-v3.js +74 -0
  59. package/dist/core/capability/attestation.d.ts +13 -0
  60. package/dist/core/capability/attestation.js +55 -0
  61. package/dist/core/capability/boundary-attestation-sign.d.ts +21 -0
  62. package/dist/core/capability/boundary-attestation-sign.js +84 -0
  63. package/dist/core/capability/boundary-driver-container.d.ts +7 -0
  64. package/dist/core/capability/boundary-driver-container.js +122 -0
  65. package/dist/core/capability/boundary-driver.d.ts +29 -0
  66. package/dist/core/capability/boundary-driver.js +43 -0
  67. package/dist/core/capability/boundary-egress.d.ts +21 -0
  68. package/dist/core/capability/boundary-egress.js +109 -0
  69. package/dist/core/capability/boundary-grant-materialize.d.ts +13 -0
  70. package/dist/core/capability/boundary-grant-materialize.js +78 -0
  71. package/dist/core/capability/boundary-profile.d.ts +15 -0
  72. package/dist/core/capability/boundary-profile.js +25 -0
  73. package/dist/core/capability/boundary-run.d.ts +23 -0
  74. package/dist/core/capability/boundary-run.js +23 -0
  75. package/dist/core/capability/boundary-session.d.ts +57 -0
  76. package/dist/core/capability/boundary-session.js +129 -0
  77. package/dist/core/capability/capability-request-hash.d.ts +2 -0
  78. package/dist/core/capability/capability-request-hash.js +8 -0
  79. package/dist/core/capability/gate-latency-ratchet.d.ts +7 -0
  80. package/dist/core/capability/gate-latency-ratchet.js +18 -0
  81. package/dist/core/capability/gate-policy-shadow.d.ts +25 -0
  82. package/dist/core/capability/gate-policy-shadow.js +108 -0
  83. package/dist/core/capability/gate-shadow-audit.d.ts +1 -0
  84. package/dist/core/capability/gate-shadow-audit.js +1 -0
  85. package/dist/core/capability/gate-shadow-ratchet.d.ts +14 -0
  86. package/dist/core/capability/gate-shadow-ratchet.js +81 -0
  87. package/dist/core/capability/grant-lease.d.ts +9 -0
  88. package/dist/core/capability/grant-lease.js +46 -0
  89. package/dist/core/capability/grant-loader.d.ts +12 -0
  90. package/dist/core/capability/grant-loader.js +23 -0
  91. package/dist/core/capability/grant-match.d.ts +6 -0
  92. package/dist/core/capability/grant-match.js +93 -0
  93. package/dist/core/capability/grant.d.ts +16 -0
  94. package/dist/core/capability/grant.js +16 -0
  95. package/dist/core/capability/index.d.ts +10 -1
  96. package/dist/core/capability/index.js +8 -0
  97. package/dist/core/capability/limits.d.ts +7 -0
  98. package/dist/core/capability/limits.js +55 -0
  99. package/dist/core/capability/paths.d.ts +2 -2
  100. package/dist/core/capability/paths.js +9 -9
  101. package/dist/core/capability/policy-bridge.d.ts +18 -0
  102. package/dist/core/capability/policy-bridge.js +51 -0
  103. package/dist/core/capability/policy-engine.d.ts +70 -0
  104. package/dist/core/capability/policy-engine.js +476 -0
  105. package/dist/core/capability/policy-types.d.ts +20 -0
  106. package/dist/core/capability/policy-types.js +1 -0
  107. package/dist/core/capability/request.d.ts +45 -0
  108. package/dist/core/capability/request.js +1 -0
  109. package/dist/core/capability/resolver.d.ts +4 -0
  110. package/dist/core/capability/resolver.js +4 -0
  111. package/dist/core/capability/trusted-workspace-roots.d.ts +25 -0
  112. package/dist/core/capability/trusted-workspace-roots.js +149 -0
  113. package/dist/core/capability/types.d.ts +11 -1
  114. package/dist/core/capability-approval.d.ts +2 -1
  115. package/dist/core/capability-approval.js +100 -2
  116. package/dist/core/classify-subagent.d.ts +2 -1
  117. package/dist/core/classify-subagent.js +40 -22
  118. package/dist/core/classify-tool.js +157 -64
  119. package/dist/core/config.d.ts +32 -3
  120. package/dist/core/config.js +105 -3
  121. package/dist/core/gate-contract.d.ts +3 -0
  122. package/dist/core/gate-contract.js +3 -0
  123. package/dist/core/gate-engine.js +12 -7
  124. package/dist/core/harvest.d.ts +53 -0
  125. package/dist/core/harvest.js +276 -0
  126. package/dist/core/index.d.ts +9 -3
  127. package/dist/core/index.js +6 -2
  128. package/dist/core/judge-doctor.d.ts +3 -0
  129. package/dist/core/judge-doctor.js +90 -11
  130. package/dist/core/judge-fallback-hints.d.ts +13 -0
  131. package/dist/core/judge-fallback-hints.js +108 -0
  132. package/dist/core/path-utils.d.ts +12 -0
  133. package/dist/core/path-utils.js +60 -7
  134. package/dist/core/reclassify.d.ts +3 -0
  135. package/dist/core/reclassify.js +44 -14
  136. package/dist/core/recovery/capability.d.ts +3 -0
  137. package/dist/core/recovery/capability.js +22 -0
  138. package/dist/core/recovery/fail-closed.d.ts +6 -0
  139. package/dist/core/recovery/fail-closed.js +25 -0
  140. package/dist/core/recovery/index.d.ts +3 -0
  141. package/dist/core/recovery/index.js +2 -0
  142. package/dist/core/recovery/types.d.ts +20 -0
  143. package/dist/core/recovery/types.js +1 -0
  144. package/dist/core/replay-scrub.d.ts +9 -0
  145. package/dist/core/replay-scrub.js +43 -0
  146. package/dist/core/shell-tokenizer.d.ts +2 -0
  147. package/dist/core/shell-tokenizer.js +82 -23
  148. package/dist/core/standing-allow.d.ts +50 -0
  149. package/dist/core/standing-allow.js +178 -0
  150. package/dist/core/transactional/diff-evaluator.js +4 -1
  151. package/dist/core/transactional/eligibility.js +4 -0
  152. package/dist/core/transactional/git-worktree.d.ts +10 -3
  153. package/dist/core/transactional/git-worktree.js +81 -11
  154. package/dist/core/transactional/reasons.d.ts +1 -0
  155. package/dist/core/transactional/reasons.js +4 -0
  156. package/dist/core/transactional/runner.js +22 -6
  157. package/dist/core/transactional/types.d.ts +4 -0
  158. package/dist/core/types.d.ts +36 -3
  159. package/dist/core/verdict/adapter.d.ts +3 -4
  160. package/dist/core/verdict/adapter.js +19 -6
  161. package/dist/core/verdict/containment.d.ts +4 -3
  162. package/dist/core/verdict/containment.js +17 -12
  163. package/dist/core/verdict/cursor-acp-client.d.ts +67 -0
  164. package/dist/core/verdict/cursor-acp-client.js +345 -0
  165. package/dist/core/verdict/egress-classify.d.ts +2 -2
  166. package/dist/core/verdict/egress-classify.js +2 -2
  167. package/dist/core/verdict/git-classifier.d.ts +26 -0
  168. package/dist/core/verdict/git-classifier.js +533 -0
  169. package/dist/core/verdict/judge-audit.d.ts +1 -0
  170. package/dist/core/verdict/judge-audit.js +33 -1
  171. package/dist/core/verdict/judge-baseline.d.ts +20 -0
  172. package/dist/core/verdict/judge-baseline.js +49 -0
  173. package/dist/core/verdict/judge-broker-service.d.ts +42 -0
  174. package/dist/core/verdict/judge-broker-service.js +291 -0
  175. package/dist/core/verdict/judge-catalog.js +1 -0
  176. package/dist/core/verdict/judge-cli-fingerprint.d.ts +6 -0
  177. package/dist/core/verdict/judge-cli-fingerprint.js +67 -0
  178. package/dist/core/verdict/judge-cli.d.ts +23 -0
  179. package/dist/core/verdict/judge-cli.js +139 -16
  180. package/dist/core/verdict/judge-factory.js +13 -4
  181. package/dist/core/verdict/judge-provider-matrix.d.ts +20 -0
  182. package/dist/core/verdict/judge-provider-matrix.js +66 -0
  183. package/dist/core/verdict/judge-runtime-config.d.ts +44 -0
  184. package/dist/core/verdict/judge-runtime-config.js +96 -0
  185. package/dist/core/verdict/judge-session-broker.d.ts +48 -0
  186. package/dist/core/verdict/judge-session-broker.js +200 -0
  187. package/dist/core/verdict/judge-session-guard.d.ts +27 -0
  188. package/dist/core/verdict/judge-session-guard.js +91 -0
  189. package/dist/core/verdict/judge-session-kill-switch.d.ts +11 -0
  190. package/dist/core/verdict/judge-session-kill-switch.js +43 -0
  191. package/dist/core/verdict/judge-session-mutex.d.ts +9 -0
  192. package/dist/core/verdict/judge-session-mutex.js +23 -0
  193. package/dist/core/verdict/judge-shadow.d.ts +24 -0
  194. package/dist/core/verdict/judge-shadow.js +116 -0
  195. package/dist/core/verdict/judge-transport.d.ts +44 -0
  196. package/dist/core/verdict/judge-transport.js +268 -0
  197. package/dist/core/verdict/judge.d.ts +14 -14
  198. package/dist/core/verdict/judge.js +5 -67
  199. package/dist/core/verdict/launcher-resolve.d.ts +2 -0
  200. package/dist/core/verdict/launcher-resolve.js +16 -0
  201. package/dist/core/verdict/parser.js +6 -1
  202. package/dist/core/verdict/prescan.d.ts +15 -0
  203. package/dist/core/verdict/prescan.js +68 -0
  204. package/dist/core/verdict/shell-policy.d.ts +25 -0
  205. package/dist/core/verdict/shell-policy.js +40 -0
  206. package/dist/core/verdict/shell-semantics.d.ts +24 -0
  207. package/dist/core/verdict/shell-semantics.js +225 -0
  208. package/dist/core/verdict/types.d.ts +26 -1
  209. package/dist/core/verdict/verdict.js +300 -179
  210. package/dist/corpus/adversarial-probe.d.ts +86 -0
  211. package/dist/corpus/adversarial-probe.js +220 -0
  212. package/dist/corpus/evaluate.d.ts +45 -12
  213. package/dist/corpus/evaluate.js +61 -8
  214. package/dist/corpus/gate-latency-budget.d.ts +39 -0
  215. package/dist/corpus/gate-latency-budget.js +33 -0
  216. package/dist/corpus/gates.d.ts +35 -0
  217. package/dist/corpus/gates.js +81 -0
  218. package/dist/corpus/judge-accuracy.d.ts +8 -0
  219. package/dist/corpus/judge-accuracy.js +39 -0
  220. package/dist/corpus/must-allow-commands.d.ts +5 -0
  221. package/dist/corpus/must-allow-commands.js +13 -0
  222. package/dist/corpus/mutators.d.ts +28 -0
  223. package/dist/corpus/mutators.js +162 -0
  224. package/dist/corpus/ratchet.d.ts +42 -0
  225. package/dist/corpus/ratchet.js +116 -0
  226. package/dist/corpus/runtime-match.d.ts +19 -0
  227. package/dist/corpus/runtime-match.js +43 -0
  228. package/dist/corpus/standing-allow-catalog.generated.d.ts +13 -0
  229. package/dist/corpus/standing-allow-catalog.generated.js +99 -0
  230. package/dist/corpus/types.d.ts +47 -0
  231. package/dist/corpus/types.js +157 -0
  232. package/dist/installer.js +4 -1
  233. package/dist/judge-broker-daemon.d.ts +1 -0
  234. package/dist/judge-broker-daemon.js +137 -0
  235. package/dist/services/sandbox-service.d.ts +5 -0
  236. package/dist/services/sandbox-service.js +30 -2
  237. package/dist/types.d.ts +2 -2
  238. package/dist/version.d.ts +1 -1
  239. package/dist/version.js +1 -1
  240. package/package.json +7 -3
  241. package/skills/belay/SKILL.md +7 -1
  242. package/skills/belay/belay-approve.md +17 -0
@@ -0,0 +1,93 @@
1
+ import { canonicalPath } from '../path-utils.js';
2
+ import { isGrantScopeTooBroad } from './grant.js';
3
+ function principalMatches(grant, request) {
4
+ if (grant.repoRoot !== request.repoRoot) {
5
+ return false;
6
+ }
7
+ if (request.adapter !== undefined && grant.adapter !== request.adapter) {
8
+ return false;
9
+ }
10
+ if (request.sessionHash !== undefined && grant.sessionHash !== request.sessionHash) {
11
+ return false;
12
+ }
13
+ if (grant.adapter !== undefined && grant.adapter !== request.adapter) {
14
+ return false;
15
+ }
16
+ if (grant.sessionHash !== undefined && grant.sessionHash !== request.sessionHash) {
17
+ return false;
18
+ }
19
+ return true;
20
+ }
21
+ function networkResourceMatches(grant, request) {
22
+ if (grant.host !== request.host) {
23
+ return false;
24
+ }
25
+ if (grant.port !== undefined && grant.port !== request.port) {
26
+ return false;
27
+ }
28
+ if (grant.protocol !== undefined &&
29
+ grant.protocol !== 'unknown' &&
30
+ request.protocol !== undefined &&
31
+ request.protocol !== 'unknown' &&
32
+ grant.protocol !== request.protocol) {
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+ function grantTargetsResource(grant, request) {
38
+ if (grant.action !== request.action) {
39
+ if (grant.action === 'indeterminate') {
40
+ return request.action === 'indeterminate';
41
+ }
42
+ return false;
43
+ }
44
+ if (grant.inputFingerprint && grant.inputFingerprint !== request.context.inputFingerprint) {
45
+ return false;
46
+ }
47
+ if (grant.resource.kind === 'path' && request.resource.kind === 'path') {
48
+ return canonicalPath(grant.resource.path) === canonicalPath(request.resource.path);
49
+ }
50
+ if (grant.resource.kind === 'network' && request.resource.kind === 'network') {
51
+ return networkResourceMatches(grant.resource, request.resource);
52
+ }
53
+ if (grant.resource.kind === 'executable' && request.resource.kind === 'executable') {
54
+ return grant.resource.command === request.resource.command;
55
+ }
56
+ if (grant.resource.kind === 'git-ref' && request.resource.kind === 'git-ref') {
57
+ return grant.resource.ref === request.resource.ref;
58
+ }
59
+ if (grant.resource.kind === 'unknown') {
60
+ if (grant.action === 'network.connect' && request.resource.kind === 'network') {
61
+ return true;
62
+ }
63
+ if (grant.action === 'fs.write' && request.resource.kind === 'path') {
64
+ return true;
65
+ }
66
+ if (grant.action === 'indeterminate') {
67
+ return request.action === 'indeterminate';
68
+ }
69
+ }
70
+ return grant.resource.kind === request.resource.kind;
71
+ }
72
+ export function grantTargetsRequest(grant, request) {
73
+ if (grant.usesRemaining <= 0) {
74
+ return false;
75
+ }
76
+ if (!principalMatches(grant.principal, request.principal)) {
77
+ return false;
78
+ }
79
+ return grantTargetsResource(grant, request);
80
+ }
81
+ /** Repo-scoped target match for forged broad-grant detection (principal may be incomplete). */
82
+ export function broadGrantTargetsRequest(grant, request) {
83
+ if (grant.principal.repoRoot !== request.principal.repoRoot) {
84
+ return false;
85
+ }
86
+ return grantTargetsResource(grant, request);
87
+ }
88
+ export function grantMatchesRequest(grant, request) {
89
+ if (isGrantScopeTooBroad(grant)) {
90
+ return false;
91
+ }
92
+ return grantTargetsRequest(grant, request);
93
+ }
@@ -0,0 +1,16 @@
1
+ import type { CapabilityAction, CapabilityPrincipal, CapabilityResource } from './request.js';
2
+ export declare const CAPABILITY_GRANT_VERSION: 1;
3
+ export interface CapabilityGrantV1 {
4
+ version: typeof CAPABILITY_GRANT_VERSION;
5
+ grantId: string;
6
+ principal: CapabilityPrincipal;
7
+ action: CapabilityAction;
8
+ resource: CapabilityResource;
9
+ inputFingerprint?: string;
10
+ issuedAt: string;
11
+ expiresAt: string;
12
+ maxUses: number;
13
+ usesRemaining: number;
14
+ issuer: string;
15
+ }
16
+ export declare function isGrantScopeTooBroad(grant: CapabilityGrantV1): boolean;
@@ -0,0 +1,16 @@
1
+ export const CAPABILITY_GRANT_VERSION = 1;
2
+ export function isGrantScopeTooBroad(grant) {
3
+ if (grant.action === 'network.connect' && grant.resource.kind === 'unknown') {
4
+ return true;
5
+ }
6
+ if (grant.resource.kind === 'network' && grant.resource.host === '*') {
7
+ return true;
8
+ }
9
+ if (grant.action === 'fs.write' && grant.resource.kind === 'unknown') {
10
+ return true;
11
+ }
12
+ if (grant.action === 'indeterminate') {
13
+ return true;
14
+ }
15
+ return false;
16
+ }
@@ -1,5 +1,14 @@
1
1
  export { addPathToAllowlist, allPathsAllowlisted, fsScopeAllowlistPath, isPathAllowlisted, loadFsScopeAllowlist, loadFsScopeAllowlistSync, saveFsScopeAllowlist, } from './allowlist.js';
2
+ export { BOUNDARY_ATTESTATION_VERSION, type BoundaryAttestation, type BoundaryDriverId, isAttestationFresh, } from './attestation.js';
3
+ export { BOUNDARY_PROFILE_L1_ATTESTED, BOUNDARY_PROFILE_L3_L4_ONLY, BOUNDARY_PROFILE_L3_POLICY, boundaryVerifiedAllowEnabled, isAttestedBoundary, resolveBoundaryProfile, } from './boundary-profile.js';
2
4
  export { evaluateL1FullStatus, hasSandboxRuntime, isCapabilityBrokerDemotionActive, isSandboxBrokerEnabled, } from './broker.js';
5
+ export { CAPABILITY_GRANT_VERSION, type CapabilityGrantV1, isGrantScopeTooBroad, } from './grant.js';
6
+ export { checkGatedActionLimits, MAX_SHELL_COMMAND_BYTES, MAX_TOOL_PAYLOAD_BYTES, } from './limits.js';
3
7
  export { collectOutsideRepoPaths, collectOutsideRepoPathsFromToolPayload } from './paths.js';
8
+ export { type CapabilityAuthorizationMetadata, type PolicyLegacyReasonHints, policyDecisionToLegacyReason, policyReasonToLegacyReason, singleCapabilityMetadata, } from './policy-bridge.js';
9
+ export { buildFileMutationCapabilityRequest, buildShellCapabilityRequest, createTypeScriptPolicyEngine, evaluateFileMutationPolicy, evaluateShellPolicy, evaluateSubagentPolicy, type FileMutationCapabilityAnalysis, getDefaultPolicyEngine, policyDecisionRequiresAsk, type ShellCapabilityAnalysis, type SubagentCapabilityAnalysis, } from './policy-engine.js';
10
+ export type { AuthorizationContext, PolicyDecision, PolicyEngine, PolicyOutcome, } from './policy-types.js';
4
11
  export { FS_SCOPE_REASONS, shouldSkipBrokerApprovedOnce, shouldSkipBrokerApprovedRecord, } from './reasons.js';
5
- export type { CapabilityApprovalScope, FsScopeAllowlistEntry, FsScopeAllowlistFile, } from './types.js';
12
+ export { CAPABILITY_REQUEST_VERSION, type CapabilityAction, type CapabilityEvidence, type CapabilityEvidenceLevel, type CapabilityHookKind, type CapabilityPrincipal, type CapabilityRequestContext, type CapabilityRequestV1, type CapabilityResource, } from './request.js';
13
+ export { addTrustedWorkspaceRoot, isBroadTrustedWorkspaceRoot, isHighStakesTrustedWorkspaceRoot, isPathWithinTrustedWorkspaceRoots, loadTrustedWorkspaceRoots, loadTrustedWorkspaceRootsSync, normalizeTrustedWorkspaceRootPath, saveTrustedWorkspaceRoots, trustedWorkspaceRootsPath, validateTrustedWorkspaceRootCandidate, } from './trusted-workspace-roots.js';
14
+ export type { CapabilityApprovalScope, FsScopeAllowlistEntry, FsScopeAllowlistFile, TrustedWorkspaceRootEntry, TrustedWorkspaceRootsFile, } from './types.js';
@@ -1,4 +1,12 @@
1
1
  export { addPathToAllowlist, allPathsAllowlisted, fsScopeAllowlistPath, isPathAllowlisted, loadFsScopeAllowlist, loadFsScopeAllowlistSync, saveFsScopeAllowlist, } from './allowlist.js';
2
+ export { BOUNDARY_ATTESTATION_VERSION, isAttestationFresh, } from './attestation.js';
3
+ export { BOUNDARY_PROFILE_L1_ATTESTED, BOUNDARY_PROFILE_L3_L4_ONLY, BOUNDARY_PROFILE_L3_POLICY, boundaryVerifiedAllowEnabled, isAttestedBoundary, resolveBoundaryProfile, } from './boundary-profile.js';
2
4
  export { evaluateL1FullStatus, hasSandboxRuntime, isCapabilityBrokerDemotionActive, isSandboxBrokerEnabled, } from './broker.js';
5
+ export { CAPABILITY_GRANT_VERSION, isGrantScopeTooBroad, } from './grant.js';
6
+ export { checkGatedActionLimits, MAX_SHELL_COMMAND_BYTES, MAX_TOOL_PAYLOAD_BYTES, } from './limits.js';
3
7
  export { collectOutsideRepoPaths, collectOutsideRepoPathsFromToolPayload } from './paths.js';
8
+ export { policyDecisionToLegacyReason, policyReasonToLegacyReason, singleCapabilityMetadata, } from './policy-bridge.js';
9
+ export { buildFileMutationCapabilityRequest, buildShellCapabilityRequest, createTypeScriptPolicyEngine, evaluateFileMutationPolicy, evaluateShellPolicy, evaluateSubagentPolicy, getDefaultPolicyEngine, policyDecisionRequiresAsk, } from './policy-engine.js';
4
10
  export { FS_SCOPE_REASONS, shouldSkipBrokerApprovedOnce, shouldSkipBrokerApprovedRecord, } from './reasons.js';
11
+ export { CAPABILITY_REQUEST_VERSION, } from './request.js';
12
+ export { addTrustedWorkspaceRoot, isBroadTrustedWorkspaceRoot, isHighStakesTrustedWorkspaceRoot, isPathWithinTrustedWorkspaceRoots, loadTrustedWorkspaceRoots, loadTrustedWorkspaceRootsSync, normalizeTrustedWorkspaceRootPath, saveTrustedWorkspaceRoots, trustedWorkspaceRootsPath, validateTrustedWorkspaceRootCandidate, } from './trusted-workspace-roots.js';
@@ -0,0 +1,7 @@
1
+ import type { GatedAction } from '../gate-contract.js';
2
+ import type { ClassifyResult } from '../types.js';
3
+ import { BOUNDARY_PROFILE_L3_POLICY } from './boundary-profile.js';
4
+ export { BOUNDARY_PROFILE_L3_POLICY };
5
+ export declare const MAX_SHELL_COMMAND_BYTES: number;
6
+ export declare const MAX_TOOL_PAYLOAD_BYTES: number;
7
+ export declare function checkGatedActionLimits(action: GatedAction): ClassifyResult | null;
@@ -0,0 +1,55 @@
1
+ import { BOUNDARY_PROFILE_L3_POLICY } from './boundary-profile.js';
2
+ export { BOUNDARY_PROFILE_L3_POLICY };
3
+ export const MAX_SHELL_COMMAND_BYTES = 64 * 1024;
4
+ export const MAX_TOOL_PAYLOAD_BYTES = 1024 * 1024;
5
+ function limitExceededResult(reason, summary) {
6
+ return {
7
+ verdict: 'deny_pending_approval',
8
+ reason,
9
+ fingerprint: `limit:${reason}`,
10
+ summary,
11
+ assessment: {
12
+ reversibility: 'irreversible',
13
+ external: false,
14
+ blastRadius: 'gate input budget',
15
+ confidence: 1,
16
+ signals: [reason, 'analysis_budget_exceeded'],
17
+ },
18
+ boundaryProfile: BOUNDARY_PROFILE_L3_POLICY,
19
+ };
20
+ }
21
+ function shellCommandFromAction(action) {
22
+ if (action.command?.trim()) {
23
+ return action.command.trim();
24
+ }
25
+ const payload = action.payload;
26
+ if (!payload) {
27
+ return '';
28
+ }
29
+ const direct = payload.command;
30
+ if (typeof direct === 'string' && direct.trim()) {
31
+ return direct.trim();
32
+ }
33
+ const toolInput = payload.tool_input;
34
+ if (toolInput && typeof toolInput === 'object') {
35
+ const command = toolInput.command;
36
+ if (typeof command === 'string' && command.trim()) {
37
+ return command.trim();
38
+ }
39
+ }
40
+ return '';
41
+ }
42
+ export function checkGatedActionLimits(action) {
43
+ if (action.kind === 'shell') {
44
+ const command = shellCommandFromAction(action);
45
+ if (Buffer.byteLength(command, 'utf8') > MAX_SHELL_COMMAND_BYTES) {
46
+ return limitExceededResult('input_too_large', command.slice(0, 120));
47
+ }
48
+ return null;
49
+ }
50
+ const payloadBytes = Buffer.byteLength(JSON.stringify(action.payload ?? {}), 'utf8');
51
+ if (payloadBytes > MAX_TOOL_PAYLOAD_BYTES) {
52
+ return limitExceededResult('input_too_large', action.toolName ?? action.kind);
53
+ }
54
+ return null;
55
+ }
@@ -1,2 +1,2 @@
1
- export declare function collectOutsideRepoPaths(command: string, cwd: string, repoRoot: string): string[];
2
- export declare function collectOutsideRepoPathsFromToolPayload(payload: Record<string, unknown>, cwd: string, repoRoot: string): string[];
1
+ export declare function collectOutsideRepoPaths(command: string, cwd: string, repoRoot: string, trustedWorkspaceRoots?: string[]): string[];
2
+ export declare function collectOutsideRepoPathsFromToolPayload(payload: Record<string, unknown>, cwd: string, repoRoot: string, trustedWorkspaceRoots?: string[]): string[];
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path';
2
- import { relativeWithinRepo, resolveMutationTarget } from '../path-utils.js';
2
+ import { resolveMutationTarget, resolveWorkspaceRootMatch } from '../path-utils.js';
3
3
  import { extractRedirectTargets, tokenizeShell } from '../shell-tokenizer.js';
4
4
  function applyPatchTargets(patch) {
5
5
  const targets = [];
@@ -42,25 +42,25 @@ function extractToolPatch(payload) {
42
42
  }
43
43
  return null;
44
44
  }
45
- function addOutsideRepoPath(paths, token, cwd, repoRoot) {
45
+ function addOutsideRepoPath(paths, token, cwd, repoRoot, trustedWorkspaceRoots = []) {
46
46
  const resolved = resolveMutationTarget(token, cwd);
47
- if (resolved && relativeWithinRepo(repoRoot, resolved) === null) {
47
+ if (resolved && resolveWorkspaceRootMatch(repoRoot, trustedWorkspaceRoots, resolved) === null) {
48
48
  paths.add(resolved);
49
49
  }
50
50
  }
51
- export function collectOutsideRepoPaths(command, cwd, repoRoot) {
51
+ export function collectOutsideRepoPaths(command, cwd, repoRoot, trustedWorkspaceRoots = []) {
52
52
  const tokens = tokenizeShell(command);
53
53
  const redirects = extractRedirectTargets(tokens);
54
54
  const paths = new Set();
55
55
  for (const token of tokens.slice(1)) {
56
- addOutsideRepoPath(paths, token, cwd, repoRoot);
56
+ addOutsideRepoPath(paths, token, cwd, repoRoot, trustedWorkspaceRoots);
57
57
  }
58
58
  for (const redirect of redirects) {
59
- addOutsideRepoPath(paths, redirect, cwd, repoRoot);
59
+ addOutsideRepoPath(paths, redirect, cwd, repoRoot, trustedWorkspaceRoots);
60
60
  }
61
61
  return [...paths];
62
62
  }
63
- export function collectOutsideRepoPathsFromToolPayload(payload, cwd, repoRoot) {
63
+ export function collectOutsideRepoPathsFromToolPayload(payload, cwd, repoRoot, trustedWorkspaceRoots = []) {
64
64
  const toolKind = String(payload.tool_name ?? '')
65
65
  .trim()
66
66
  .toLowerCase();
@@ -68,7 +68,7 @@ export function collectOutsideRepoPathsFromToolPayload(payload, cwd, repoRoot) {
68
68
  const filePath = extractToolFilePath(payload);
69
69
  if (filePath) {
70
70
  const resolved = path.isAbsolute(filePath) ? filePath : path.resolve(cwd, filePath);
71
- if (relativeWithinRepo(repoRoot, resolved) === null) {
71
+ if (resolveWorkspaceRootMatch(repoRoot, trustedWorkspaceRoots, resolved) === null) {
72
72
  paths.add(resolved);
73
73
  }
74
74
  return [...paths];
@@ -78,7 +78,7 @@ export function collectOutsideRepoPathsFromToolPayload(payload, cwd, repoRoot) {
78
78
  if (patch) {
79
79
  for (const target of applyPatchTargets(patch)) {
80
80
  const resolved = path.isAbsolute(target) ? target : path.resolve(cwd, target);
81
- if (relativeWithinRepo(repoRoot, resolved) === null) {
81
+ if (resolveWorkspaceRootMatch(repoRoot, trustedWorkspaceRoots, resolved) === null) {
82
82
  paths.add(resolved);
83
83
  }
84
84
  }
@@ -0,0 +1,18 @@
1
+ import type { PolicyDecision } from './policy-types.js';
2
+ import type { CapabilityRequestV1 } from './request.js';
3
+ export interface CapabilityAuthorizationMetadata {
4
+ capabilityRequests: CapabilityRequestV1[];
5
+ authorizationDecision: PolicyDecision;
6
+ }
7
+ export interface PolicyLegacyReasonHints {
8
+ outsideMutation?: boolean;
9
+ effect?: 'read_only' | 'local_mutation' | 'remote_mutation' | 'unknown';
10
+ }
11
+ export declare function singleCapabilityMetadata(request: CapabilityRequestV1, decision: PolicyDecision): CapabilityAuthorizationMetadata;
12
+ /**
13
+ * Maps a PolicyDecision to hook-facing legacy reason strings.
14
+ * Pass hints when the shell segment context is known (outside-repo mutation, etc.).
15
+ */
16
+ export declare function policyDecisionToLegacyReason(decision: PolicyDecision, hints?: PolicyLegacyReasonHints): string;
17
+ /** @deprecated Use policyDecisionToLegacyReason for shell segments that need outside-repo hints. */
18
+ export declare function policyReasonToLegacyReason(decision: PolicyDecision): string;
@@ -0,0 +1,51 @@
1
+ export function singleCapabilityMetadata(request, decision) {
2
+ return {
3
+ capabilityRequests: [request],
4
+ authorizationDecision: decision,
5
+ };
6
+ }
7
+ /**
8
+ * Maps a PolicyDecision to hook-facing legacy reason strings.
9
+ * Pass hints when the shell segment context is known (outside-repo mutation, etc.).
10
+ */
11
+ export function policyDecisionToLegacyReason(decision, hints = {}) {
12
+ if (decision.reason === 'outside_repo_mutation') {
13
+ return 'outside_repo_mutation';
14
+ }
15
+ if (decision.reason === 'external_effect' || decision.reason === 'network_connect') {
16
+ return 'external_effect';
17
+ }
18
+ if (decision.reason === 'high_stakes_path' || decision.reason === 'secret_path') {
19
+ return 'tier1_catastrophic';
20
+ }
21
+ if (decision.reason === 'indeterminate_effect') {
22
+ return 'unknown_local_effect';
23
+ }
24
+ if (decision.reason === 'opaque_execution') {
25
+ return 'opaque_execution';
26
+ }
27
+ if (decision.reason === 'control_plane_mutation') {
28
+ return 'control_plane_mutation';
29
+ }
30
+ if (decision.reason === 'policy_default') {
31
+ if (decision.signals.includes('outside_repo_path') ||
32
+ decision.signals.includes('outside_repo_mutation')) {
33
+ return 'outside_repo_mutation';
34
+ }
35
+ if (hints.outsideMutation && hints.effect !== 'read_only') {
36
+ return 'outside_repo_mutation';
37
+ }
38
+ return 'unknown_local_effect';
39
+ }
40
+ if (decision.reason === 'subagent_review') {
41
+ return 'subagent_review';
42
+ }
43
+ if (decision.outcome === 'deny') {
44
+ return decision.reason;
45
+ }
46
+ return decision.reason;
47
+ }
48
+ /** @deprecated Use policyDecisionToLegacyReason for shell segments that need outside-repo hints. */
49
+ export function policyReasonToLegacyReason(decision) {
50
+ return policyDecisionToLegacyReason(decision);
51
+ }
@@ -0,0 +1,70 @@
1
+ import type { BelayConfigV4 } from '../config.js';
2
+ import type { VerdictEffect, VerdictLocation, VerdictOpacity } from '../verdict/types.js';
3
+ import type { AuthorizationContext, PolicyDecision, PolicyEngine } from './policy-types.js';
4
+ import { type CapabilityHookKind, type CapabilityRequestV1 } from './request.js';
5
+ export type PolicyAuthExtras = Pick<AuthorizationContext, 'grants' | 'attestation'> & {
6
+ egressProxyActive?: boolean;
7
+ sensitivePaths?: string[];
8
+ };
9
+ export interface ShellCapabilityAnalysis {
10
+ command: string;
11
+ hookKind: CapabilityHookKind;
12
+ segmentHead: string;
13
+ effect: VerdictEffect;
14
+ location: VerdictLocation;
15
+ opacity: VerdictOpacity;
16
+ egressClass?: 'read' | 'destructive' | 'ambiguous';
17
+ pathArgs: string[];
18
+ /** Verdict-resolved canonical paths aligned with pathArgs (preferred for policy resource selection). */
19
+ resolvedPathTargets?: string[];
20
+ signals: string[];
21
+ cwd: string;
22
+ repoRoot: string;
23
+ inputFingerprint: string;
24
+ adapter?: string;
25
+ trustedWorkspaceRoots?: string[];
26
+ sensitivePaths?: string[];
27
+ protectedArtifactRoots?: string[];
28
+ }
29
+ export interface FileMutationCapabilityAnalysis {
30
+ hookKind: CapabilityHookKind;
31
+ toolKind: string;
32
+ filePath: string;
33
+ resolvedPath: string;
34
+ repoRoot: string;
35
+ cwd: string;
36
+ inputFingerprint: string;
37
+ signals: string[];
38
+ isDelete: boolean;
39
+ locationLabel: 'repo_local' | 'outside_repo' | 'sensitive_path' | 'control_plane';
40
+ trustedWorkspaceRoots?: string[];
41
+ sensitivePaths?: string[];
42
+ adapter?: string;
43
+ }
44
+ export interface SubagentCapabilityAnalysis {
45
+ subagentType: string;
46
+ summary: string;
47
+ repoRoot: string;
48
+ cwd: string;
49
+ inputFingerprint: string;
50
+ signals: string[];
51
+ adapter?: string;
52
+ }
53
+ export declare function buildSubagentCapabilityRequest(analysis: SubagentCapabilityAnalysis): CapabilityRequestV1;
54
+ export declare function evaluateSubagentPolicy(analysis: SubagentCapabilityAnalysis, config: BelayConfigV4, auth?: PolicyAuthExtras): {
55
+ request: CapabilityRequestV1;
56
+ decision: PolicyDecision;
57
+ };
58
+ export declare function buildShellCapabilityRequest(analysis: ShellCapabilityAnalysis): CapabilityRequestV1;
59
+ export declare function buildFileMutationCapabilityRequest(analysis: FileMutationCapabilityAnalysis): CapabilityRequestV1;
60
+ export declare function createTypeScriptPolicyEngine(): PolicyEngine;
61
+ export declare function getDefaultPolicyEngine(): PolicyEngine;
62
+ export declare function policyDecisionRequiresAsk(decision: PolicyDecision): boolean;
63
+ export declare function evaluateShellPolicy(analysis: ShellCapabilityAnalysis, config: BelayConfigV4, auth?: PolicyAuthExtras): {
64
+ request: CapabilityRequestV1;
65
+ decision: PolicyDecision;
66
+ };
67
+ export declare function evaluateFileMutationPolicy(analysis: FileMutationCapabilityAnalysis, config: BelayConfigV4, auth?: PolicyAuthExtras): {
68
+ request: CapabilityRequestV1;
69
+ decision: PolicyDecision;
70
+ };