@fedify/fedify 2.4.0-dev.2122 → 2.4.0-dev.2129
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/{builder-BCXywsZF.mjs → builder-C0bxZDL0.mjs} +3 -3
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-Fxd45Oy5.mjs → compound-proof-D9Kljk_7.mjs} +3 -3
- package/dist/{context-tOiJfBoD.d.ts → context-Cz1w5Krc.d.ts} +31 -5
- package/dist/{context-CoNRxGYp.mjs → context-DfSVPcJ8.mjs} +6 -3
- package/dist/{context-SMNOiiY6.d.cts → context-Dvec_D_h.d.cts} +31 -5
- package/dist/{deno-BZrnW0Qz.mjs → deno-_o3lkDlG.mjs} +1 -1
- package/dist/{docloader-3BHaS20Z.mjs → docloader-BbS0rO-Y.mjs} +7 -7
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +4 -4
- package/dist/federation/handler.test.mjs +6 -6
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +8 -8
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +6 -6
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.d.mts +2 -0
- package/dist/federation/portable-chain.test.mjs +358 -0
- package/dist/federation/portable-gateway-keys.test.mjs +77 -6
- package/dist/federation/portable-inbox.test.mjs +9 -4
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +2 -2
- package/dist/federation/tasks/tasks.test.mjs +3 -3
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{federation-Ml6NrgRV.cjs → federation-DRY8KrkB.cjs} +46 -22
- package/dist/{http-4bmgw-mA.cjs → http-B1J6E-bT.cjs} +384 -33
- package/dist/{http-B9BQDNIy.mjs → http-BpOiZE09.mjs} +18 -12
- package/dist/{http-D76Py0M4.d.cts → http-C-x_OLSp.d.ts} +57 -14
- package/dist/{http-BETASGl0.js → http-C2M6wcs8.js} +374 -35
- package/dist/{http-BrQgkJay.d.ts → http-CjezPjFX.d.cts} +57 -14
- package/dist/{key-PyYvun0F.mjs → key-DolJjJab.mjs} +103 -16
- package/dist/{kv-cache-CPqUxRL3.mjs → kv-cache-Bq2cah0c.mjs} +1 -1
- package/dist/{kv-cache-C4mv2ZFQ.js → kv-cache-D7TiyMxv.js} +6 -6
- package/dist/{kv-cache-D2Bz6t_c.cjs → kv-cache-D9nRbG2Q.cjs} +6 -6
- package/dist/{ld-u4JOD4iO.mjs → ld-Dwc176V4.mjs} +3 -3
- package/dist/{metrics-DCLoLvLz.mjs → metrics-CDaHfBXY.mjs} +1 -1
- package/dist/{middleware-B7bmtONC.mjs → middleware-CmB1FD8A.mjs} +1 -1
- package/dist/{middleware-DWlAGlyP.js → middleware-CylX-pvI.js} +52 -28
- package/dist/{middleware-CgOqRkK-.mjs → middleware-DN3MdTDg.mjs} +64 -39
- package/dist/{mod-CTh7ijx5.d.ts → mod-Bz9tFXI2.d.ts} +14 -3
- package/dist/{mod-Cwdt_CWU.d.ts → mod-CZetqT5h.d.ts} +1 -1
- package/dist/{mod-Cr79cQlc.d.cts → mod-D4g9ffEn.d.cts} +1 -1
- package/dist/{mod-DnElMslb.d.cts → mod-DGOIxEfb.d.cts} +1 -1
- package/dist/{mod-DMdGFMEl.d.cts → mod-S--JxYjo.d.cts} +14 -3
- package/dist/{mod-COWgSo2v.d.ts → mod-owwElvpw.d.ts} +1 -1
- package/dist/mod.cjs +8 -8
- package/dist/mod.d.cts +5 -5
- package/dist/mod.d.ts +5 -5
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/{owner-CPFM-sqo.mjs → owner-BNHhwjNu.mjs} +37 -4
- package/dist/{sig-C1xOA4ml.js → portable-collection-CRpTUHCY.mjs} +5 -4
- package/dist/portable-collection-CgglAI9B.js +656 -0
- package/dist/{sig-Cb9VSeiF.cjs → portable-collection-PTGD0q70.cjs} +253 -2
- package/dist/portable-key-DqX2emHQ.mjs +395 -0
- package/dist/{portable-key-id-T7lecIbt.mjs → portable-key-id-Bg259c4Z.mjs} +69 -2
- package/dist/{proof-BCOg7Njv.mjs → proof-B4_0E-KU.mjs} +5 -5
- package/dist/{send-C8eOPat3.mjs → send-Dpu5qbP5.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +5 -6
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +2 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +20 -431
- package/dist/sig/portable-key.test.mjs +479 -5
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{temporal-vjHOhBpy.mjs → temporal-78JVR3GK.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +30 -4
- package/dist/testing/mod.mjs +2 -2
- package/dist/{testing-BWq1dCzx.mjs → testing-otQhu4aD.mjs} +1 -1
- package/dist/utils/docloader.test.mjs +81 -2
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +7 -7
- package/dist/owner-DkA0Lz7v.cjs +0 -225
- package/dist/owner-wNinn7RK.js +0 -215
- package/dist/portable-key-DyylakVV.mjs +0 -214
|
@@ -2,12 +2,12 @@ import { Temporal } from "temporal-polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
5
|
-
import { i as fetchKey } from "../key-
|
|
6
|
-
import { h as verifyJsonLd, p as signJsonLd } from "../ld-
|
|
7
|
-
import { n as createProof, u as verifyProof } from "../proof-
|
|
8
|
-
import { d as verifyRequest, f as verifyRequestDetailed, l as signRequest } from "../http-
|
|
5
|
+
import { i as fetchKey } from "../key-DolJjJab.mjs";
|
|
6
|
+
import { h as verifyJsonLd, p as signJsonLd } from "../ld-Dwc176V4.mjs";
|
|
7
|
+
import { n as createProof, u as verifyProof } from "../proof-B4_0E-KU.mjs";
|
|
8
|
+
import { d as verifyRequest, f as verifyRequestDetailed, l as signRequest } from "../http-BpOiZE09.mjs";
|
|
9
9
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
10
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-
|
|
10
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-BNHhwjNu.mjs";
|
|
11
11
|
import { t as KvKeyCache } from "../keycache-BInaECGj.mjs";
|
|
12
12
|
import { Create, CryptographicKey, Multikey, Note, Person } from "@fedify/vocab";
|
|
13
13
|
import { test } from "@fedify/fixture";
|
|
@@ -715,5 +715,479 @@ test("verifyRequest() binds gateway keys to the actor whose document is signed",
|
|
|
715
715
|
contextLoader: shiftingContextLoader
|
|
716
716
|
}), null);
|
|
717
717
|
});
|
|
718
|
+
test("verifyRequest() matches gateway keys listed under ap: URIs", async () => {
|
|
719
|
+
const portableKeyId = parseIri(`${actorId}#main-key`);
|
|
720
|
+
const cases = {
|
|
721
|
+
"both properties": await actorJson({ key: portableKeyId }),
|
|
722
|
+
"assertionMethod only": await actorJson({
|
|
723
|
+
key: portableKeyId,
|
|
724
|
+
publicKey: null
|
|
725
|
+
}),
|
|
726
|
+
"publicKey only": await actorJson({
|
|
727
|
+
key: portableKeyId,
|
|
728
|
+
assertionMethod: false
|
|
729
|
+
})
|
|
730
|
+
};
|
|
731
|
+
for (const [name, document] of Object.entries(cases)) {
|
|
732
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(document) });
|
|
733
|
+
for (const spec of specs) {
|
|
734
|
+
const key = await verifyRequest(await signedRequest(spec), {
|
|
735
|
+
documentLoader,
|
|
736
|
+
contextLoader,
|
|
737
|
+
spec
|
|
738
|
+
});
|
|
739
|
+
strictEqual(key?.id?.href, keyId.href, `${name}, ${spec}`);
|
|
740
|
+
strictEqual(key?.ownerId?.href, parseIri(actorId).href, name);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
test("verifyRequest() rejects ambiguous or foreign aliases of gateway keys", async () => {
|
|
745
|
+
const portableKeyId = `${actorId}#main-key`;
|
|
746
|
+
const base = await actorJson();
|
|
747
|
+
const assertionMethod = base.assertionMethod;
|
|
748
|
+
const publicKey = base.publicKey;
|
|
749
|
+
const cases = {
|
|
750
|
+
"an exact entry and an ap: alias in assertionMethod": {
|
|
751
|
+
...base,
|
|
752
|
+
assertionMethod: [assertionMethod, {
|
|
753
|
+
...assertionMethod,
|
|
754
|
+
id: portableKeyId
|
|
755
|
+
}]
|
|
756
|
+
},
|
|
757
|
+
"a reference and an embedded ap: alias in assertionMethod": {
|
|
758
|
+
...base,
|
|
759
|
+
assertionMethod: [keyId.href, {
|
|
760
|
+
...assertionMethod,
|
|
761
|
+
id: portableKeyId
|
|
762
|
+
}]
|
|
763
|
+
},
|
|
764
|
+
"an exact entry and an ap: alias in publicKey": {
|
|
765
|
+
...base,
|
|
766
|
+
publicKey: [publicKey, {
|
|
767
|
+
...publicKey,
|
|
768
|
+
id: portableKeyId
|
|
769
|
+
}]
|
|
770
|
+
},
|
|
771
|
+
"a key of another gateway": await actorJson({ key: new URL(`${compatibleId(gw2)}#main-key`) }),
|
|
772
|
+
"an ap: key ID with dot segments": {
|
|
773
|
+
...base,
|
|
774
|
+
assertionMethod: {
|
|
775
|
+
...assertionMethod,
|
|
776
|
+
id: portableKeyId.replace("/actor#", "/x/../actor#")
|
|
777
|
+
},
|
|
778
|
+
publicKey: {
|
|
779
|
+
...publicKey,
|
|
780
|
+
id: portableKeyId.replace("/actor#", "/x/../actor#")
|
|
781
|
+
}
|
|
782
|
+
},
|
|
783
|
+
"a compatible key ID with dot segments": {
|
|
784
|
+
...base,
|
|
785
|
+
assertionMethod: {
|
|
786
|
+
...assertionMethod,
|
|
787
|
+
id: keyId.href.replace("/actor#", "/x/../actor#")
|
|
788
|
+
},
|
|
789
|
+
publicKey: {
|
|
790
|
+
...publicKey,
|
|
791
|
+
id: keyId.href.replace("/actor#", "/x/../actor#")
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
for (const [name, document] of Object.entries(cases)) {
|
|
796
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(document) });
|
|
797
|
+
strictEqual(await verifyRequest(await signedRequest(), {
|
|
798
|
+
documentLoader,
|
|
799
|
+
contextLoader
|
|
800
|
+
}), null, name);
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
test("verifyRequest() refuses key IDs whose identity URL parsing changes", async () => {
|
|
804
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await actorJson()) });
|
|
805
|
+
const request = await signedRequest("draft-cavage-http-signatures-12");
|
|
806
|
+
const dotted = keyId.href.replace("/actor#", "/x/../actor#");
|
|
807
|
+
const headers = new Headers(request.headers);
|
|
808
|
+
headers.set("Signature", headers.get("Signature").replace(keyId.href, dotted));
|
|
809
|
+
strictEqual(await verifyRequest(new Request(request, { headers }), {
|
|
810
|
+
documentLoader,
|
|
811
|
+
contextLoader
|
|
812
|
+
}), null);
|
|
813
|
+
strictEqual(documentLoader.fetched.length, 0);
|
|
814
|
+
const dottedPortable = `${actorId.replace("/actor", "/x/../actor")}#main-key`;
|
|
815
|
+
for (const id of [
|
|
816
|
+
dotted,
|
|
817
|
+
dottedPortable,
|
|
818
|
+
` ${dotted}`,
|
|
819
|
+
` ${dottedPortable}`,
|
|
820
|
+
` ${parseIri(dottedPortable).href}`,
|
|
821
|
+
dottedPortable.replace("ap+ef61:", "ap+ ef61:"),
|
|
822
|
+
dotted.replace("did:key:", "did:ke y:"),
|
|
823
|
+
`${gw1}/.well-known/apgateway/${did}/../../../users/alice#main-key`,
|
|
824
|
+
` ap://not-a-did/actor#main-key`
|
|
825
|
+
]) {
|
|
826
|
+
let error;
|
|
827
|
+
try {
|
|
828
|
+
await fetchKey(id, CryptographicKey, {
|
|
829
|
+
documentLoader,
|
|
830
|
+
contextLoader
|
|
831
|
+
});
|
|
832
|
+
} catch (e) {
|
|
833
|
+
error = e;
|
|
834
|
+
}
|
|
835
|
+
ok(error instanceof TypeError, id);
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
const apKeyId = parseIri(`${actorId}#main-key`);
|
|
839
|
+
function hinted(...gateways) {
|
|
840
|
+
const query = gateways.map((g) => `@gateway=${encodeURIComponent(g)}`).join("&");
|
|
841
|
+
return parseIri(`${actorId}${query === "" ? "" : `?${query}`}#main-key`);
|
|
842
|
+
}
|
|
843
|
+
async function apActorJson(options = {}) {
|
|
844
|
+
return await actorJson({
|
|
845
|
+
key: apKeyId,
|
|
846
|
+
...options
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
test("verifyRequest() accepts keys of portable actors at ap: key IDs", async () => {
|
|
850
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await apActorJson()) });
|
|
851
|
+
const hintedKeyId = hinted(gw1);
|
|
852
|
+
for (const spec of specs) {
|
|
853
|
+
const key = await verifyRequest(await signedRequest(spec, hintedKeyId), {
|
|
854
|
+
documentLoader,
|
|
855
|
+
contextLoader,
|
|
856
|
+
spec
|
|
857
|
+
});
|
|
858
|
+
ok(key != null, spec);
|
|
859
|
+
strictEqual(key.id?.href, hintedKeyId.href, spec);
|
|
860
|
+
strictEqual(key.ownerId?.href, parseIri(actorId).href, spec);
|
|
861
|
+
}
|
|
862
|
+
const raw = `ap://${did}/actor?@gateway=${encodeURIComponent(gw1)}#main-key`;
|
|
863
|
+
for (const written of [raw, raw.replace(/^ap:/, "ap+ef61:")]) {
|
|
864
|
+
const request = await signedRequest("draft-cavage-http-signatures-12", hintedKeyId);
|
|
865
|
+
const headers = new Headers(request.headers);
|
|
866
|
+
headers.set("Signature", headers.get("Signature").replace(hintedKeyId.href, written));
|
|
867
|
+
strictEqual((await verifyRequest(new Request(request, { headers }), {
|
|
868
|
+
documentLoader,
|
|
869
|
+
contextLoader
|
|
870
|
+
}))?.ownerId?.href, parseIri(actorId).href, written);
|
|
871
|
+
}
|
|
872
|
+
deepStrictEqual([...new Set(documentLoader.fetched)], [compatibleId(gw1)]);
|
|
873
|
+
});
|
|
874
|
+
test("verifyRequest() asks the document loader for ap: key IDs without hints", async () => {
|
|
875
|
+
const documentLoader = createLoader({ [actorId]: await sign(await apActorJson()) });
|
|
876
|
+
strictEqual((await verifyRequest(await signedRequest(void 0, apKeyId), {
|
|
877
|
+
documentLoader,
|
|
878
|
+
contextLoader
|
|
879
|
+
}))?.ownerId?.href, parseIri(actorId).href);
|
|
880
|
+
deepStrictEqual(documentLoader.fetched, [actorId]);
|
|
881
|
+
const result = await verifyRequestDetailed(await signedRequest(void 0, apKeyId), {
|
|
882
|
+
documentLoader: createLoader({}),
|
|
883
|
+
contextLoader
|
|
884
|
+
});
|
|
885
|
+
ok(!result.verified);
|
|
886
|
+
strictEqual(result.reason.type, "keyFetchError");
|
|
887
|
+
});
|
|
888
|
+
test("verifyRequest() rejects keys at ap: key IDs that portable actors do not vouch for", async () => {
|
|
889
|
+
const unsigned = await apActorJson();
|
|
890
|
+
const ordinaryActorId = "https://gw1.example/users/alice";
|
|
891
|
+
const cases = {
|
|
892
|
+
"an unsigned actor document": unsigned,
|
|
893
|
+
"an actor document signed by another DID": await sign(unsigned, otherKeyPair.privateKey, `${otherDid}#${otherDid.slice(8)}`),
|
|
894
|
+
"a key missing from both assertionMethod and publicKey": await sign(await apActorJson({
|
|
895
|
+
assertionMethod: false,
|
|
896
|
+
publicKey: null
|
|
897
|
+
})),
|
|
898
|
+
"a key referred to by URL": await sign({
|
|
899
|
+
...await apActorJson({
|
|
900
|
+
publicKey: null,
|
|
901
|
+
assertionMethod: false
|
|
902
|
+
}),
|
|
903
|
+
assertionMethod: [apKeyId.href]
|
|
904
|
+
}),
|
|
905
|
+
"a key only in publicKey without an owner": await sign(withoutPublicKeyOwner(await apActorJson({ assertionMethod: false }))),
|
|
906
|
+
"a publicKey entry with other key material": await sign(await apActorJson({ publicKey: rsaPublicKey3.publicKey })),
|
|
907
|
+
"a key only at a compatible identifier": await sign(await actorJson()),
|
|
908
|
+
"an actor without gateways": await sign(await apActorJson({ gateways: [] })),
|
|
909
|
+
"the document of another actor": await sign(await apActorJson({ id: `${actorId}/other` })),
|
|
910
|
+
"an ordinary actor": await actorJson({
|
|
911
|
+
id: ordinaryActorId,
|
|
912
|
+
key: apKeyId
|
|
913
|
+
}),
|
|
914
|
+
"a standalone key": {
|
|
915
|
+
"@context": "https://w3id.org/security/v1",
|
|
916
|
+
id: apKeyId.href,
|
|
917
|
+
type: "Key",
|
|
918
|
+
owner: actorId,
|
|
919
|
+
publicKeyPem: await exportSpki(gatewayPublicKey)
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
for (const [name, document] of Object.entries(cases)) {
|
|
923
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: document });
|
|
924
|
+
strictEqual(await verifyRequest(await signedRequest(void 0, hinted(gw1)), {
|
|
925
|
+
documentLoader,
|
|
926
|
+
contextLoader
|
|
927
|
+
}), null, name);
|
|
928
|
+
}
|
|
929
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await apActorJson()) });
|
|
930
|
+
strictEqual(await verifyRequest(await signedRequest(void 0, parseIri(`${actorId}?@gateway=${encodeURIComponent(gw1)}`)), {
|
|
931
|
+
documentLoader,
|
|
932
|
+
contextLoader
|
|
933
|
+
}), null);
|
|
934
|
+
strictEqual(documentLoader.fetched.length, 0);
|
|
935
|
+
});
|
|
936
|
+
test("verifyRequest() tries the gateways of ap: key IDs in order", async () => {
|
|
937
|
+
const signed = await sign(await apActorJson());
|
|
938
|
+
const cases = {
|
|
939
|
+
"an invalid document at the first gateway": {
|
|
940
|
+
[compatibleId(gw1)]: await apActorJson(),
|
|
941
|
+
[compatibleId(gw2)]: signed
|
|
942
|
+
},
|
|
943
|
+
"an unreachable first gateway": { [compatibleId(gw2)]: signed }
|
|
944
|
+
};
|
|
945
|
+
for (const [name, responses] of Object.entries(cases)) {
|
|
946
|
+
const documentLoader = createLoader(responses);
|
|
947
|
+
strictEqual((await verifyRequest(await signedRequest(void 0, hinted(gw1, gw2)), {
|
|
948
|
+
documentLoader,
|
|
949
|
+
contextLoader
|
|
950
|
+
}))?.ownerId?.href, parseIri(actorId).href, name);
|
|
951
|
+
deepStrictEqual(documentLoader.fetched, [compatibleId(gw1), compatibleId(gw2)], name);
|
|
952
|
+
}
|
|
953
|
+
const documentLoader = createLoader({
|
|
954
|
+
[compatibleId(gw1)]: signed,
|
|
955
|
+
[compatibleId(gw2)]: signed
|
|
956
|
+
});
|
|
957
|
+
ok(await verifyRequest(await signedRequest(void 0, hinted(gw1, gw2)), {
|
|
958
|
+
documentLoader,
|
|
959
|
+
contextLoader
|
|
960
|
+
}) != null);
|
|
961
|
+
deepStrictEqual(documentLoader.fetched, [compatibleId(gw1)]);
|
|
962
|
+
const gateways = Array.from({ length: 7 }, (_, i) => `https://gw${i + 10}.example`);
|
|
963
|
+
const many = createLoader({});
|
|
964
|
+
ok(!(await verifyRequestDetailed(await signedRequest(void 0, hinted(...gateways)), {
|
|
965
|
+
documentLoader: many,
|
|
966
|
+
contextLoader
|
|
967
|
+
})).verified);
|
|
968
|
+
deepStrictEqual(many.fetched, gateways.slice(0, 5).map((g) => compatibleId(g)));
|
|
969
|
+
});
|
|
970
|
+
function failingLoader(responses) {
|
|
971
|
+
const fetched = [];
|
|
972
|
+
const loader = (url) => {
|
|
973
|
+
fetched.push(url);
|
|
974
|
+
const response = responses[url.replace(/#.*$/, "")] ?? 404;
|
|
975
|
+
if (typeof response === "number") return Promise.reject(new FetchError(url, `HTTP ${response}`, new Response(null, { status: response })));
|
|
976
|
+
return Promise.resolve({
|
|
977
|
+
contextUrl: null,
|
|
978
|
+
documentUrl: url,
|
|
979
|
+
document: structuredClone(response)
|
|
980
|
+
});
|
|
981
|
+
};
|
|
982
|
+
return Object.assign(loader, { fetched });
|
|
983
|
+
}
|
|
984
|
+
test("verifyRequest() reports why keys at ap: key IDs could not be looked up", async () => {
|
|
985
|
+
const hintedKeyId = hinted(gw1, gw2);
|
|
986
|
+
const invalid = await apActorJson();
|
|
987
|
+
const cases = [
|
|
988
|
+
{
|
|
989
|
+
name: "every gateway serves an invalid document",
|
|
990
|
+
responses: {
|
|
991
|
+
[compatibleId(gw1)]: invalid,
|
|
992
|
+
[compatibleId(gw2)]: invalid
|
|
993
|
+
},
|
|
994
|
+
reason: "invalidSignature",
|
|
995
|
+
cached: true
|
|
996
|
+
},
|
|
997
|
+
{
|
|
998
|
+
name: "every gateway responds with 410 Gone",
|
|
999
|
+
responses: {
|
|
1000
|
+
[compatibleId(gw1)]: 410,
|
|
1001
|
+
[compatibleId(gw2)]: 410
|
|
1002
|
+
},
|
|
1003
|
+
reason: "keyFetchError",
|
|
1004
|
+
status: 410,
|
|
1005
|
+
cached: true
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
name: "the gateways respond with different statuses",
|
|
1009
|
+
responses: {
|
|
1010
|
+
[compatibleId(gw1)]: 404,
|
|
1011
|
+
[compatibleId(gw2)]: 503
|
|
1012
|
+
},
|
|
1013
|
+
reason: "keyFetchError",
|
|
1014
|
+
cached: true
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
name: "one gateway serves an invalid document, the other is gone",
|
|
1018
|
+
responses: {
|
|
1019
|
+
[compatibleId(gw1)]: invalid,
|
|
1020
|
+
[compatibleId(gw2)]: 410
|
|
1021
|
+
},
|
|
1022
|
+
reason: "keyFetchError",
|
|
1023
|
+
cached: false
|
|
1024
|
+
}
|
|
1025
|
+
];
|
|
1026
|
+
for (const { name, responses, reason, status, cached } of cases) for (const spec of specs) {
|
|
1027
|
+
const documentLoader = failingLoader(responses);
|
|
1028
|
+
const keyCache = new KvKeyCache(new MemoryKvStore(), ["pk"]);
|
|
1029
|
+
const options = {
|
|
1030
|
+
documentLoader,
|
|
1031
|
+
contextLoader,
|
|
1032
|
+
keyCache,
|
|
1033
|
+
spec
|
|
1034
|
+
};
|
|
1035
|
+
for (let i = 0; i < 2; i++) {
|
|
1036
|
+
const result = await verifyRequestDetailed(await signedRequest(spec, hintedKeyId), options);
|
|
1037
|
+
ok(!result.verified, `${name}, ${spec}`);
|
|
1038
|
+
strictEqual(result.reason.type, reason, `${name}, ${spec}`);
|
|
1039
|
+
if (result.reason.type === "keyFetchError") strictEqual("status" in result.reason.result ? result.reason.result.status : void 0, status, `${name}, ${spec}`);
|
|
1040
|
+
}
|
|
1041
|
+
strictEqual(documentLoader.fetched.length, cached ? 2 : 4, `${name}, ${spec}`);
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
test("verifyRequest() accepts keys at ap: key IDs only for HTTP Signatures", async () => {
|
|
1045
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await apActorJson()) });
|
|
1046
|
+
const hintedKeyId = hinted(gw1);
|
|
1047
|
+
const keyCache = new KvKeyCache(new MemoryKvStore(), ["pk"]);
|
|
1048
|
+
const options = {
|
|
1049
|
+
documentLoader,
|
|
1050
|
+
contextLoader,
|
|
1051
|
+
keyCache
|
|
1052
|
+
};
|
|
1053
|
+
for (const cls of [CryptographicKey, Multikey]) strictEqual((cls === CryptographicKey ? await fetchKey(hintedKeyId, CryptographicKey, options) : await fetchKey(hintedKeyId, Multikey, options)).key, null);
|
|
1054
|
+
strictEqual(documentLoader.fetched.length, 0);
|
|
1055
|
+
for (let i = 0; i < 3; i++) {
|
|
1056
|
+
const key = await verifyRequest(await signedRequest(void 0, hintedKeyId), options);
|
|
1057
|
+
strictEqual(key?.id?.href, hintedKeyId.href);
|
|
1058
|
+
strictEqual(key?.ownerId?.href, parseIri(actorId).href);
|
|
1059
|
+
}
|
|
1060
|
+
strictEqual(documentLoader.fetched.length, 1);
|
|
1061
|
+
for (const cls of [CryptographicKey, Multikey]) strictEqual((cls === CryptographicKey ? await fetchKey(hintedKeyId, CryptographicKey, options) : await fetchKey(hintedKeyId, Multikey, options)).key, null);
|
|
1062
|
+
const document = {
|
|
1063
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
1064
|
+
type: "Create",
|
|
1065
|
+
id: "https://gw1.example/activities/1",
|
|
1066
|
+
actor: compatibleId(gw1)
|
|
1067
|
+
};
|
|
1068
|
+
const { signature } = await signJsonLd(document, rsaPrivateKey2, hintedKeyId, { contextLoader });
|
|
1069
|
+
ok(!await verifyJsonLd({
|
|
1070
|
+
...document,
|
|
1071
|
+
signature
|
|
1072
|
+
}, options));
|
|
1073
|
+
strictEqual(documentLoader.fetched.length, 1);
|
|
1074
|
+
const legacyCache = {
|
|
1075
|
+
get: () => Promise.resolve(new CryptographicKey({
|
|
1076
|
+
id: hintedKeyId,
|
|
1077
|
+
owner: parseIri(actorId),
|
|
1078
|
+
publicKey: gatewayPublicKey
|
|
1079
|
+
})),
|
|
1080
|
+
set: () => Promise.resolve()
|
|
1081
|
+
};
|
|
1082
|
+
const empty = createLoader({});
|
|
1083
|
+
strictEqual(await verifyRequest(await signedRequest(void 0, hintedKeyId), {
|
|
1084
|
+
documentLoader: empty,
|
|
1085
|
+
contextLoader,
|
|
1086
|
+
keyCache: legacyCache
|
|
1087
|
+
}), null);
|
|
1088
|
+
strictEqual(empty.fetched.length, 1);
|
|
1089
|
+
});
|
|
1090
|
+
test("verifyRequest() refreshes a cached key at an ap: key ID that fails to verify", async () => {
|
|
1091
|
+
for (const spec of specs) {
|
|
1092
|
+
const responses = { [compatibleId(gw1)]: await sign(await apActorJson()) };
|
|
1093
|
+
const documentLoader = failingLoader(responses);
|
|
1094
|
+
const hintedKeyId = hinted(gw1, gw2);
|
|
1095
|
+
const keyCache = new KvKeyCache(new MemoryKvStore(), ["pk"]);
|
|
1096
|
+
const options = {
|
|
1097
|
+
documentLoader,
|
|
1098
|
+
contextLoader,
|
|
1099
|
+
keyCache,
|
|
1100
|
+
spec
|
|
1101
|
+
};
|
|
1102
|
+
ok(await verifyRequest(await signedRequest(spec, hintedKeyId), options) != null);
|
|
1103
|
+
strictEqual(documentLoader.fetched.length, 1, spec);
|
|
1104
|
+
responses[compatibleId(gw1)] = await apActorJson();
|
|
1105
|
+
responses[compatibleId(gw2)] = 503;
|
|
1106
|
+
ok(!(await verifyRequestDetailed(await signRequest(new Request("https://recipient.example/inbox", {
|
|
1107
|
+
method: "POST",
|
|
1108
|
+
body: "{}",
|
|
1109
|
+
headers: { "Content-Type": "application/activity+json" }
|
|
1110
|
+
}), rsaPrivateKey3, hintedKeyId, { spec }), options)).verified, spec);
|
|
1111
|
+
strictEqual(documentLoader.fetched.length, 3, spec);
|
|
1112
|
+
const next = await verifyRequestDetailed(await signedRequest(spec, hintedKeyId), options);
|
|
1113
|
+
ok(!next.verified, spec);
|
|
1114
|
+
strictEqual(next.reason.type, "keyFetchError", spec);
|
|
1115
|
+
strictEqual(documentLoader.fetched.length, 5, spec);
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
test("doesActorOwnKey() and getKeyOwner() resolve keys at ap: key IDs to portable actors", async () => {
|
|
1119
|
+
const options = {
|
|
1120
|
+
documentLoader: createLoader({ [compatibleId(gw1)]: await sign(await apActorJson()) }),
|
|
1121
|
+
contextLoader
|
|
1122
|
+
};
|
|
1123
|
+
const hintedKeyId = hinted(gw1);
|
|
1124
|
+
const key = new CryptographicKey({
|
|
1125
|
+
id: hintedKeyId,
|
|
1126
|
+
owner: parseIri(actorId),
|
|
1127
|
+
publicKey: gatewayPublicKey
|
|
1128
|
+
});
|
|
1129
|
+
const activity = new Create({
|
|
1130
|
+
id: parseIri(`${actorId.replace("/actor", "")}/activities/1`),
|
|
1131
|
+
actor: parseIri(`ap://${did}/actor`)
|
|
1132
|
+
});
|
|
1133
|
+
ok(await doesActorOwnKey(activity, key, options));
|
|
1134
|
+
strictEqual((await getKeyOwner(hintedKeyId, options))?.id?.href, parseIri(actorId).href);
|
|
1135
|
+
strictEqual((await getKeyOwner(key, options))?.id?.href, parseIri(actorId).href);
|
|
1136
|
+
ok(!await doesActorOwnKey(new Create({
|
|
1137
|
+
id: parseIri(`ap+ef61://${otherDid}/activities/1`),
|
|
1138
|
+
actor: parseIri(`ap+ef61://${otherDid}/actor`)
|
|
1139
|
+
}), key, options));
|
|
1140
|
+
const other = key.clone({ publicKey: rsaPublicKey3.publicKey });
|
|
1141
|
+
ok(!await doesActorOwnKey(activity, other, options));
|
|
1142
|
+
strictEqual(await getKeyOwner(other, options), null);
|
|
1143
|
+
const unsigned = {
|
|
1144
|
+
documentLoader: createLoader({ [compatibleId(gw1)]: await apActorJson() }),
|
|
1145
|
+
contextLoader
|
|
1146
|
+
};
|
|
1147
|
+
ok(!await doesActorOwnKey(activity, key, unsigned));
|
|
1148
|
+
strictEqual(await getKeyOwner(hintedKeyId, unsigned), null);
|
|
1149
|
+
});
|
|
1150
|
+
test("verifyRequest() does not trust a cached key at an ap: key ID for longer than its proof", async () => {
|
|
1151
|
+
let now = Temporal.Now.instant();
|
|
1152
|
+
const keyCache = new KvKeyCache(new MemoryKvStore(), ["pk"], { now: () => now });
|
|
1153
|
+
const expires = now.add({ minutes: 30 });
|
|
1154
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await apActorJson(), ed25519PrivateKey, didKeyId, { expires: expires.toString() }) });
|
|
1155
|
+
const options = {
|
|
1156
|
+
documentLoader,
|
|
1157
|
+
contextLoader,
|
|
1158
|
+
keyCache
|
|
1159
|
+
};
|
|
1160
|
+
const hintedKeyId = hinted(gw1);
|
|
1161
|
+
ok(await verifyRequest(await signedRequest(void 0, hintedKeyId), options) != null);
|
|
1162
|
+
now = expires.subtract({ seconds: 1 });
|
|
1163
|
+
ok(await verifyRequest(await signedRequest(void 0, hintedKeyId), options) != null);
|
|
1164
|
+
strictEqual(documentLoader.fetched.length, 1);
|
|
1165
|
+
now = expires;
|
|
1166
|
+
ok(await verifyRequest(await signedRequest(void 0, hintedKeyId), options) != null);
|
|
1167
|
+
strictEqual(documentLoader.fetched.length, 2);
|
|
1168
|
+
});
|
|
1169
|
+
test("verifyRequest() does not cache keys at ap: key IDs it could not process", async () => {
|
|
1170
|
+
let failures = 1;
|
|
1171
|
+
const flakyContextLoader = (url, options) => {
|
|
1172
|
+
if (failures > 0) {
|
|
1173
|
+
failures--;
|
|
1174
|
+
return Promise.reject(/* @__PURE__ */ new Error(`Temporarily failed to load ${url}`));
|
|
1175
|
+
}
|
|
1176
|
+
return contextLoader(url, options);
|
|
1177
|
+
};
|
|
1178
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await apActorJson()) });
|
|
1179
|
+
const options = {
|
|
1180
|
+
documentLoader,
|
|
1181
|
+
contextLoader: flakyContextLoader,
|
|
1182
|
+
keyCache: new KvKeyCache(new MemoryKvStore(), ["pk"])
|
|
1183
|
+
};
|
|
1184
|
+
const hintedKeyId = hinted(gw1);
|
|
1185
|
+
const result = await verifyRequestDetailed(await signedRequest(void 0, hintedKeyId), options);
|
|
1186
|
+
ok(!result.verified);
|
|
1187
|
+
strictEqual(result.reason.type, "keyFetchError");
|
|
1188
|
+
if (result.reason.type === "keyFetchError") ok(!("status" in result.reason.result));
|
|
1189
|
+
strictEqual((await verifyRequest(await signedRequest(void 0, hintedKeyId), options))?.ownerId?.href, parseIri(actorId).href);
|
|
1190
|
+
strictEqual(documentLoader.fetched.length, 2);
|
|
1191
|
+
});
|
|
718
1192
|
//#endregion
|
|
719
1193
|
export {};
|
package/dist/sig/proof.test.mjs
CHANGED
|
@@ -10,10 +10,10 @@ import "../std__assert-DvMDRPes.mjs";
|
|
|
10
10
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
11
11
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
12
12
|
import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
|
|
13
|
-
import { i as signObject, n as createProof, o as verifyObject, r as hasProofLike, s as verifyPortableObjectProof, u as verifyProof } from "../proof-
|
|
14
|
-
import { d as verifyRequest } from "../http-
|
|
13
|
+
import { i as signObject, n as createProof, o as verifyObject, r as hasProofLike, s as verifyPortableObjectProof, u as verifyProof } from "../proof-B4_0E-KU.mjs";
|
|
14
|
+
import { d as verifyRequest } from "../http-BpOiZE09.mjs";
|
|
15
15
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
|
|
16
|
-
import { t as getAuthenticatedDocumentLoader } from "../docloader-
|
|
16
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-BbS0rO-Y.mjs";
|
|
17
17
|
import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place, Translation } from "@fedify/vocab";
|
|
18
18
|
import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
19
19
|
import { decodeMultibase, encodeMultibase, exportDidKey, exportMultibaseKey, formatIri, importMultibaseKey, parseIri } from "@fedify/vocab-runtime";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { c as getNormalizationContextLoader } from "./ld-
|
|
4
|
+
import { c as getNormalizationContextLoader } from "./ld-Dwc176V4.mjs";
|
|
5
5
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
6
6
|
//#region src/federation/temporal.ts
|
|
7
7
|
function isPlainObject(value) {
|
package/dist/testing/kv.test.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
|
6
6
|
import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
|
|
7
7
|
import { n as baseOptions, o as stringSchema, t as MockQueue } from "../tasks-dbCShlCb.mjs";
|
|
8
8
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
9
|
-
import { o as createFederation } from "../middleware-
|
|
9
|
+
import { o as createFederation } from "../middleware-DN3MdTDg.mjs";
|
|
10
10
|
//#region src/testing/kv.test.ts
|
|
11
11
|
test("ManualClockKvStore keeps an entry at its exact expiration instant", async () => {
|
|
12
12
|
const kv = new ManualClockKvStore();
|
package/dist/testing/mod.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ import { Router } from "@fedify/uri-template";
|
|
|
5
5
|
import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Note, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab";
|
|
6
6
|
import { Link as Link$1, LookupWebFingerOptions, ResourceDescriptor } from "@fedify/webfinger";
|
|
7
7
|
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
8
|
-
import { AuthenticatedDocumentLoaderFactory, DocumentLoader, DocumentLoaderFactory, GetUserAgentOptions } from "@fedify/vocab-runtime";
|
|
8
|
+
import { AuthenticatedDocumentLoaderFactory, DocumentLoader, DocumentLoaderFactory, GetUserAgentOptions, PortableObjectVerifier } from "@fedify/vocab-runtime";
|
|
9
9
|
import { MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
|
|
10
10
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
11
11
|
|
|
@@ -2881,6 +2881,27 @@ interface Context<TContextData> {
|
|
|
2881
2881
|
* The context loader for loading remote JSON-LD contexts.
|
|
2882
2882
|
*/
|
|
2883
2883
|
readonly contextLoader: DocumentLoader;
|
|
2884
|
+
/**
|
|
2885
|
+
* The [FEP-ef61] portable object policy that this context applies to
|
|
2886
|
+
* portable objects it dereferences. It is `verifyPortableObject()` with
|
|
2887
|
+
* this context's document loader, context loader, and tracer provider as
|
|
2888
|
+
* defaults, which the options passed to it override.
|
|
2889
|
+
*
|
|
2890
|
+
* Since its name is the same as the `verifyPortableObject` option of
|
|
2891
|
+
* property accessors, `lookupObject()`, and `traverseCollection()`, passing
|
|
2892
|
+
* a context as their options applies the policy, e.g.,
|
|
2893
|
+
* `await create.getObject(ctx)`. Objects parsed with a context as options,
|
|
2894
|
+
* such as activities that inboxes receive, also use it by default for
|
|
2895
|
+
* their property accessors. It never verifies an object by itself being
|
|
2896
|
+
* there: it only applies to objects that are dereferenced.
|
|
2897
|
+
*
|
|
2898
|
+
* It is optional only so that custom implementations of this interface
|
|
2899
|
+
* keep working; contexts that Fedify creates always have it.
|
|
2900
|
+
*
|
|
2901
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2902
|
+
* @since 2.4.0
|
|
2903
|
+
*/
|
|
2904
|
+
readonly verifyPortableObject?: PortableObjectVerifier;
|
|
2884
2905
|
/**
|
|
2885
2906
|
* The federation object that this context belongs to.
|
|
2886
2907
|
* @since 1.6.0
|
|
@@ -3158,10 +3179,13 @@ interface Context<TContextData> {
|
|
|
3158
3179
|
*
|
|
3159
3180
|
* It's almost the same as the {@link lookupObject} function, but it uses
|
|
3160
3181
|
* the context's document loader and context loader by default. It also
|
|
3161
|
-
* uses
|
|
3182
|
+
* uses {@link Context.verifyPortableObject} as the `verifyPortableObject`
|
|
3162
3183
|
* option by default (since 2.4.0), so [FEP-ef61] portable objects,
|
|
3163
3184
|
* including portable actors found through WebFinger, are looked up through
|
|
3164
|
-
* their gateways and returned only if they have valid proofs
|
|
3185
|
+
* their gateways and returned only if they have valid proofs, or, for
|
|
3186
|
+
* collections without proofs, if they are served by gateways that their
|
|
3187
|
+
* owners list. The returned object uses the same policy by default for
|
|
3188
|
+
* its property accessors.
|
|
3165
3189
|
*
|
|
3166
3190
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
3167
3191
|
*
|
|
@@ -3187,7 +3211,9 @@ interface Context<TContextData> {
|
|
|
3187
3211
|
* ```
|
|
3188
3212
|
*
|
|
3189
3213
|
* It's almost the same as the {@link traverseCollection} function, but it
|
|
3190
|
-
* uses the context's document loader and context loader by default.
|
|
3214
|
+
* uses the context's document loader and context loader by default. It
|
|
3215
|
+
* also uses {@link Context.verifyPortableObject} as the
|
|
3216
|
+
* `verifyPortableObject` option by default (since 2.4.0).
|
|
3191
3217
|
* @param collection The collection to traverse.
|
|
3192
3218
|
* @param options Options for traversing the collection.
|
|
3193
3219
|
* @returns An async iterable of each item in the collection.
|
package/dist/testing/mod.mjs
CHANGED
|
@@ -2,8 +2,8 @@ import "temporal-polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { r as testDefinitions } from "../dist-BQvArojP.mjs";
|
|
5
|
-
import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-
|
|
5
|
+
import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-DfSVPcJ8.mjs";
|
|
6
6
|
import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
|
|
7
7
|
import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, r as envelopeSchema, t as MockQueue } from "../tasks-dbCShlCb.mjs";
|
|
8
|
-
import "../testing-
|
|
8
|
+
import "../testing-otQhu4aD.mjs";
|
|
9
9
|
export { ManualClockKvStore, MockQueue, baseOptions, createInboxContext, createOutboxContext, createRequestContext, envelopeSchema, makeSchema, numberSchema, stringSchema, testDefinitions };
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import "./dist-BQvArojP.mjs";
|
|
5
|
-
import "./context-
|
|
5
|
+
import "./context-DfSVPcJ8.mjs";
|
|
6
6
|
import "./kv-DBRWVx3Q.mjs";
|
|
7
7
|
import "./tasks-dbCShlCb.mjs";
|
|
8
8
|
export {};
|