@orangecheck/agent-core 2.1.0 → 2.2.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/README.md +3 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +37 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +37 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/federation.test.ts +26 -0
- package/src/federation.ts +14 -0
- package/src/revocation-authority.test.ts +258 -0
- package/src/verify.ts +61 -49
package/dist/index.mjs
CHANGED
|
@@ -635,6 +635,12 @@ async function verifyAction(input) {
|
|
|
635
635
|
"verifyAction requires `revocations` (fetch kind-30085 by #delegation for every link in the chain) or an explicit skipRevocationCheck:true"
|
|
636
636
|
);
|
|
637
637
|
}
|
|
638
|
+
let actionAnchor;
|
|
639
|
+
try {
|
|
640
|
+
actionAnchor = await verifiedAnchorHeight(a, input);
|
|
641
|
+
} catch (e) {
|
|
642
|
+
return err("E_MALFORMED", `anchor verifier threw: ${e.message}`);
|
|
643
|
+
}
|
|
638
644
|
if (input.revocations && input.revocations.length > 0) {
|
|
639
645
|
const allLinks = [rootHydrated, ...hydratedChain];
|
|
640
646
|
for (const link of allLinks) {
|
|
@@ -647,9 +653,13 @@ async function verifyAction(input) {
|
|
|
647
653
|
skipSignatureVerification: input.skipSignatureVerification
|
|
648
654
|
});
|
|
649
655
|
if (!rr.ok) continue;
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
656
|
+
let revAnchor;
|
|
657
|
+
try {
|
|
658
|
+
revAnchor = await verifiedAnchorHeight(rev, input);
|
|
659
|
+
} catch (e) {
|
|
660
|
+
return err("E_MALFORMED", `anchor verifier threw: ${e.message}`);
|
|
661
|
+
}
|
|
662
|
+
if (revocationPrecedes(rev, revAnchor, a, actionAnchor)) {
|
|
653
663
|
return err("E_REVOKED", `chain link ${link.id} was revoked by ${rev.id} before action was signed`);
|
|
654
664
|
}
|
|
655
665
|
}
|
|
@@ -672,14 +682,7 @@ async function verifyAction(input) {
|
|
|
672
682
|
if (h === null || hash === null) {
|
|
673
683
|
return err("E_MALFORMED", "confirmed OTS proof missing block_height or block_hash");
|
|
674
684
|
}
|
|
675
|
-
|
|
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
|
-
}
|
|
685
|
+
const verified = actionAnchor !== null;
|
|
683
686
|
anchor = { status: "confirmed", blockHeight: h, blockHash: hash, verified };
|
|
684
687
|
}
|
|
685
688
|
return {
|
|
@@ -749,9 +752,8 @@ async function verifyRevocation(input) {
|
|
|
749
752
|
return err("E_DELEGATION_MISMATCH", `revocation.delegation_id (${env.delegation_id}) != delegation.id (${d.id})`);
|
|
750
753
|
}
|
|
751
754
|
const holders = d.revocation?.holders ?? ["principal"];
|
|
752
|
-
const holderAddrs = /* @__PURE__ */ new Set();
|
|
753
|
-
if (holders.includes("
|
|
754
|
-
if (holders.includes("agent")) holderAddrs.add(d.agent.address);
|
|
755
|
+
const holderAddrs = /* @__PURE__ */ new Set([d.principal.address]);
|
|
756
|
+
if (Array.isArray(holders) && holders.includes("agent")) holderAddrs.add(d.agent.address);
|
|
755
757
|
if (!holderAddrs.has(env.signer.address)) {
|
|
756
758
|
return err("E_REVOKER_UNAUTHORIZED", `revocation signer ${env.signer.address} not in delegation holders`);
|
|
757
759
|
}
|
|
@@ -951,25 +953,17 @@ async function verifySubdelegation(input) {
|
|
|
951
953
|
}
|
|
952
954
|
return r;
|
|
953
955
|
}
|
|
954
|
-
function
|
|
955
|
-
if (
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
return
|
|
956
|
+
async function verifiedAnchorHeight(env, input) {
|
|
957
|
+
if (env.ots?.status !== "confirmed" || !input.verifyOtsAnchor) return null;
|
|
958
|
+
const h = input.resolveAnchorBlockHeight ? input.resolveAnchorBlockHeight(env) : env.ots.block_height;
|
|
959
|
+
const hash = env.ots.block_hash;
|
|
960
|
+
if (h === null || h === void 0 || !Number.isInteger(h) || !hash) return null;
|
|
961
|
+
return await input.verifyOtsAnchor(env.ots.proof, h, hash, env.id) ? h : null;
|
|
960
962
|
}
|
|
961
|
-
function
|
|
962
|
-
if (
|
|
963
|
-
|
|
964
|
-
|
|
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;
|
|
963
|
+
function revocationPrecedes(rev, revAnchor, action, actionAnchor) {
|
|
964
|
+
if (revAnchor !== null && actionAnchor !== null) return revAnchor <= actionAnchor;
|
|
965
|
+
if (actionAnchor === null && rev.ots?.status === "confirmed") return true;
|
|
966
|
+
return new Date(rev.signed_at).getTime() <= new Date(action.signed_at).getTime();
|
|
973
967
|
}
|
|
974
968
|
function err(code, message) {
|
|
975
969
|
return { ok: false, code, message };
|
|
@@ -1119,6 +1113,17 @@ async function verifyFederationRevocation(input) {
|
|
|
1119
1113
|
return fail("E_MALFORMED", "reason must be a string \u2264128 bytes");
|
|
1120
1114
|
}
|
|
1121
1115
|
if (!ISO_UTC.test(env.signed_at)) return fail("E_MALFORMED", "signed_at must be ISO 8601 UTC");
|
|
1116
|
+
const d = input.delegation;
|
|
1117
|
+
if (!d || !HEX64.test(d.id ?? "")) return fail("E_MALFORMED", "the revoked delegation is required");
|
|
1118
|
+
if (env.delegation_id !== d.id) {
|
|
1119
|
+
return fail("E_DELEGATION_MISMATCH", `revocation.delegation_id (${env.delegation_id}) != delegation.id (${d.id})`);
|
|
1120
|
+
}
|
|
1121
|
+
if (d.principal?.alg !== "federation" || env.signer?.descriptor_id !== d.principal.descriptor_id) {
|
|
1122
|
+
return fail(
|
|
1123
|
+
"E_REVOKER_UNAUTHORIZED",
|
|
1124
|
+
`revoking federation (${env.signer?.descriptor_id}) is not the delegation's principal`
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1122
1127
|
const canonInput = {
|
|
1123
1128
|
address: `federation:${env.signer?.descriptor_id ?? ""}`,
|
|
1124
1129
|
delegation_id: env.delegation_id,
|