@guilz-dev/belay 0.6.0 → 0.8.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 (183) hide show
  1. package/README.md +39 -20
  2. package/dist/adapters/claude/runtime-entry.js +54 -25
  3. package/dist/adapters/shared/gate-runtime.d.ts +7 -0
  4. package/dist/adapters/shared/gate-runtime.js +443 -225
  5. package/dist/bundle/claude-runtime.mjs +13027 -7271
  6. package/dist/bundle/codex-runtime.mjs +12700 -6977
  7. package/dist/bundle/cursor-runtime.mjs +12695 -6977
  8. package/dist/cli.js +37 -1
  9. package/dist/commands/approve.js +34 -10
  10. package/dist/commands/doctor.js +58 -0
  11. package/dist/commands/dogfood.js +1 -1
  12. package/dist/commands/explain.js +2 -2
  13. package/dist/commands/harvest.d.ts +0 -1
  14. package/dist/commands/harvest.js +1 -4
  15. package/dist/commands/metrics.js +6 -0
  16. package/dist/commands/quality.js +1 -3
  17. package/dist/commands/recovery-checkpoints.d.ts +164 -0
  18. package/dist/commands/recovery-checkpoints.js +347 -0
  19. package/dist/commands/revoke.js +19 -7
  20. package/dist/commands/status.js +7 -0
  21. package/dist/config-io.js +49 -18
  22. package/dist/conformance/guarantee-table.js +137 -9
  23. package/dist/conformance/types.d.ts +2 -0
  24. package/dist/core/approval-replay.d.ts +1 -1
  25. package/dist/core/approval-replay.js +4 -1
  26. package/dist/core/approval-service.d.ts +6 -1
  27. package/dist/core/approval-service.js +86 -27
  28. package/dist/core/approval.d.ts +2 -0
  29. package/dist/core/approval.js +6 -3
  30. package/dist/core/audit-metrics.d.ts +1 -0
  31. package/dist/core/audit-metrics.js +12 -4
  32. package/dist/core/audit-types.d.ts +16 -0
  33. package/dist/core/capability/approval-state-mutation.d.ts +19 -0
  34. package/dist/core/capability/approval-state-mutation.js +76 -3
  35. package/dist/core/capability/approval-v3.d.ts +18 -1
  36. package/dist/core/capability/approval-v3.js +63 -23
  37. package/dist/core/capability/attestation.d.ts +3 -0
  38. package/dist/core/capability/attestation.js +7 -0
  39. package/dist/core/capability/boundary-driver-container.d.ts +12 -0
  40. package/dist/core/capability/boundary-driver-container.js +101 -34
  41. package/dist/core/capability/boundary-driver.js +1 -0
  42. package/dist/core/capability/boundary-grant-materialize.d.ts +1 -0
  43. package/dist/core/capability/boundary-grant-materialize.js +15 -0
  44. package/dist/core/capability/boundary-run.d.ts +25 -0
  45. package/dist/core/capability/boundary-run.js +37 -9
  46. package/dist/core/capability/boundary-session.d.ts +4 -0
  47. package/dist/core/capability/boundary-session.js +9 -0
  48. package/dist/core/capability/boundary-workspace-mount.d.ts +5 -0
  49. package/dist/core/capability/boundary-workspace-mount.js +68 -0
  50. package/dist/core/capability/gate-policy-shadow.js +23 -1
  51. package/dist/core/capability/grant-consumption.d.ts +4 -0
  52. package/dist/core/capability/grant-consumption.js +11 -0
  53. package/dist/core/capability/grant-lease.d.ts +36 -1
  54. package/dist/core/capability/grant-lease.js +213 -16
  55. package/dist/core/capability/grant-match.js +3 -0
  56. package/dist/core/capability/index.d.ts +2 -2
  57. package/dist/core/capability/index.js +1 -1
  58. package/dist/core/capability/policy-engine.d.ts +38 -1
  59. package/dist/core/capability/policy-engine.js +388 -15
  60. package/dist/core/capability/request.d.ts +12 -0
  61. package/dist/core/capability/resolver.d.ts +0 -1
  62. package/dist/core/capability/resolver.js +0 -1
  63. package/dist/core/config.d.ts +20 -0
  64. package/dist/core/config.js +62 -2
  65. package/dist/core/effect-ir/audit.d.ts +9 -0
  66. package/dist/core/effect-ir/audit.js +87 -0
  67. package/dist/core/effect-ir/build.d.ts +31 -0
  68. package/dist/core/effect-ir/build.js +281 -0
  69. package/dist/core/effect-ir/index.d.ts +13 -0
  70. package/dist/core/effect-ir/index.js +9 -0
  71. package/dist/core/effect-ir/normalize.d.ts +4 -0
  72. package/dist/core/effect-ir/normalize.js +110 -0
  73. package/dist/core/effect-ir/package-exec-eval.d.ts +8 -0
  74. package/dist/core/effect-ir/package-exec-eval.js +152 -0
  75. package/dist/core/effect-ir/package-exec.d.ts +29 -0
  76. package/dist/core/effect-ir/package-exec.js +292 -0
  77. package/dist/core/effect-ir/policy.d.ts +14 -0
  78. package/dist/core/effect-ir/policy.js +164 -0
  79. package/dist/core/effect-ir/shell-build.d.ts +43 -0
  80. package/dist/core/effect-ir/shell-build.js +77 -0
  81. package/dist/core/effect-ir/shell-lower.d.ts +14 -0
  82. package/dist/core/effect-ir/shell-lower.js +1509 -0
  83. package/dist/core/effect-ir/types.d.ts +62 -0
  84. package/dist/core/effect-ir/types.js +1 -0
  85. package/dist/core/egress/allowlist.d.ts +1 -0
  86. package/dist/core/egress/allowlist.js +8 -0
  87. package/dist/core/egress-approval.js +45 -51
  88. package/dist/core/gate-contract.d.ts +2 -0
  89. package/dist/core/gate-contract.js +2 -0
  90. package/dist/core/gate-engine.js +82 -25
  91. package/dist/core/git-resource-identity.d.ts +26 -0
  92. package/dist/core/git-resource-identity.js +284 -0
  93. package/dist/core/harvest.d.ts +3 -7
  94. package/dist/core/harvest.js +4 -27
  95. package/dist/core/index.d.ts +5 -1
  96. package/dist/core/index.js +3 -1
  97. package/dist/core/judge-cloud-consent.js +29 -15
  98. package/dist/core/network-endpoint.d.ts +10 -0
  99. package/dist/core/network-endpoint.js +51 -0
  100. package/dist/core/path-utils.js +42 -23
  101. package/dist/core/process-runner.d.ts +10 -0
  102. package/dist/core/process-runner.js +124 -0
  103. package/dist/core/recover-advice.js +2 -1
  104. package/dist/core/recovery/artifact-store.d.ts +29 -0
  105. package/dist/core/recovery/artifact-store.js +336 -0
  106. package/dist/core/recovery/checkpoint.d.ts +25 -0
  107. package/dist/core/recovery/checkpoint.js +260 -0
  108. package/dist/core/recovery/index.d.ts +3 -1
  109. package/dist/core/recovery/index.js +2 -0
  110. package/dist/core/recovery/operator-guidance.d.ts +7 -0
  111. package/dist/core/recovery/operator-guidance.js +39 -0
  112. package/dist/core/recovery/reconcile.d.ts +3 -0
  113. package/dist/core/recovery/reconcile.js +48 -0
  114. package/dist/core/recovery/resource-identity.d.ts +4 -0
  115. package/dist/core/recovery/resource-identity.js +34 -0
  116. package/dist/core/recovery/restore.d.ts +13 -0
  117. package/dist/core/recovery/restore.js +114 -0
  118. package/dist/core/recovery/snapshot-node.d.ts +27 -0
  119. package/dist/core/recovery/snapshot-node.js +261 -0
  120. package/dist/core/recovery/types.d.ts +85 -1
  121. package/dist/core/shell-substitution.d.ts +1 -0
  122. package/dist/core/shell-substitution.js +61 -0
  123. package/dist/core/standing-allow.d.ts +1 -2
  124. package/dist/core/standing-allow.js +3 -20
  125. package/dist/core/transactional/apply-observed-changes.d.ts +13 -0
  126. package/dist/core/transactional/apply-observed-changes.js +275 -0
  127. package/dist/core/transactional/backend-selector.d.ts +8 -0
  128. package/dist/core/transactional/backend-selector.js +118 -0
  129. package/dist/core/transactional/backend.d.ts +55 -0
  130. package/dist/core/transactional/backend.js +1 -0
  131. package/dist/core/transactional/file-checkpoint-backend.d.ts +3 -0
  132. package/dist/core/transactional/file-checkpoint-backend.js +278 -0
  133. package/dist/core/transactional/file-checkpoint-git.d.ts +11 -0
  134. package/dist/core/transactional/file-checkpoint-git.js +217 -0
  135. package/dist/core/transactional/file-checkpoint-staging.d.ts +13 -0
  136. package/dist/core/transactional/file-checkpoint-staging.js +54 -0
  137. package/dist/core/transactional/file-clone.d.ts +15 -0
  138. package/dist/core/transactional/file-clone.js +139 -0
  139. package/dist/core/transactional/file-tree-path.d.ts +7 -0
  140. package/dist/core/transactional/file-tree-path.js +50 -0
  141. package/dist/core/transactional/file-tree.d.ts +41 -0
  142. package/dist/core/transactional/file-tree.js +186 -0
  143. package/dist/core/transactional/git-worktree-backend.d.ts +2 -0
  144. package/dist/core/transactional/git-worktree-backend.js +50 -0
  145. package/dist/core/transactional/git-worktree.d.ts +9 -11
  146. package/dist/core/transactional/git-worktree.js +24 -119
  147. package/dist/core/transactional/index.d.ts +11 -0
  148. package/dist/core/transactional/index.js +10 -0
  149. package/dist/core/transactional/reasons.js +1 -0
  150. package/dist/core/transactional/runner.js +157 -25
  151. package/dist/core/transactional/snapshot-node.d.ts +26 -0
  152. package/dist/core/transactional/snapshot-node.js +87 -0
  153. package/dist/core/transactional/types.d.ts +17 -1
  154. package/dist/core/types.d.ts +13 -1
  155. package/dist/core/verdict/adapter.js +23 -15
  156. package/dist/core/verdict/containment.js +4 -0
  157. package/dist/core/verdict/egress-classify.d.ts +12 -0
  158. package/dist/core/verdict/egress-classify.js +746 -0
  159. package/dist/core/verdict/git-classifier.d.ts +12 -0
  160. package/dist/core/verdict/git-classifier.js +320 -0
  161. package/dist/core/verdict/launcher-resolve.js +79 -37
  162. package/dist/core/verdict/parser.d.ts +2 -0
  163. package/dist/core/verdict/parser.js +95 -1
  164. package/dist/core/verdict/types.d.ts +6 -2
  165. package/dist/core/verdict/verdict.js +103 -935
  166. package/dist/corpus/must-allow-commands.d.ts +2 -1
  167. package/dist/corpus/must-allow-commands.js +2 -1
  168. package/dist/corpus/runtime-match.d.ts +2 -1
  169. package/dist/corpus/runtime-match.js +2 -1
  170. package/dist/corpus/types.d.ts +2 -2
  171. package/dist/templates.js +7 -2
  172. package/dist/types.d.ts +11 -0
  173. package/dist/version.d.ts +1 -1
  174. package/dist/version.js +1 -1
  175. package/package.json +2 -2
  176. package/skills/belay/SKILL.md +8 -3
  177. package/skills/belay/belay-approve.md +10 -7
  178. package/dist/core/verdict/overrides.d.ts +0 -7
  179. package/dist/core/verdict/overrides.js +0 -37
  180. package/dist/core/verdict/shell-policy.d.ts +0 -25
  181. package/dist/core/verdict/shell-policy.js +0 -40
  182. package/dist/corpus/standing-allow-catalog.generated.d.ts +0 -13
  183. package/dist/corpus/standing-allow-catalog.generated.js +0 -99
