@orangecheck/agent-core 2.6.0 → 2.7.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 +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +47 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +45 -2
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.mts +9 -1
- package/dist/types.d.ts +9 -1
- package/dist/types.js.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/live-time.test.ts +151 -0
- package/src/revocation-authority.test.ts +15 -13
- package/src/revocation-failclosed.test.ts +1 -1
- package/src/test-vectors.test.ts +43 -8
- package/src/types.ts +9 -0
- package/src/verify.ts +100 -0
package/dist/index.mjs
CHANGED
|
@@ -410,6 +410,7 @@ function hasPrivateScopes(envelope) {
|
|
|
410
410
|
|
|
411
411
|
// src/verify.ts
|
|
412
412
|
var DEFAULT_MAX_CHAIN_DEPTH = 5;
|
|
413
|
+
var DEFAULT_MAX_SKEW_MS = 12e4;
|
|
413
414
|
var AgentError = class extends Error {
|
|
414
415
|
constructor(code, message) {
|
|
415
416
|
super(message);
|
|
@@ -544,6 +545,12 @@ async function verifyDelegation(input) {
|
|
|
544
545
|
};
|
|
545
546
|
}
|
|
546
547
|
async function verifyAction(input) {
|
|
548
|
+
return verifyActionAt(input, input.now ?? /* @__PURE__ */ new Date());
|
|
549
|
+
}
|
|
550
|
+
async function verifyActionAsOfSignedAt(input) {
|
|
551
|
+
return verifyActionAt(input, null);
|
|
552
|
+
}
|
|
553
|
+
async function verifyActionAt(input, now) {
|
|
547
554
|
const a = input.action;
|
|
548
555
|
const d = input.delegation;
|
|
549
556
|
const chain = input.subdelegationChain ?? [];
|
|
@@ -621,6 +628,17 @@ async function verifyAction(input) {
|
|
|
621
628
|
if (signed < issued || signed >= expires) {
|
|
622
629
|
return err("E_OUT_OF_WINDOW", `action.signed_at ${a.signed_at} is outside leaf window [${leaf.issued_at}, ${leaf.expires_at})`);
|
|
623
630
|
}
|
|
631
|
+
if (now) {
|
|
632
|
+
const t = now.getTime();
|
|
633
|
+
for (const link of [rootHydrated, ...hydratedChain]) {
|
|
634
|
+
if (t < new Date(link.issued_at).getTime()) {
|
|
635
|
+
return err("E_NOT_YET_VALID", `${link.id} is not valid until ${link.issued_at}`);
|
|
636
|
+
}
|
|
637
|
+
if (t >= new Date(link.expires_at).getTime()) {
|
|
638
|
+
return err("E_EXPIRED", `${link.id} expired at ${link.expires_at}`);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
624
642
|
if (!leaf.scopes) {
|
|
625
643
|
return err("E_SCOPES_NEITHER_PROVIDED", "leaf has no plaintext scopes after hydration");
|
|
626
644
|
}
|
|
@@ -669,9 +687,21 @@ async function verifyAction(input) {
|
|
|
669
687
|
if (revocationPrecedes(rev, revAnchor, a, actionAnchor)) {
|
|
670
688
|
return err("E_REVOKED", `chain link ${link.id} was revoked by ${rev.id} before action was signed`);
|
|
671
689
|
}
|
|
690
|
+
if (now && (revAnchor !== null || new Date(rev.signed_at).getTime() <= now.getTime())) {
|
|
691
|
+
return err("E_REVOKED", `chain link ${link.id} was revoked by ${rev.id}`);
|
|
692
|
+
}
|
|
672
693
|
}
|
|
673
694
|
}
|
|
674
695
|
}
|
|
696
|
+
if (now) {
|
|
697
|
+
const maxSkew = input.maxSkewMs ?? DEFAULT_MAX_SKEW_MS;
|
|
698
|
+
if (Math.abs(now.getTime() - signed) > maxSkew) {
|
|
699
|
+
return err(
|
|
700
|
+
"E_STALE",
|
|
701
|
+
`action.signed_at ${a.signed_at} is more than ${maxSkew} ms from the time of verification ${now.toISOString()}`
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
675
705
|
if (input.content) {
|
|
676
706
|
const actualHash = "sha256:" + hexEncode(sha256(input.content));
|
|
677
707
|
if (actualHash !== a.content.hash) {
|
|
@@ -699,7 +729,20 @@ async function verifyAction(input) {
|
|
|
699
729
|
delegation: rootHydrated,
|
|
700
730
|
chain: hydratedChain,
|
|
701
731
|
scopeExercised: exercised,
|
|
702
|
-
anchor
|
|
732
|
+
anchor,
|
|
733
|
+
asOf: now ? { basis: "now", now: now.toISOString() } : { basis: "signed_at", signedAt: a.signed_at, anchored: actionAnchor !== null }
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
function createReplayGuard(maxSkewMs = DEFAULT_MAX_SKEW_MS) {
|
|
737
|
+
const keepUntil = /* @__PURE__ */ new Map();
|
|
738
|
+
return {
|
|
739
|
+
firstUse(action, now = /* @__PURE__ */ new Date()) {
|
|
740
|
+
const t = now.getTime();
|
|
741
|
+
for (const [id, until] of keepUntil) if (until <= t) keepUntil.delete(id);
|
|
742
|
+
if (keepUntil.has(action.id)) return false;
|
|
743
|
+
keepUntil.set(action.id, new Date(action.signed_at).getTime() + maxSkewMs);
|
|
744
|
+
return true;
|
|
745
|
+
}
|
|
703
746
|
};
|
|
704
747
|
}
|
|
705
748
|
async function hydrateSubdelegationScopes(sub, input) {
|
|
@@ -1239,6 +1282,6 @@ function assertScopeGranted(delegation, scopeExercised, fnName) {
|
|
|
1239
1282
|
}
|
|
1240
1283
|
}
|
|
1241
1284
|
|
|
1242
|
-
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 };
|
|
1285
|
+
export { AgentError, DEFAULT_MAX_CHAIN_DEPTH, DEFAULT_MAX_SKEW_MS, ENVELOPE_VERSION, REGISTERED_SCOPES, ScopeNotGrantedError, ScopeParseError, actionCanonicalBytes, actionCanonicalMessage, assertScopeGranted, canonicalActionBytes, canonicalDelegationBytes, canonicalRevocationBytes, canonicalizeAction, canonicalizeDelegation, canonicalizeRevocation, canonicalizeScope, canonicalizeScopeString, canonicalizeScopes, computeActionId, computeDelegationId, computeFederationDescriptorId, computeRevocationId, computeSubdelegationId, createReplayGuard, decodeScopesPayload, delegationCanonicalBytes, delegationCanonicalMessage, encodeScopesPayload, federationDescriptorCanonicalMessage, hasPrivateScopes, isSubScope, parseAndCanonicalizeScopes, parseScope, revocationCanonicalBytes, revocationCanonicalMessage, sealScopes, sha256Hex, subdelegationCanonicalBytes, subdelegationCanonicalMessage, unsealScopes, validateScope, verifyAction, verifyActionAsOfSignedAt, verifyDelegation, verifyFederationDelegation, verifyFederationRevocation, verifyRevocation, verifySubdelegation };
|
|
1243
1286
|
//# sourceMappingURL=index.mjs.map
|
|
1244
1287
|
//# sourceMappingURL=index.mjs.map
|