@orangecheck/agent-core 1.1.0 → 2.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.
package/dist/index.mjs CHANGED
@@ -496,6 +496,25 @@ async function verifyDelegation(input) {
496
496
  const ok = await input.verifyBip322(env.id, env.sig.value, env.principal.address);
497
497
  if (!ok) return err("E_BAD_SIG", "BIP-322 signature did not verify");
498
498
  }
499
+ if (!input.skipRevocationCheck && !input.revocations) {
500
+ return err(
501
+ "E_MALFORMED",
502
+ "verifyDelegation requires `revocations` (fetch kind-30085 by #delegation) or an explicit skipRevocationCheck:true to state that revocation is not being checked"
503
+ );
504
+ }
505
+ if (input.revocations) {
506
+ for (const rev of input.revocations) {
507
+ if (rev.delegation_id !== env.id) continue;
508
+ const rr = await verifyRevocation({
509
+ envelope: rev,
510
+ delegation: env,
511
+ verifyBip322: input.verifyBip322,
512
+ skipSignatureVerification: input.skipSignatureVerification
513
+ });
514
+ if (!rr.ok) continue;
515
+ return err("E_REVOKED", `delegation ${env.id} was revoked by ${rev.id}`);
516
+ }
517
+ }
499
518
  if (!input.skipTemporalCheck) {
500
519
  const now = input.now ?? /* @__PURE__ */ new Date();
501
520
  const issued = new Date(env.issued_at);
@@ -530,6 +549,12 @@ async function verifyAction(input) {
530
549
  scopeMode: input.scopeMode,
531
550
  skipTemporalCheck: true,
532
551
  // action window check dominates
552
+ // Revocation is evaluated ONCE, below, across every link in the chain
553
+ // (root + subdelegations) against the action's effective time — a
554
+ // per-link check here would use the wrong clock and would also
555
+ // double-report. Forward the caller's decision so this inner call does
556
+ // not trip the fail-closed guard.
557
+ skipRevocationCheck: true,
533
558
  ...input.decryptScopesWith ? { decryptScopesWith: input.decryptScopesWith } : {}
534
559
  });
535
560
  if (!dr.ok) return dr;
@@ -599,6 +624,12 @@ async function verifyAction(input) {
599
624
  return err("E_BAD_SCOPE_GRAMMAR", msg);
600
625
  }
601
626
  if (!accepted) return err("E_SCOPE_DENIED", `scope_exercised (${exercised}) not a sub-scope of any granted scope`);
627
+ if (!input.skipRevocationCheck && !input.revocations) {
628
+ return err(
629
+ "E_MALFORMED",
630
+ "verifyAction requires `revocations` (fetch kind-30085 by #delegation for every link in the chain) or an explicit skipRevocationCheck:true"
631
+ );
632
+ }
602
633
  if (input.revocations && input.revocations.length > 0) {
603
634
  const allLinks = [rootHydrated, ...hydratedChain];
604
635
  for (const link of allLinks) {
@@ -1101,6 +1132,37 @@ function fail(code, message) {
1101
1132
  return { ok: false, code, message };
1102
1133
  }
1103
1134
 
1104
- export { AgentError, DEFAULT_MAX_CHAIN_DEPTH, ENVELOPE_VERSION, REGISTERED_SCOPES, ScopeParseError, actionCanonicalBytes, actionCanonicalMessage, canonicalActionBytes, canonicalDelegationBytes, canonicalRevocationBytes, canonicalizeAction, canonicalizeDelegation, canonicalizeRevocation, canonicalizeScope, canonicalizeScopeString, canonicalizeScopes, computeActionId, computeDelegationId, computeFederationDescriptorId, computeRevocationId, computeSubdelegationId, decodeScopesPayload, delegationCanonicalBytes, delegationCanonicalMessage, encodeScopesPayload, federationDescriptorCanonicalMessage, hasPrivateScopes, isSubScope, parseAndCanonicalizeScopes, parseScope, revocationCanonicalBytes, revocationCanonicalMessage, sealScopes, sha256Hex, subdelegationCanonicalBytes, subdelegationCanonicalMessage, unsealScopes, validateScope, verifyAction, verifyDelegation, verifyFederationDelegation, verifyFederationRevocation, verifyRevocation, verifySubdelegation };
1135
+ // src/assert-scope.ts
1136
+ var ScopeNotGrantedError = class extends Error {
1137
+ constructor(reason, message) {
1138
+ super(message);
1139
+ this.name = "ScopeNotGrantedError";
1140
+ this.reason = reason;
1141
+ }
1142
+ };
1143
+ function assertScopeGranted(delegation, scopeExercised, fnName) {
1144
+ if (hasPrivateScopes(delegation)) {
1145
+ throw new ScopeNotGrantedError(
1146
+ "scopes_encrypted",
1147
+ `${fnName}: this delegation uses v1.2 private scopes \u2014 \`scopes_encrypted\` is set and \`scopes\` is absent, so the granted set cannot be read here. Decrypt it with decryptPrivateScopes() using a matching device key and pass the recovered scopes as \`delegation.scopes\`. Refusing to stamp \`${scopeExercised}\` against an unreadable grant.`
1148
+ );
1149
+ }
1150
+ const scopes = delegation.scopes;
1151
+ if (scopes === void 0 || scopes.length === 0) {
1152
+ throw new ScopeNotGrantedError(
1153
+ "no_scopes",
1154
+ `${fnName}: delegation grants no scopes, so \`${scopeExercised}\` cannot be exercised. An absent or empty \`scopes\` means nothing is granted, never everything.`
1155
+ );
1156
+ }
1157
+ const exercised = parseScope(scopeExercised);
1158
+ if (!scopes.map(parseScope).some((g) => isSubScope(exercised, g))) {
1159
+ throw new ScopeNotGrantedError(
1160
+ "not_subscope",
1161
+ `${fnName}: scope_exercised (${scopeExercised}) is not a sub-scope of any granted scope (${scopes.join(", ")})`
1162
+ );
1163
+ }
1164
+ }
1165
+
1166
+ export { AgentError, DEFAULT_MAX_CHAIN_DEPTH, ENVELOPE_VERSION, REGISTERED_SCOPES, ScopeNotGrantedError, ScopeParseError, actionCanonicalBytes, actionCanonicalMessage, assertScopeGranted, canonicalActionBytes, canonicalDelegationBytes, canonicalRevocationBytes, canonicalizeAction, canonicalizeDelegation, canonicalizeRevocation, canonicalizeScope, canonicalizeScopeString, canonicalizeScopes, computeActionId, computeDelegationId, computeFederationDescriptorId, computeRevocationId, computeSubdelegationId, decodeScopesPayload, delegationCanonicalBytes, delegationCanonicalMessage, encodeScopesPayload, federationDescriptorCanonicalMessage, hasPrivateScopes, isSubScope, parseAndCanonicalizeScopes, parseScope, revocationCanonicalBytes, revocationCanonicalMessage, sealScopes, sha256Hex, subdelegationCanonicalBytes, subdelegationCanonicalMessage, unsealScopes, validateScope, verifyAction, verifyDelegation, verifyFederationDelegation, verifyFederationRevocation, verifyRevocation, verifySubdelegation };
1105
1167
  //# sourceMappingURL=index.mjs.map
1106
1168
  //# sourceMappingURL=index.mjs.map