@@ -3,6 +3,7 @@ import type { CapabilityGrantV1 } from './capability/grant.js';
3
3
  import type { PolicyDecision } from './capability/policy-types.js';
4
4
  import type { CapabilityRequestV1 } from './capability/request.js';
5
5
  import type { FsScopeAllowlistFile } from './capability/types.js';
6
+ import type { EffectPlan, EffectPlanPolicyProjection } from './effect-ir/types.js';
6
7
  export type BelayMode = 'enforce' | 'audit';
7
8
  export type HookVerdict = 'allow' | 'allow_flagged' | 'deny_pending_approval';
8
9
  export type Reversibility = 'reversible' | 'recoverable_with_cost' | 'irreversible';
@@ -40,6 +41,9 @@ export interface ClassifyResult {
40
41
  axes?: VerdictAxes;
41
42
  capabilityRequests?: CapabilityRequestV1[];
42
43
  authorizationDecision?: PolicyDecision;
44
+ effectPlan?: EffectPlan;
45
+ effectPlanPolicyDecisions?: PolicyDecision[];
46
+ effectPlanProjection?: EffectPlanPolicyProjection;
43
47
  boundaryProfile?: string;
44
48
  }
45
49
  export type UnknownLocalEffectPolicy = 'allow_flagged' | 'deny';
