@orangecheck/agent-core 2.2.0 → 2.4.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_]*$/;
@@ -682,8 +685,7 @@ async function verifyAction(input) {
682
685
  if (h === null || hash === null) {
683
686
  return err("E_MALFORMED", "confirmed OTS proof missing block_height or block_hash");
684
687
  }
685
- const verified = actionAnchor !== null;
686
- anchor = { status: "confirmed", blockHeight: h, blockHash: hash, verified };
688
+ anchor = actionAnchor !== null ? { status: "confirmed", blockHeight: h, blockHash: hash, verified: true } : { status: "claimed", blockHeight: h, blockHash: hash, verified: false };
687
689
  }
688
690
  return {
689
691
  ok: true,
@@ -1094,6 +1096,18 @@ async function verifyFederationDelegation(input) {
1094
1096
  }
1095
1097
  const quorum = await checkFederationQuorum(env.principal, env.sig, env.id, input);
1096
1098
  if (!quorum.ok) return quorum;
1099
+ if (!input.skipRevocationCheck && !input.revocations) {
1100
+ return fail(
1101
+ "E_MALFORMED",
1102
+ "verifyFederationDelegation requires `revocations` (fetch kind-30085 by #delegation) or an explicit skipRevocationCheck:true to state that revocation is not being checked"
1103
+ );
1104
+ }
1105
+ for (const rev of input.revocations ?? []) {
1106
+ if (rev?.delegation_id !== env.id) continue;
1107
+ const rr = await verifyRevocationOf(env, rev, input);
1108
+ if (!rr.ok) continue;
1109
+ return fail("E_REVOKED", `delegation ${env.id} was revoked by ${rev.id}`);
1110
+ }
1097
1111
  if (!input.skipTemporalCheck) {
1098
1112
  const now = input.now ?? /* @__PURE__ */ new Date();
1099
1113
  const issued = new Date(env.issued_at);
@@ -1104,6 +1118,42 @@ async function verifyFederationDelegation(input) {
1104
1118
  }
1105
1119
  return { ok: true, id: env.id, canonicalMessage: delegationCanonicalMessage(canonInput) };
1106
1120
  }
1121
+ async function verifyRevocationOf(d, rev, input) {
1122
+ if (rev.signer?.alg === "federation") {
1123
+ return verifyFederationRevocation({
1124
+ envelope: rev,
1125
+ delegation: d,
1126
+ verifyBip322: input.verifyBip322,
1127
+ skipSignatureVerification: input.skipSignatureVerification
1128
+ });
1129
+ }
1130
+ const v1 = rev;
1131
+ const holders = d.revocation?.holders ?? ["principal"];
1132
+ if (!Array.isArray(holders) || !holders.includes("agent")) {
1133
+ return fail("E_REVOKER_UNAUTHORIZED", "only the federation may revoke this delegation");
1134
+ }
1135
+ if (v1.kind !== "agent-revocation" || v1.signer?.address !== d.agent.address) {
1136
+ return fail("E_REVOKER_UNAUTHORIZED", "a single-address revocation must be signed by the agent");
1137
+ }
1138
+ if (typeof v1.reason !== "string" || !ISO_UTC.test(v1.signed_at ?? "")) {
1139
+ return fail("E_MALFORMED", "revocation reason / signed_at invalid");
1140
+ }
1141
+ const canonInput = {
1142
+ address: v1.signer.address,
1143
+ delegation_id: v1.delegation_id,
1144
+ reason: v1.reason,
1145
+ signed_at: v1.signed_at
1146
+ };
1147
+ const id = computeRevocationId(canonInput);
1148
+ if (id !== v1.id) return fail("E_BAD_ID", `reconstructed id (${id}) != revocation.id (${v1.id})`);
1149
+ if (!input.skipSignatureVerification) {
1150
+ if (!input.verifyBip322) return fail("E_BAD_SIG", "no BIP-322 verifier supplied");
1151
+ if (typeof v1.sig?.value !== "string" || !await input.verifyBip322(v1.id, v1.sig.value, v1.signer.address)) {
1152
+ return fail("E_BAD_SIG", "revocation BIP-322 signature did not verify");
1153
+ }
1154
+ }
1155
+ return { ok: true, id: v1.id, canonicalMessage: revocationCanonicalMessage(canonInput) };
1156
+ }
1107
1157
  async function verifyFederationRevocation(input) {
1108
1158
  const env = input.envelope;
1109
1159
  if (env?.kind !== "agent-revocation") return fail("E_MALFORMED", 'kind must be "agent-revocation"');