@tinycloud/sdk-core 3.10.0-beta.2 → 3.11.0-beta.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.cjs +58 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.js +58 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -288,6 +288,7 @@ __export(index_exports, {
|
|
|
288
288
|
canonicalizeSecretScope: () => import_sdk_services10.canonicalizeSecretScope,
|
|
289
289
|
canonicalizeSignedObjectUnsigned: () => canonicalizeSignedObjectUnsigned,
|
|
290
290
|
canonicalizeUnifiedPolicyCapability: () => canonicalizeUnifiedPolicyCapability,
|
|
291
|
+
checkChangedExpiration: () => checkChangedExpiration,
|
|
291
292
|
checkDecryptInvocationInput: () => import_sdk_services10.checkDecryptInvocationInput,
|
|
292
293
|
checkNodeInfo: () => checkNodeInfo,
|
|
293
294
|
classifyRegistryLookup: () => classifyRegistryLookup,
|
|
@@ -16679,7 +16680,7 @@ function diffImmutableSiweFields(original, signed, options2) {
|
|
|
16679
16680
|
"requestId",
|
|
16680
16681
|
"nonRecapResources"
|
|
16681
16682
|
];
|
|
16682
|
-
const keys = options2?.originalHasRecap ? baseKeys : [...baseKeys, "statement"];
|
|
16683
|
+
const keys = (options2?.originalHasRecap ? baseKeys : [...baseKeys, "statement"]).filter((key) => !(options2?.allowExpirationChange === true && key === "expirationTime"));
|
|
16683
16684
|
const diffs = [];
|
|
16684
16685
|
for (const key of keys) {
|
|
16685
16686
|
const a = original[key] ?? "";
|
|
@@ -16690,6 +16691,62 @@ function diffImmutableSiweFields(original, signed, options2) {
|
|
|
16690
16691
|
}
|
|
16691
16692
|
return diffs;
|
|
16692
16693
|
}
|
|
16694
|
+
var CHANGED_EXPIRY_MIN_REMAINING_MS = 6e4;
|
|
16695
|
+
var ISO_INSTANT = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
16696
|
+
function parseInstantMs(value) {
|
|
16697
|
+
const match = value === void 0 ? null : ISO_INSTANT.exec(value);
|
|
16698
|
+
if (!match || value === void 0) return void 0;
|
|
16699
|
+
const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
16700
|
+
if (new Date(Date.UTC(year, month - 1, day)).getUTCDate() !== day) return void 0;
|
|
16701
|
+
const ms2 = Date.parse(value);
|
|
16702
|
+
return Number.isFinite(ms2) ? ms2 : void 0;
|
|
16703
|
+
}
|
|
16704
|
+
var EXPIRATION_LINE = /^Expiration Time:/;
|
|
16705
|
+
function hasCanonicalExpirationLine(siwe) {
|
|
16706
|
+
if (siwe.includes("\r")) return false;
|
|
16707
|
+
const lines = siwe.split("\n");
|
|
16708
|
+
const index = lines.findIndex((line) => EXPIRATION_LINE.test(line));
|
|
16709
|
+
if (index < 0 || !/^Expiration Time: \S+$/.test(lines[index])) return false;
|
|
16710
|
+
const resources = lines.indexOf("Resources:", 4);
|
|
16711
|
+
return resources < 0 || index < resources;
|
|
16712
|
+
}
|
|
16713
|
+
function checkChangedExpiration(input) {
|
|
16714
|
+
const nowMs = input.now instanceof Date ? input.now.getTime() : input.now;
|
|
16715
|
+
if (!Number.isFinite(nowMs)) return "expiry check needs a finite current time";
|
|
16716
|
+
const maxMs = input.maxExpiresAt === void 0 ? void 0 : input.maxExpiresAt instanceof Date ? input.maxExpiresAt.getTime() : input.maxExpiresAt;
|
|
16717
|
+
if (maxMs !== void 0 && !Number.isFinite(new Date(maxMs).getTime())) return "expiry check needs a finite maximum";
|
|
16718
|
+
const originalHasRecap = input.originalHasRecap ?? /(?:^|\n)-\s+urn:recap:/i.test(input.preparedSiwe);
|
|
16719
|
+
const countLines = (siwe) => siwe.split(/\r?\n/).filter((line) => EXPIRATION_LINE.test(line)).length;
|
|
16720
|
+
if (countLines(input.preparedSiwe) !== 1 || countLines(input.signedSiwe) !== 1) {
|
|
16721
|
+
return "expiry check needs exactly one Expiration Time line in both messages";
|
|
16722
|
+
}
|
|
16723
|
+
if (!hasCanonicalExpirationLine(input.signedSiwe)) {
|
|
16724
|
+
return "the Expiration Time line is not in canonical SIWE form";
|
|
16725
|
+
}
|
|
16726
|
+
const prepared = extractImmutableSiweFields(input.preparedSiwe);
|
|
16727
|
+
const signed = extractImmutableSiweFields(input.signedSiwe);
|
|
16728
|
+
const drift = diffImmutableSiweFields(prepared, signed, { originalHasRecap, allowExpirationChange: true });
|
|
16729
|
+
if (drift.length > 0) return `altered immutable SIWE fields: ${drift.join(", ")}`;
|
|
16730
|
+
if (signed.expirationTime === prepared.expirationTime) return null;
|
|
16731
|
+
const expiresAt = parseInstantMs(signed.expirationTime);
|
|
16732
|
+
if (expiresAt === void 0) return "expiry is not a valid timestamp";
|
|
16733
|
+
if (expiresAt <= nowMs + CHANGED_EXPIRY_MIN_REMAINING_MS) {
|
|
16734
|
+
return "expiry must be more than 60 seconds from now; choose a longer expiry";
|
|
16735
|
+
}
|
|
16736
|
+
for (const [label, value] of [["Issued At", prepared.issuedAt], ["Not Before", prepared.notBefore]]) {
|
|
16737
|
+
if (value === void 0 || value === "") continue;
|
|
16738
|
+
const bound = parseInstantMs(value);
|
|
16739
|
+
if (bound === void 0) return `${label} is not a valid timestamp`;
|
|
16740
|
+
if (expiresAt <= bound) return `expiry must be after ${label}; choose a later expiry`;
|
|
16741
|
+
}
|
|
16742
|
+
if (maxMs !== void 0 && expiresAt > maxMs) {
|
|
16743
|
+
return `expiry is later than the maximum for this request (the latest allowed is ${new Date(maxMs).toISOString()}); choose an earlier expiry`;
|
|
16744
|
+
}
|
|
16745
|
+
if (expiresAt > nowMs + EXPIRY.MAX_MS) {
|
|
16746
|
+
return "expiry is more than 10 years away, the longest this SDK accepts; choose a shorter expiry";
|
|
16747
|
+
}
|
|
16748
|
+
return null;
|
|
16749
|
+
}
|
|
16693
16750
|
function extractRecapAttenuations(siwe) {
|
|
16694
16751
|
const merged = {};
|
|
16695
16752
|
const lines = siwe.split(/\r?\n/);
|