@orangecheck/agent-core 2.1.0 → 2.3.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
@@ -15,7 +15,9 @@ var REGISTERED_SCOPES = {
15
15
  "nostr:publish": { keys: ["kind", "relay", "max_bytes"] },
16
16
  "http:request": { keys: ["origin", "method", "max_rps", "max_bytes_out"] },
17
17
  "ln:send": { keys: ["max_sats", "node", "max_fee_sats"] },
18
- "mcp:invoke": { keys: ["server", "tool", "max_invocations"] }
18
+ "mcp:invoke": { keys: ["server", "tool", "max_invocations"] },
19
+ // oc-pledge-protocol SPEC §7.3.
20
+ "pledge:create": { keys: ["max_bond_sats", "mechanism", "counterparty"] }
19
21
  };
20
22
  var NUMERIC_KEYS = /* @__PURE__ */ new Set([
21
23
  "max_bytes",
@@ -26,6 +28,7 @@ var NUMERIC_KEYS = /* @__PURE__ */ new Set([
26
28
  "max_sats",
27
29
  "max_fee_sats",
28
30
  "max_invocations",
31
+ "max_bond_sats",
29
32
  "kind"
30
33
  ]);
31
34
  var IDENT_RE = /^[a-z][a-z0-9_]*$/;
@@ -635,6 +638,12 @@ async function verifyAction(input) {
635
638
  "verifyAction requires `revocations` (fetch kind-30085 by #delegation for every link in the chain) or an explicit skipRevocationCheck:true"
636
639
  );
637
640
  }
641
+ let actionAnchor;
642
+ try {
643
+ actionAnchor = await verifiedAnchorHeight(a, input);
644
+ } catch (e) {
645
+ return err("E_MALFORMED", `anchor verifier threw: ${e.message}`);
646
+ }
638
647
  if (input.revocations && input.revocations.length > 0) {
639
648
  const allLinks = [rootHydrated, ...hydratedChain];
640
649
  for (const link of allLinks) {
@@ -647,9 +656,13 @@ async function verifyAction(input) {
647
656
  skipSignatureVerification: input.skipSignatureVerification
648
657
  });
649
658
  if (!rr.ok) continue;
650
- const effective = effectiveRevocationTime(rev, input.resolveAnchorBlockHeight);
651
- const actionTime = actionEffectiveTime(a, input.resolveAnchorBlockHeight);
652
- if (compareTimes(effective, actionTime) <= 0) {
659
+ let revAnchor;
660
+ try {
661
+ revAnchor = await verifiedAnchorHeight(rev, input);
662
+ } catch (e) {
663
+ return err("E_MALFORMED", `anchor verifier threw: ${e.message}`);
664
+ }
665
+ if (revocationPrecedes(rev, revAnchor, a, actionAnchor)) {
653
666
  return err("E_REVOKED", `chain link ${link.id} was revoked by ${rev.id} before action was signed`);
654
667
  }
655
668
  }
@@ -672,14 +685,7 @@ async function verifyAction(input) {
672
685
  if (h === null || hash === null) {
673
686
  return err("E_MALFORMED", "confirmed OTS proof missing block_height or block_hash");
674
687
  }
675
- let verified = false;
676
- if (input.verifyOtsAnchor) {
677
- try {
678
- verified = await input.verifyOtsAnchor(a.ots.proof, h, hash);
679
- } catch (e) {
680
- return err("E_MALFORMED", `anchor verifier threw: ${e.message}`);
681
- }
682
- }
688
+ const verified = actionAnchor !== null;
683
689
  anchor = { status: "confirmed", blockHeight: h, blockHash: hash, verified };
684
690
  }
685
691
  return {
@@ -749,9 +755,8 @@ async function verifyRevocation(input) {
749
755
  return err("E_DELEGATION_MISMATCH", `revocation.delegation_id (${env.delegation_id}) != delegation.id (${d.id})`);
750
756
  }
751
757
  const holders = d.revocation?.holders ?? ["principal"];
752
- const holderAddrs = /* @__PURE__ */ new Set();
753
- if (holders.includes("principal")) holderAddrs.add(d.principal.address);
754
- if (holders.includes("agent")) holderAddrs.add(d.agent.address);
758
+ const holderAddrs = /* @__PURE__ */ new Set([d.principal.address]);
759
+ if (Array.isArray(holders) && holders.includes("agent")) holderAddrs.add(d.agent.address);
755
760
  if (!holderAddrs.has(env.signer.address)) {
756
761
  return err("E_REVOKER_UNAUTHORIZED", `revocation signer ${env.signer.address} not in delegation holders`);
757
762
  }
@@ -951,25 +956,17 @@ async function verifySubdelegation(input) {
951
956
  }
952
957
  return r;
953
958
  }
954
- function actionEffectiveTime(a, resolve) {
955
- if (a.ots?.status === "confirmed") {
956
- const h = resolve ? resolve(a) : a.ots.block_height;
957
- if (h !== null && h !== void 0) return { kind: "anchor", blockHeight: h };
958
- }
959
- return { kind: "signed", ms: new Date(a.signed_at).getTime() };
959
+ async function verifiedAnchorHeight(env, input) {
960
+ if (env.ots?.status !== "confirmed" || !input.verifyOtsAnchor) return null;
961
+ const h = input.resolveAnchorBlockHeight ? input.resolveAnchorBlockHeight(env) : env.ots.block_height;
962
+ const hash = env.ots.block_hash;
963
+ if (h === null || h === void 0 || !Number.isInteger(h) || !hash) return null;
964
+ return await input.verifyOtsAnchor(env.ots.proof, h, hash, env.id) ? h : null;
960
965
  }
961
- function effectiveRevocationTime(r, resolve) {
962
- if (r.ots?.status === "confirmed") {
963
- const h = resolve ? resolve(r) : r.ots.block_height;
964
- if (h !== null && h !== void 0) return { kind: "anchor", blockHeight: h };
965
- }
966
- return { kind: "signed", ms: new Date(r.signed_at).getTime() };
967
- }
968
- function compareTimes(a, b) {
969
- if (a.kind === "anchor" && b.kind === "anchor") return a.blockHeight - b.blockHeight;
970
- if (a.kind === "anchor") return -1;
971
- if (b.kind === "anchor") return 1;
972
- return a.ms - b.ms;
966
+ function revocationPrecedes(rev, revAnchor, action, actionAnchor) {
967
+ if (revAnchor !== null && actionAnchor !== null) return revAnchor <= actionAnchor;
968
+ if (actionAnchor === null && rev.ots?.status === "confirmed") return true;
969
+ return new Date(rev.signed_at).getTime() <= new Date(action.signed_at).getTime();
973
970
  }
974
971
  function err(code, message) {
975
972
  return { ok: false, code, message };
@@ -1119,6 +1116,17 @@ async function verifyFederationRevocation(input) {
1119
1116
  return fail("E_MALFORMED", "reason must be a string \u2264128 bytes");
1120
1117
  }
1121
1118
  if (!ISO_UTC.test(env.signed_at)) return fail("E_MALFORMED", "signed_at must be ISO 8601 UTC");
1119
+ const d = input.delegation;
1120
+ if (!d || !HEX64.test(d.id ?? "")) return fail("E_MALFORMED", "the revoked delegation is required");
1121
+ if (env.delegation_id !== d.id) {
1122
+ return fail("E_DELEGATION_MISMATCH", `revocation.delegation_id (${env.delegation_id}) != delegation.id (${d.id})`);
1123
+ }
1124
+ if (d.principal?.alg !== "federation" || env.signer?.descriptor_id !== d.principal.descriptor_id) {
1125
+ return fail(
1126
+ "E_REVOKER_UNAUTHORIZED",
1127
+ `revoking federation (${env.signer?.descriptor_id}) is not the delegation's principal`
1128
+ );
1129
+ }
1122
1130
  const canonInput = {
1123
1131
  address: `federation:${env.signer?.descriptor_id ?? ""}`,
1124
1132
  delegation_id: env.delegation_id,