@@ -58,7 +62,9 @@ export interface ConfidenceThresholds {
58
62
  }
59
63
  export interface ClassifierOptions {
60
64
  strictChains?: boolean;
65
+ /** @deprecated Accepted for API compatibility but ignored by shell EffectPlan authorization. */
61
66
  customExternalCommands?: string[];
67
+ /** @deprecated Accepted for API compatibility but ignored by shell EffectPlan authorization. */
62
68
  customAllowCommands?: string[];
63
69
  sensitivePaths?: string[];
64
70
  unknownLocalEffect?: UnknownLocalEffectPolicy;
@@ -116,8 +122,14 @@ export interface ApprovalRecord {
116
122
  capabilityRequests?: CapabilityRequestV1[];
117
123
  /** Approval state v3: hash of capabilityRequests for replay binding. */
118
124
  capabilityRequestHash?: string;
119
- /** Approval state v3: minted grant after human approval. */
125
+ /** Approval state v3: hash of normalized EffectPlan for composite replay binding. */
126
+ effectPlanHash?: string;
127
+ /** Approval state v3: minted grant after human approval (legacy single grant; first of bundle). */
120
128
  grant?: CapabilityGrantV1;
129
+ /** Approval state v3: all grants for composite capability requests (atomic bundle). */
130
+ grants?: CapabilityGrantV1[];
131
+ /** Exact one-to-one grant bundle contract. Missing means legacy fingerprint authorization. */
132
+ grantBundleVersion?: 1;
121
133
  }
122
134
  export interface ApprovalStateFile {
123
135
  version: 1 | 2 | 3;
@@ -1,4 +1,5 @@
1
1
  import { BOUNDARY_PROFILE_L3_L4_ONLY, resolveBoundaryProfile, } from '../capability/boundary-profile.js';
2
+ import { effectPlanAuditFields } from '../effect-ir/audit.js';
2
3
  import { judgeTraceAuditFields } from './judge-audit.js';
3
4
  import { recordJudgeLatency } from './judge-baseline.js';
4
5
  import { verdict } from './verdict.js';
@@ -21,8 +22,6 @@ export function buildVerdictContext(params) {
21
22
  trustedWorkspaceRoots: params.options?.trustedWorkspaceRoots ?? [],
22
23
  sensitivePaths: params.options?.sensitivePaths ?? params.config.classifier.sensitivePaths,
23
24
  protectedArtifactRoots: protectedArtifactRoots.length > 0 ? [...new Set(protectedArtifactRoots)] : undefined,
24
- customAllowCommands: params.options?.customAllowCommands ?? params.config.overrides.allow,
25
- customExternalCommands: params.options?.customExternalCommands ?? params.config.overrides.external,
26
25
  mode: params.config.mode,
27
26
  unknownLocalEffect: params.options?.unknownLocalEffect ?? params.config.policy.unknownLocalEffect,
28
27
  unparseableShell: params.options?.unparseableShell ?? params.config.policy.unparseableShell,
@@ -74,14 +73,15 @@ export function verdictToClassifyResult(result, config, options = {}) {
74
73
  result.location === 'repo_outside' ||
75
74
  result.effect === 'remote_mutation';
76
75
  const legacyReason = mapLegacyReason(result);
77
- const hookVerdict = result.permission === 'ask'
78
- ? 'deny_pending_approval'
79
- : legacyReason === 'command_substitution' ||
80
- legacyReason === 'unknown_local_effect' ||
81
- legacyReason === 'unparseable_shell' ||
82
- result.effect === 'local_mutation'
83
- ? 'allow_flagged'
84
- : 'allow';
76
+ const hookVerdict = result.effectPlanProjection?.hookVerdict ??
77
+ (result.permission === 'ask'
78
+ ? 'deny_pending_approval'
79
+ : legacyReason === 'command_substitution' ||
80
+ legacyReason === 'unknown_local_effect' ||
81
+ legacyReason === 'unparseable_shell' ||
82
+ result.effect === 'local_mutation'
83
+ ? 'allow_flagged'
84
+ : 'allow');
85
85
  const assessment = {
86
86
  reversibility: result.effect === 'read_only'
87
87
  ? 'reversible'
@@ -90,11 +90,11 @@ export function verdictToClassifyResult(result, config, options = {}) {
90
90
  : 'irreversible',
91
91
  external,
92
92
  blastRadius: result.location,
93
- confidence: result.confidence === 'deterministic'
94
- ? 0.95
95
- : result.confidence === 'llm'
96
- ? 0.75
97
- : hookVerdict === 'allow_flagged'
93
+ confidence: hookVerdict === 'allow_flagged'
94
+ ? 0.75
95
+ : result.confidence === 'deterministic'
96
+ ? 0.95
97
+ : result.confidence === 'llm'
98
98
  ? 0.75
99
99
  : 0.7,
100
100
  signals: result.signals,
@@ -120,6 +120,9 @@ export function verdictToClassifyResult(result, config, options = {}) {
120
120
  },
121
121
  capabilityRequests: result.capabilityRequests,
122
122
  authorizationDecision: result.authorizationDecision,
123
+ effectPlan: result.effectPlan,
124
+ effectPlanPolicyDecisions: result.effectPlanPolicyDecisions,
125
+ effectPlanProjection: result.effectPlanProjection,
123
126
  boundaryProfile: options.boundaryProfile ??
124
127
  (config
125
128
  ? resolveBoundaryProfile({ config, attestation: options.attestation })
@@ -138,6 +141,11 @@ export function verdictAuditFields(result) {
138
141
  would: result.permission,
139
142
  by: 'verdict',
140
143
  signals: result.signals,
144
+ ...effectPlanAuditFields(result.effectPlan, {
145
+ capabilityRequests: result.capabilityRequests,
146
+ decisions: result.effectPlanPolicyDecisions,
147
+ authorizationDecision: result.authorizationDecision,
148
+ }),
141
149
  ...judgeTraceAuditFields(result.judgeTrace),
142
150
  };
143
151
  }
@@ -1,4 +1,5 @@
1
1
  import path from 'node:path';
2
+ import { isGitMetadataPath } from '../git-resource-identity.js';
2
3
  import { matchesSensitivePath } from '../glob.js';
3
4
  import { canonicalPath, pathWithinRoot, relativeWithinRepo, resolveMutationTarget, resolveWorkspaceRootMatch, } from '../path-utils.js';
4
5
  import { isOutsideRepoSecretCredentialPath } from './persistent-paths.js';
@@ -36,6 +37,9 @@ export function locationForPath(resolvedPath, repoRoot, trustedWorkspaceRoots =
36
37
  return 'repo_outside';
37
38
  }
38
39
  export function isGitPath(resolvedPath, repoRoot) {
40
+ if (isGitMetadataPath(resolvedPath, repoRoot)) {
41
+ return true;
42
+ }
39
43
  const relative = relativeWithinRepo(repoRoot, resolvedPath);
40
44
  if (!relative) {
41
45
  return false;
@@ -2,6 +2,18 @@
2
2
  * Egress tool classification (SPEC v2.1.3 R33–R34).
3
3
  * destructive → ask | read → allow at egress layer | ambiguous → require_approval via PolicyEngine
4
4
  */
5
+ import type { ShellEffectRequirement } from '../effect-ir/shell-build.js';
5
6
  export type EgressClassification = 'destructive' | 'read' | 'ambiguous';
7
+ export interface DecodeEgressEffectsParams {
8
+ tokens: string[];
9
+ cwd: string;
10
+ segment: string;
11
+ }
6
12
  export declare function isEgressToolHead(head: string): boolean;
7
13
  export declare function classifyEgressTool(head: string, tokens: string[]): EgressClassification | null;
14
+ /**
15
+ * Decode curl/wget/gh grammar into typed effects. This API deliberately has no
16
+ * permission or verdict output; uncertainty is represented by indeterminate
17
+ * requirements alongside every effect that was still recoverable.
18
+ */
19
+ export declare function decodeEgressEffects(params: DecodeEgressEffectsParams): ShellEffectRequirement[] | null;