@xyo-network/event-kit-protocol 1.0.0 → 1.0.1
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/neutral/admissionCore.d.ts.map +1 -1
- package/dist/neutral/endpointChallenge.d.ts.map +1 -1
- package/dist/neutral/index.mjs +25 -74
- package/dist/neutral/index.mjs.map +2 -2
- package/dist/neutral/lifecycleSelection.d.ts.map +1 -1
- package/dist/neutral/publisherSubscription.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admissionCore.d.ts","sourceRoot":"","sources":["../../src/admissionCore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAGf,oBAAoB,EAGpB,mBAAmB,EAEpB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAEvE,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,YAAY;IACtD,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IACtC,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAA;IACxC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CACrB;AAED,MAAM,MAAM,4BAA4B,GAClC,eAAe,GACf,mBAAmB,GACnB,oBAAoB,GACpB,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,mBAAmB,CAAA;AAEzB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAA;CAC9C;AAED,MAAM,WAAW,sBAAsB,CAAC,KAAK,GAAG,YAAY;IAC1D,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;IACjB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;IACtC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CACrB;AAED,MAAM,MAAM,qBAAqB,CAAC,KAAK,GAAG,YAAY,IAAI,sBAAsB,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAA;AAEhH;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"admissionCore.d.ts","sourceRoot":"","sources":["../../src/admissionCore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAGf,oBAAoB,EAGpB,mBAAmB,EAEpB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAEvE,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,YAAY;IACtD,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;IACtC,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAA;IACxC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CACrB;AAED,MAAM,MAAM,4BAA4B,GAClC,eAAe,GACf,mBAAmB,GACnB,oBAAoB,GACpB,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,mBAAmB,CAAA;AAEzB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAA;CAC9C;AAED,MAAM,WAAW,sBAAsB,CAAC,KAAK,GAAG,YAAY;IAC1D,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;IACjB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;IACtC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CACrB;AAED,MAAM,MAAM,qBAAqB,CAAC,KAAK,GAAG,YAAY,IAAI,sBAAsB,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAA;AAEhH;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAetH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpointChallenge.d.ts","sourceRoot":"","sources":["../../src/endpointChallenge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,OAAO,EACP,iBAAiB,EACjB,yBAAyB,EACzB,WAAW,EACX,IAAI,EACJ,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,gCAAgC,CAAA;AAevC,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,IAAI,CAAA;IACnB,SAAS,EAAE,mBAAmB,CAAA;IAC9B,KAAK,EAAE,IAAI,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,WAAW,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,OAAO,EAAE,IAAI,CAAA;IACb,UAAU,EAAE,iBAAiB,CAAA;IAC7B,YAAY,EAAE,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,oCAAoC;IACnD,SAAS,EAAE,iBAAiB,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,yBAAyB,CAAA;IACnC,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,KAAK,iCAAiC,GAAG,IAAI,CAAC,oCAAoC,EAAE,YAAY,CAAC,CAAA;AA6BjG,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvF;AAED,uFAAuF;AACvF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,CA4B9F;AAED,uFAAuF;AACvF,wBAAsB,+BAA+B,CACnD,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,yBAAyB,CAAC,CAOpC;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"endpointChallenge.d.ts","sourceRoot":"","sources":["../../src/endpointChallenge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,OAAO,EACP,iBAAiB,EACjB,yBAAyB,EACzB,WAAW,EACX,IAAI,EACJ,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,gCAAgC,CAAA;AAevC,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,IAAI,CAAA;IACnB,SAAS,EAAE,mBAAmB,CAAA;IAC9B,KAAK,EAAE,IAAI,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,WAAW,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,OAAO,EAAE,IAAI,CAAA;IACb,UAAU,EAAE,iBAAiB,CAAA;IAC7B,YAAY,EAAE,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,oCAAoC;IACnD,SAAS,EAAE,iBAAiB,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,yBAAyB,CAAA;IACnC,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,KAAK,iCAAiC,GAAG,IAAI,CAAC,oCAAoC,EAAE,YAAY,CAAC,CAAA;AA6BjG,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvF;AAED,uFAAuF;AACvF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,CA4B9F;AAED,uFAAuF;AACvF,wBAAsB,+BAA+B,CACnD,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,yBAAyB,CAAC,CAOpC;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,OAAO,CAAC,CASlB;AAED,iGAAiG;AACjG,wBAAsB,+BAA+B,CACnD,KAAK,EAAE,oCAAoC,GAC1C,OAAO,CAAC,OAAO,CAAC,CAUlB"}
|
package/dist/neutral/index.mjs
CHANGED
|
@@ -13,8 +13,7 @@ async function admitVerifiedWake(input) {
|
|
|
13
13
|
return reject("grant-view-invalid", ["expectedHead must be a nonnegative safe integer"]);
|
|
14
14
|
}
|
|
15
15
|
const authorization = await authorize(input);
|
|
16
|
-
|
|
17
|
-
return await commitAuthorizedWake(input.inbox, attempt, authorization.grant, wake);
|
|
16
|
+
return authorization.ok ? await commitAuthorizedWake(input.inbox, attempt, authorization.grant, wake) : authorization.failure;
|
|
18
17
|
}
|
|
19
18
|
async function resolvePriorAttempt(inbox, attempt, wake) {
|
|
20
19
|
let resolution;
|
|
@@ -33,10 +32,7 @@ async function resolvePriorAttempt(inbox, attempt, wake) {
|
|
|
33
32
|
const receiptFailure = validateReceipt(resolution.receipt, attempt);
|
|
34
33
|
return completed(receiptFailure ?? success("duplicate", snapshotReceipt(resolution.receipt), wake));
|
|
35
34
|
}
|
|
36
|
-
|
|
37
|
-
return completed(reject("inbox-unavailable", ["inbox returned an unknown attempt resolution"]));
|
|
38
|
-
}
|
|
39
|
-
return Object.freeze({ pending: true });
|
|
35
|
+
return resolution.kind === "new" ? Object.freeze({ pending: true }) : completed(reject("inbox-unavailable", ["inbox returned an unknown attempt resolution"]));
|
|
40
36
|
}
|
|
41
37
|
async function commitAuthorizedWake(inbox, attempt, grant, wake) {
|
|
42
38
|
let committed;
|
|
@@ -59,8 +55,7 @@ async function commitAuthorizedWake(inbox, attempt, grant, wake) {
|
|
|
59
55
|
return reject("inbox-unavailable", ["inbox returned an unknown commit result"]);
|
|
60
56
|
}
|
|
61
57
|
const receiptFailure = validateReceipt(committed.receipt, attempt);
|
|
62
|
-
|
|
63
|
-
return success(committed.kind, snapshotReceipt(committed.receipt), wake);
|
|
58
|
+
return receiptFailure ?? success(committed.kind, snapshotReceipt(committed.receipt), wake);
|
|
64
59
|
}
|
|
65
60
|
function completed(result) {
|
|
66
61
|
return Object.freeze({ pending: false, result });
|
|
@@ -132,10 +127,7 @@ function validateGrantView(decision, expectedHead, maxGrantLagBlocks) {
|
|
|
132
127
|
if (decision.lag !== void 0 && decision.lag !== lag) {
|
|
133
128
|
return reject("grant-view-invalid", ["grant diagnostic lag disagrees with the recomputed lag"]);
|
|
134
129
|
}
|
|
135
|
-
|
|
136
|
-
return reject("grant-view-stale", [`grantLag=${lag} max=${maxGrantLagBlocks}`]);
|
|
137
|
-
}
|
|
138
|
-
return void 0;
|
|
130
|
+
return lag > maxGrantLagBlocks ? reject("grant-view-stale", [`grantLag=${lag} max=${maxGrantLagBlocks}`]) : void 0;
|
|
139
131
|
}
|
|
140
132
|
function validateGrantEvidence(evidence, verified, atBlock) {
|
|
141
133
|
if (!isRecord(evidence)) return reject("grant-view-invalid", ["enabled grant decision omitted evidence"]);
|
|
@@ -170,10 +162,7 @@ function validateGrantEvidence(evidence, verified, atBlock) {
|
|
|
170
162
|
}
|
|
171
163
|
const evidenceHasQueue = Object.hasOwn(evidence, "queueId");
|
|
172
164
|
const routeHasQueue = Object.hasOwn(verified.route, "queueId");
|
|
173
|
-
|
|
174
|
-
return reject("grant-view-invalid", ["grant scope does not exactly match the configured route"]);
|
|
175
|
-
}
|
|
176
|
-
return void 0;
|
|
165
|
+
return evidence.deploymentId !== verified.route.deploymentId || evidenceHasQueue !== routeHasQueue || evidence.queueId !== verified.route.queueId ? reject("grant-view-invalid", ["grant scope does not exactly match the configured route"]) : void 0;
|
|
177
166
|
}
|
|
178
167
|
function validateReceipt(receipt, attempt) {
|
|
179
168
|
const requiredFields = [
|
|
@@ -186,10 +175,7 @@ function validateReceipt(receipt, attempt) {
|
|
|
186
175
|
if (!isRecord(receipt) || requiredFields.some((field) => !Object.hasOwn(receipt, field)) || typeof receipt.id !== "string" || receipt.id.length === 0) {
|
|
187
176
|
return reject("inbox-unavailable", ["inbox returned an invalid receipt"]);
|
|
188
177
|
}
|
|
189
|
-
|
|
190
|
-
return reject("inbox-unavailable", ["inbox receipt is not bound to the verified attempt"]);
|
|
191
|
-
}
|
|
192
|
-
return void 0;
|
|
178
|
+
return receipt.audience !== attempt.audience || receipt.publisher !== attempt.publisher || receipt.eventHash !== attempt.eventHash || receipt.wakeId !== attempt.wakeId ? reject("inbox-unavailable", ["inbox receipt is not bound to the verified attempt"]) : void 0;
|
|
193
179
|
}
|
|
194
180
|
function snapshotGrantEvidence(evidence) {
|
|
195
181
|
return Object.freeze({
|
|
@@ -427,8 +413,7 @@ async function verifyEndpointChallengeProof(input) {
|
|
|
427
413
|
const challenge = EndpointChallengeZod.parse(input.challenge);
|
|
428
414
|
const response = EndpointChallengeResponseZod.parse(input.response);
|
|
429
415
|
const challengeHash = await endpointChallengeHash(challenge);
|
|
430
|
-
|
|
431
|
-
return equalProof(response.proof, await hmacProof(input.secret, challengeHash));
|
|
416
|
+
return response.challenge === challengeHash && equalProof(response.proof, await hmacProof(input.secret, challengeHash));
|
|
432
417
|
} catch {
|
|
433
418
|
return false;
|
|
434
419
|
}
|
|
@@ -436,8 +421,7 @@ async function verifyEndpointChallengeProof(input) {
|
|
|
436
421
|
async function verifyEndpointChallengeResponse(input) {
|
|
437
422
|
try {
|
|
438
423
|
const challenge = EndpointChallengeZod.parse(input.challenge);
|
|
439
|
-
|
|
440
|
-
return await verifyEndpointChallengeProof(input);
|
|
424
|
+
return Number.isSafeInteger(input.nowSeconds) && input.nowSeconds >= challenge.issuedAt && input.nowSeconds < challenge.expiresAt && await verifyEndpointChallengeProof(input);
|
|
441
425
|
} catch {
|
|
442
426
|
return false;
|
|
443
427
|
}
|
|
@@ -850,12 +834,10 @@ function isUnrevokedEvidence(claimedAtBlock, revokedAtBlock, finalizedHead) {
|
|
|
850
834
|
return isVisible(claimedAtBlock, finalizedHead) && (revokedAtBlock === void 0 || isNonnegativeSafeInteger2(revokedAtBlock) && revokedAtBlock >= claimedAtBlock) && !isRevoked(revokedAtBlock, finalizedHead);
|
|
851
835
|
}
|
|
852
836
|
function isInsideExclusiveWindow(finalizedHead, validFromBlock, expiresAtBlock) {
|
|
853
|
-
|
|
854
|
-
return expiresAtBlock === void 0 || isNonnegativeSafeInteger2(expiresAtBlock) && expiresAtBlock > validFromBlock && finalizedHead < expiresAtBlock;
|
|
837
|
+
return isNonnegativeSafeInteger2(validFromBlock) && finalizedHead >= validFromBlock && (expiresAtBlock === void 0 || isNonnegativeSafeInteger2(expiresAtBlock) && expiresAtBlock > validFromBlock && finalizedHead < expiresAtBlock);
|
|
855
838
|
}
|
|
856
839
|
function isRevisionShapeValid(revision) {
|
|
857
|
-
if (!Number.isSafeInteger(revision.revision) || revision.revision < 1) return false;
|
|
858
|
-
if (!isNonnegativeSafeInteger2(revision.claimedAtBlock)) return false;
|
|
840
|
+
if (!Number.isSafeInteger(revision.revision) || revision.revision < 1 || !isNonnegativeSafeInteger2(revision.claimedAtBlock)) return false;
|
|
859
841
|
if (revision.revokedAtBlock !== void 0 && (!isNonnegativeSafeInteger2(revision.revokedAtBlock) || revision.revokedAtBlock < revision.claimedAtBlock)) return false;
|
|
860
842
|
return revision.revision === 1 ? revision.supersedes === void 0 : revision.supersedes !== void 0;
|
|
861
843
|
}
|
|
@@ -929,8 +911,7 @@ function selectPublisherService(input) {
|
|
|
929
911
|
}
|
|
930
912
|
}
|
|
931
913
|
if (selectable.length === 0) return { ok: false, reason: "service-not-found" };
|
|
932
|
-
|
|
933
|
-
return { ok: true, service: selectable[0] };
|
|
914
|
+
return selectable.length > 1 ? { ok: false, reason: "ambiguous-service" } : { ok: true, service: selectable[0] };
|
|
934
915
|
}
|
|
935
916
|
function resolvePreferredEncryptionKey(input) {
|
|
936
917
|
const preferredHash = input.service.preferredEncryptionKey;
|
|
@@ -943,10 +924,7 @@ function resolvePreferredEncryptionKey(input) {
|
|
|
943
924
|
const key = exact[0];
|
|
944
925
|
const sameStableIdentity = input.keys.filter((candidate) => candidate.source === key.source && candidate.keyId === key.keyId && candidate.objectHash !== key.objectHash && isVisible(candidate.claimedAtBlock, input.finalizedHead));
|
|
945
926
|
if (sameStableIdentity.length > 0) return { ok: false, reason: "ambiguous-key" };
|
|
946
|
-
|
|
947
|
-
return { ok: false, reason: "preferred-key-inactive" };
|
|
948
|
-
}
|
|
949
|
-
return { ok: true, key };
|
|
927
|
+
return !isUnrevokedEvidence(key.claimedAtBlock, key.revokedAtBlock, input.finalizedHead) || !isInsideExclusiveWindow(input.finalizedHead, key.validFromBlock, key.expiresAtBlock) ? { ok: false, reason: "preferred-key-inactive" } : { ok: true, key };
|
|
950
928
|
}
|
|
951
929
|
function acceptanceFor(subscription, input) {
|
|
952
930
|
return input.acceptances.filter((acceptance) => acceptance.source === input.publisherSource && acceptance.subscription === subscription.objectHash && isVisible(acceptance.acceptanceBlock, input.finalizedHead));
|
|
@@ -991,10 +969,7 @@ function selectSubscriptionActivation(input) {
|
|
|
991
969
|
if (selected === void 0) return { ok: false, reason: "subscription-pending" };
|
|
992
970
|
const latest = resolution.chain.at(-1);
|
|
993
971
|
if (!isActiveAcceptedSubscription(selected, input.finalizedHead)) {
|
|
994
|
-
|
|
995
|
-
return { ok: false, reason: "subscription-pending" };
|
|
996
|
-
}
|
|
997
|
-
return { ok: false, reason: "subscription-inactive" };
|
|
972
|
+
return { ok: false, reason: latest?.objectHash === selected.subscription.objectHash ? "subscription-inactive" : "subscription-pending" };
|
|
998
973
|
}
|
|
999
974
|
return {
|
|
1000
975
|
acceptance: selected.acceptance,
|
|
@@ -1323,8 +1298,7 @@ function publicBindingFailure(candidate, parsed) {
|
|
|
1323
1298
|
if (!hasExactKeyBinding(parsed.service, hashedKey, parsed.subscription)) return "key-binding-invalid";
|
|
1324
1299
|
if (!isActiveAt(parsed.service, candidate.tupleBlock) || !isActiveAt(parsed.service, candidate.finalizedHead)) return "service-inactive";
|
|
1325
1300
|
if (!isActiveAt(parsed.key, candidate.tupleBlock) || !isActiveAt(parsed.key, candidate.finalizedHead)) return "key-inactive";
|
|
1326
|
-
|
|
1327
|
-
return void 0;
|
|
1301
|
+
return !expiryWithinServicePolicy(parsed.subscription, parsed.service, candidate.tupleBlock) || parsed.subscription.expiresAtBlock - candidate.finalizedHead <= 2 ? "subscription-expiry-invalid" : void 0;
|
|
1328
1302
|
}
|
|
1329
1303
|
async function decryptCandidate(candidate, parsed) {
|
|
1330
1304
|
let privateKey;
|
|
@@ -1388,19 +1362,14 @@ async function validateAndDecryptPublisherSubscription(candidate) {
|
|
|
1388
1362
|
if (!hasExactQueueScope(parsed.grant, decrypted.plaintext)) {
|
|
1389
1363
|
return rejectPublisherSubscription("grant-scope-invalid");
|
|
1390
1364
|
}
|
|
1391
|
-
|
|
1392
|
-
return rejectPublisherSubscription("service-limit-invalid");
|
|
1393
|
-
}
|
|
1394
|
-
return validatedPublisherSubscription(candidate, parsed, decrypted.plaintext);
|
|
1365
|
+
return filterWithinServicePolicy(parsed.service, decrypted.plaintext) ? validatedPublisherSubscription(candidate, parsed, decrypted.plaintext) : rejectPublisherSubscription("service-limit-invalid");
|
|
1395
1366
|
}
|
|
1396
1367
|
function endpointChallengeMatchesPublisherContext(challenge, context) {
|
|
1397
1368
|
const parsed = EndpointChallengeZod3.safeParse(challenge);
|
|
1398
|
-
|
|
1399
|
-
return parsed.data.chainId === context.chainId && parsed.data.publisher === context.publisher && parsed.data.subscriber === context.subscriber && parsed.data.service === context.service && parsed.data.encryptionKey === context.encryptionKey && parsed.data.keyId === context.keyId && parsed.data.subscription === context.subscription && parsed.data.grant === context.grant && parsed.data.eventKind === context.eventKind;
|
|
1369
|
+
return parsed.success && parsed.data.chainId === context.chainId && parsed.data.publisher === context.publisher && parsed.data.subscriber === context.subscriber && parsed.data.service === context.service && parsed.data.encryptionKey === context.encryptionKey && parsed.data.keyId === context.keyId && parsed.data.subscription === context.subscription && parsed.data.grant === context.grant && parsed.data.eventKind === context.eventKind;
|
|
1400
1370
|
}
|
|
1401
1371
|
async function challengeRecordMatches(record, challenge, challengeHash, responseHash) {
|
|
1402
|
-
|
|
1403
|
-
return responseHash === void 0 || record.responseHash === responseHash;
|
|
1372
|
+
return record.challengeHash === challengeHash && await endpointChallengeHash(record.challenge) === challengeHash && await endpointChallengeHash(challenge) === challengeHash && (responseHash === void 0 || record.responseHash === responseHash);
|
|
1404
1373
|
}
|
|
1405
1374
|
async function issuePublisherEndpointChallenge(input) {
|
|
1406
1375
|
const context = input.subscription.context;
|
|
@@ -1443,8 +1412,7 @@ async function beginPublisherEndpointChallengeAttempt(input) {
|
|
|
1443
1412
|
HashZod4.parse(input.challengeHash)
|
|
1444
1413
|
)) return { kind: "store-invalid" };
|
|
1445
1414
|
if ((result.kind === "started" || result.kind === "already-attempted") && result.record.state !== "attempted") return { kind: "store-invalid" };
|
|
1446
|
-
|
|
1447
|
-
return result;
|
|
1415
|
+
return result.kind === "verified" && result.record.state !== "verified" ? { kind: "store-invalid" } : result;
|
|
1448
1416
|
} catch {
|
|
1449
1417
|
return { kind: "store-unavailable" };
|
|
1450
1418
|
}
|
|
@@ -1461,10 +1429,7 @@ async function validateChallengeCompletion(input, result, challengeHash, respons
|
|
|
1461
1429
|
if (result.kind === "expired") return completeFailure("challenge-expired");
|
|
1462
1430
|
if (result.kind === "not-attempted") return completeFailure("challenge-not-attempted");
|
|
1463
1431
|
if (result.kind === "collision") return completeFailure("challenge-response-collision");
|
|
1464
|
-
|
|
1465
|
-
return completeFailure("challenge-store-invalid");
|
|
1466
|
-
}
|
|
1467
|
-
return result;
|
|
1432
|
+
return result.kind !== "duplicate" && result.kind !== "verified" || !await challengeRecordMatches(result.record, input.challenge, challengeHash, responseHash) ? completeFailure("challenge-store-invalid") : result;
|
|
1468
1433
|
}
|
|
1469
1434
|
async function completePublisherEndpointChallenge(input) {
|
|
1470
1435
|
if (!endpointChallengeMatchesPublisherContext(input.challenge, input.subscription.context)) {
|
|
@@ -1620,9 +1585,7 @@ async function readRevocations(viewer, controller, subject, atBlock) {
|
|
|
1620
1585
|
for (const claim of claims) {
|
|
1621
1586
|
if (!isLiveClaim(claim, controller, subject, WakeGrantRevocationSchema3, atBlock)) continue;
|
|
1622
1587
|
const object = await viewer.object(claim.objectHash);
|
|
1623
|
-
if (object?.assurance !== "resolved") continue;
|
|
1624
|
-
if (object.declaredSchema !== WakeGrantRevocationSchema3 || object.objectHash !== claim.objectHash) continue;
|
|
1625
|
-
if (!isRecord2(object.params) || Object.hasOwn(object.params, "schema")) continue;
|
|
1588
|
+
if (object?.assurance !== "resolved" || object.declaredSchema !== WakeGrantRevocationSchema3 || object.objectHash !== claim.objectHash || !isRecord2(object.params) || Object.hasOwn(object.params, "schema")) continue;
|
|
1626
1589
|
const revocation = asWakeGrantRevocation({ ...object.params, schema: object.declaredSchema });
|
|
1627
1590
|
if (revocation !== void 0) revoked.add(revocation.grant);
|
|
1628
1591
|
}
|
|
@@ -1654,13 +1617,7 @@ async function resolveEvidence(viewer, claim, request, atBlock, revokedGrantHash
|
|
|
1654
1617
|
});
|
|
1655
1618
|
}
|
|
1656
1619
|
function isLiveClaim(claim, controller, subject, declaredObjectSchema, atBlock) {
|
|
1657
|
-
|
|
1658
|
-
if (claim.subject !== subject) return false;
|
|
1659
|
-
if (claim.declaredObjectSchema !== declaredObjectSchema) return false;
|
|
1660
|
-
if (!isNonnegativeSafeInteger4(claim.firstBlock) || claim.firstBlock > atBlock) return false;
|
|
1661
|
-
if (!isNonnegativeSafeInteger4(claim.lastBlock) || claim.lastBlock < claim.firstBlock) return false;
|
|
1662
|
-
if (!HashZod6.safeParse(claim.firstEventHash).success) return false;
|
|
1663
|
-
return HashZod6.safeParse(claim.objectHash).success;
|
|
1620
|
+
return claim.source === controller && claim.subject === subject && claim.declaredObjectSchema === declaredObjectSchema && isNonnegativeSafeInteger4(claim.firstBlock) && claim.firstBlock <= atBlock && isNonnegativeSafeInteger4(claim.lastBlock) && claim.lastBlock >= claim.firstBlock && HashZod6.safeParse(claim.firstEventHash).success && HashZod6.safeParse(claim.objectHash).success;
|
|
1664
1621
|
}
|
|
1665
1622
|
function parseExactGrantObject(object, expectedObjectHash) {
|
|
1666
1623
|
if (object?.assurance !== "resolved") return void 0;
|
|
@@ -1844,8 +1801,7 @@ async function verifyJwtProfile(token, audience, nowSeconds) {
|
|
|
1844
1801
|
return reject2("jwt-malformed", [errorMessage2(error)]);
|
|
1845
1802
|
}
|
|
1846
1803
|
if (!verified.ok) {
|
|
1847
|
-
|
|
1848
|
-
return reject2(classifySdkJwtFailure(verified.reasons), verified.reasons);
|
|
1804
|
+
return Object.hasOwn(verified.payload ?? {}, "nbf") ? reject2("jwt-nbf-not-allowed") : reject2(classifySdkJwtFailure(verified.reasons), verified.reasons);
|
|
1849
1805
|
}
|
|
1850
1806
|
const wireResult = parseStrictJwtWire(verified.header, verified.payload, audience);
|
|
1851
1807
|
if (!wireResult.ok) return wireResult;
|
|
@@ -1866,8 +1822,7 @@ async function verifyJwtProfile(token, audience, nowSeconds) {
|
|
|
1866
1822
|
function parseStrictJwtWire(header, payload, audience) {
|
|
1867
1823
|
const headerResult = WakeJwtHeaderZod.safeParse(header);
|
|
1868
1824
|
if (!headerResult.success) {
|
|
1869
|
-
|
|
1870
|
-
return reject2("jwt-header-invalid", zodDetails(headerResult.error.issues));
|
|
1825
|
+
return NormalizedAddressZod7.safeParse(header.kid).success ? reject2("jwt-header-invalid", zodDetails(headerResult.error.issues)) : reject2("jwt-identity-invalid");
|
|
1871
1826
|
}
|
|
1872
1827
|
if (Object.hasOwn(payload, "nbf")) return reject2("jwt-nbf-not-allowed");
|
|
1873
1828
|
if (!NormalizedAddressZod7.safeParse(payload.iss).success) return reject2("jwt-identity-invalid");
|
|
@@ -1890,16 +1845,12 @@ function classifySdkJwtFailure(reasons) {
|
|
|
1890
1845
|
if (reasons.some((reason) => reason.startsWith("unsupported alg:") || reason.startsWith("unsupported typ:"))) {
|
|
1891
1846
|
return "jwt-header-invalid";
|
|
1892
1847
|
}
|
|
1893
|
-
|
|
1894
|
-
return "jwt-identity-invalid";
|
|
1895
|
-
}
|
|
1896
|
-
return "jwt-invalid";
|
|
1848
|
+
return reasons.some((reason) => reason.startsWith("invalid public key:") || reason.startsWith("public key does not derive to kid:") || reason === "header.kid does not match payload.iss") ? "jwt-identity-invalid" : "jwt-invalid";
|
|
1897
1849
|
}
|
|
1898
1850
|
function malformedWake(body, issues) {
|
|
1899
1851
|
const details = zodDetails(issues);
|
|
1900
1852
|
if (hasInvertedSafeRange(body)) return reject2("range-invalid", details);
|
|
1901
|
-
|
|
1902
|
-
return reject2("event-malformed", details);
|
|
1853
|
+
return reject2(isRecord3(body) && Object.hasOwn(body, "wakeId") && issues.some((issue) => issue.path[0] === "wakeId") ? "wake-id-invalid" : "event-malformed", details);
|
|
1903
1854
|
}
|
|
1904
1855
|
function hasInvertedSafeRange(value) {
|
|
1905
1856
|
if (!isRecord3(value)) return false;
|