@agimon-ai/doompi-web-security 0.0.1-alpha.2 → 0.0.1-alpha.26

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.
Files changed (54) hide show
  1. package/README.md +14 -7
  2. package/dist/adapters/browserBundleVerifier.cjs +2 -0
  3. package/dist/adapters/browserBundleVerifier.cjs.map +1 -0
  4. package/dist/adapters/browserBundleVerifier.d.cts +44 -0
  5. package/dist/adapters/browserBundleVerifier.d.cts.map +1 -0
  6. package/dist/adapters/browserBundleVerifier.d.mts +44 -0
  7. package/dist/adapters/browserBundleVerifier.d.mts.map +1 -0
  8. package/dist/adapters/browserBundleVerifier.mjs +2 -0
  9. package/dist/adapters/browserBundleVerifier.mjs.map +1 -0
  10. package/dist/adapters/browserSealedChannel.d.cts +5 -6
  11. package/dist/adapters/browserSealedChannel.d.cts.map +1 -1
  12. package/dist/adapters/browserSealedChannel.d.mts +5 -6
  13. package/dist/adapters/browserSealedChannel.d.mts.map +1 -1
  14. package/dist/adapters/bundleSigner.cjs +1 -1
  15. package/dist/adapters/bundleSigner.cjs.map +1 -1
  16. package/dist/adapters/bundleSigner.d.cts +9 -6
  17. package/dist/adapters/bundleSigner.d.cts.map +1 -1
  18. package/dist/adapters/bundleSigner.d.mts +9 -6
  19. package/dist/adapters/bundleSigner.d.mts.map +1 -1
  20. package/dist/adapters/bundleSigner.mjs +1 -1
  21. package/dist/adapters/bundleSigner.mjs.map +1 -1
  22. package/dist/adapters/nodeSealedChannel.d.cts +5 -6
  23. package/dist/adapters/nodeSealedChannel.d.cts.map +1 -1
  24. package/dist/adapters/nodeSealedChannel.d.mts +5 -6
  25. package/dist/adapters/nodeSealedChannel.d.mts.map +1 -1
  26. package/dist/adapters/sealedTransport.d.cts +3 -4
  27. package/dist/adapters/sealedTransport.d.cts.map +1 -1
  28. package/dist/adapters/sealedTransport.d.mts +3 -4
  29. package/dist/adapters/sealedTransport.d.mts.map +1 -1
  30. package/dist/browser.cjs +1 -1
  31. package/dist/browser.d.cts +3 -1
  32. package/dist/browser.d.mts +3 -1
  33. package/dist/browser.mjs +1 -1
  34. package/dist/index.cjs +1 -1
  35. package/dist/index.d.cts +2 -2
  36. package/dist/index.d.mts +2 -2
  37. package/dist/index.mjs +1 -1
  38. package/dist/services/serialQueue.d.cts +2 -3
  39. package/dist/services/serialQueue.d.cts.map +1 -1
  40. package/dist/services/serialQueue.d.mts +2 -3
  41. package/dist/services/serialQueue.d.mts.map +1 -1
  42. package/dist/types/bundleManifest.cjs +0 -0
  43. package/dist/types/bundleManifest.cjs.map +1 -1
  44. package/dist/types/bundleManifest.d.cts +24 -28
  45. package/dist/types/bundleManifest.d.cts.map +1 -1
  46. package/dist/types/bundleManifest.d.mts +24 -28
  47. package/dist/types/bundleManifest.d.mts.map +1 -1
  48. package/dist/types/bundleManifest.mjs +0 -0
  49. package/dist/types/bundleManifest.mjs.map +1 -1
  50. package/dist/types/sealedChannel.d.cts +16 -17
  51. package/dist/types/sealedChannel.d.cts.map +1 -1
  52. package/dist/types/sealedChannel.d.mts +16 -17
  53. package/dist/types/sealedChannel.d.mts.map +1 -1
  54. package/package.json +5 -5
@@ -1,5 +1,5 @@
1
1
  //#region src/adapters/sealedTransport.d.ts
2
- interface SealedTransport {
2
+ export interface SealedTransport {
3
3
  /** False on loopback and before the handshake completes, where everything passes through. */
4
4
  active(): boolean;
5
5
  sealText(text: string): Promise<string>;
@@ -11,7 +11,7 @@ interface SealedTransport {
11
11
  fetch(input: string, init?: RequestInit): Promise<Response>;
12
12
  lastFailure(): string | undefined;
13
13
  }
14
- declare function createSealedTransport(): SealedTransport & {
14
+ export declare function createSealedTransport(): SealedTransport & {
15
15
  /** Completes the handshake against the host key from the QR. */
16
16
  connect: (hostPublicKey: string) => Promise<string | undefined>;
17
17
  /** Drops the channel, so everything falls back to pass-through. */
@@ -30,7 +30,7 @@ declare function createSealedTransport(): SealedTransport & {
30
30
  * Inactive until a handshake completes, and inactive forever on the loopback
31
31
  * listener, so `sealedTransport.fetch` is a plain `fetch` there.
32
32
  */
33
- declare const sealedTransport: SealedTransport & {
33
+ export declare const sealedTransport: SealedTransport & {
34
34
  /** Completes the handshake against the host key from the QR. */
35
35
  connect: (hostPublicKey: string) => Promise<string | undefined>;
36
36
  /** Drops the channel, so everything falls back to pass-through. */
@@ -39,5 +39,4 @@ declare const sealedTransport: SealedTransport & {
39
39
  relayRequestsThrough: (path: string) => void;
40
40
  };
41
41
  //#endregion
42
- export { SealedTransport, createSealedTransport, sealedTransport };
43
42
  //# sourceMappingURL=sealedTransport.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sealedTransport.d.cts","names":[],"sources":["../../src/adapters/sealedTransport.ts"],"mappings":";UAqBiB;;EAEf;EACA,SAAS,eAAe;;EAExB,SAAS,eAAe;EACxB,WAAW,OAAO,aAAa,QAAQ;EACvC,WAAW,OAAO,aAAa,QAAQ;;EAEvC,MAAM,eAAe,OAAO,cAAc,QAAQ;EAClD;;iBA4Dc,yBAAyB;;EAEvC,UAAU,0BAA0B;;EAEpC;;EAEA,uBAAuB;;;;;;;;;;;;;cAmJZ,iBAAe;;EAvJjB,UAAC,0BAA0B;;EAE7B;;EAEe,uBAAC"}
1
+ {"version":3,"file":"sealedTransport.d.cts","names":[],"sources":["../../src/adapters/sealedTransport.ts"],"mappings":";iBAqBiB;;EAEf;EACA,SAAS,eAAe;;EAExB,SAAS,eAAe;EACxB,WAAW,OAAO,aAAa,QAAQ;EACvC,WAAW,OAAO,aAAa,QAAQ;;EAEvC,MAAM,eAAe,OAAO,cAAc,QAAQ;EAClD;;wBA4Dc,yBAAyB;;EAEvC,UAAU,0BAA0B;;EAEpC;;EAEA,uBAAuB;;;;;;;;;;;;;qBAmJZ,iBAAe;;EAvJjB,UAAC,0BAA0B;;EAE7B;;EAEe,uBAAC"}
@@ -1,5 +1,5 @@
1
1
  //#region src/adapters/sealedTransport.d.ts
2
- interface SealedTransport {
2
+ export interface SealedTransport {
3
3
  /** False on loopback and before the handshake completes, where everything passes through. */
4
4
  active(): boolean;
5
5
  sealText(text: string): Promise<string>;
@@ -11,7 +11,7 @@ interface SealedTransport {
11
11
  fetch(input: string, init?: RequestInit): Promise<Response>;
12
12
  lastFailure(): string | undefined;
13
13
  }
14
- declare function createSealedTransport(): SealedTransport & {
14
+ export declare function createSealedTransport(): SealedTransport & {
15
15
  /** Completes the handshake against the host key from the QR. */
16
16
  connect: (hostPublicKey: string) => Promise<string | undefined>;
17
17
  /** Drops the channel, so everything falls back to pass-through. */
@@ -30,7 +30,7 @@ declare function createSealedTransport(): SealedTransport & {
30
30
  * Inactive until a handshake completes, and inactive forever on the loopback
31
31
  * listener, so `sealedTransport.fetch` is a plain `fetch` there.
32
32
  */
33
- declare const sealedTransport: SealedTransport & {
33
+ export declare const sealedTransport: SealedTransport & {
34
34
  /** Completes the handshake against the host key from the QR. */
35
35
  connect: (hostPublicKey: string) => Promise<string | undefined>;
36
36
  /** Drops the channel, so everything falls back to pass-through. */
@@ -39,5 +39,4 @@ declare const sealedTransport: SealedTransport & {
39
39
  relayRequestsThrough: (path: string) => void;
40
40
  };
41
41
  //#endregion
42
- export { SealedTransport, createSealedTransport, sealedTransport };
43
42
  //# sourceMappingURL=sealedTransport.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sealedTransport.d.mts","names":[],"sources":["../../src/adapters/sealedTransport.ts"],"mappings":";UAqBiB;;EAEf;EACA,SAAS,eAAe;;EAExB,SAAS,eAAe;EACxB,WAAW,OAAO,aAAa,QAAQ;EACvC,WAAW,OAAO,aAAa,QAAQ;;EAEvC,MAAM,eAAe,OAAO,cAAc,QAAQ;EAClD;;iBA4Dc,yBAAyB;;EAEvC,UAAU,0BAA0B;;EAEpC;;EAEA,uBAAuB;;;;;;;;;;;;;cAmJZ,iBAAe;;EAvJjB,UAAC,0BAA0B;;EAE7B;;EAEe,uBAAC"}
1
+ {"version":3,"file":"sealedTransport.d.mts","names":[],"sources":["../../src/adapters/sealedTransport.ts"],"mappings":";iBAqBiB;;EAEf;EACA,SAAS,eAAe;;EAExB,SAAS,eAAe;EACxB,WAAW,OAAO,aAAa,QAAQ;EACvC,WAAW,OAAO,aAAa,QAAQ;;EAEvC,MAAM,eAAe,OAAO,cAAc,QAAQ;EAClD;;wBA4Dc,yBAAyB;;EAEvC,UAAU,0BAA0B;;EAEpC;;EAEA,uBAAuB;;;;;;;;;;;;;qBAmJZ,iBAAe;;EAvJjB,UAAC,0BAA0B;;EAE7B;;EAEe,uBAAC"}
package/dist/browser.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/browserSealedChannel.cjs"),t=require("./adapters/sealedTransport.cjs");exports.channelFromSecret=e.channelFromSecret,exports.connectSealedChannel=e.connectSealedChannel,exports.createSealedTransport=t.createSealedTransport,exports.sealedTransport=t.sealedTransport;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./types/bundleManifest.cjs"),t=require("./adapters/browserBundleVerifier.cjs"),n=require("./adapters/browserSealedChannel.cjs"),r=require("./adapters/sealedTransport.cjs");exports.BUNDLE_MANIFEST_ROUTE=e.BUNDLE_MANIFEST_ROUTE,exports.BUNDLE_MANIFEST_VERSION=e.BUNDLE_MANIFEST_VERSION,exports.assetFor=e.assetFor,exports.canonicalManifest=e.canonicalManifest,exports.channelFromSecret=n.channelFromSecret,exports.connectSealedChannel=n.connectSealedChannel,exports.createSealedTransport=r.createSealedTransport,exports.digestFor=e.digestFor,exports.isBundleManifest=e.isBundleManifest,exports.isSignedBundleManifest=e.isSignedBundleManifest,exports.sealedTransport=r.sealedTransport,exports.verifyBundleAsset=t.verifyBundleAsset,exports.verifySignedBundleManifest=t.verifySignedBundleManifest;
@@ -1,3 +1,5 @@
1
+ import { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, assetFor, canonicalManifest, digestFor, isBundleManifest, isSignedBundleManifest } from "./types/bundleManifest.cjs";
2
+ import { BundleAssetVerificationFailure, BundleAssetVerificationResult, BundleVerificationFailure, BundleVerificationResult, verifyBundleAsset, verifySignedBundleManifest } from "./adapters/browserBundleVerifier.cjs";
1
3
  import { OpenResult, SealResult, SealedChannel, channelFromSecret, connectSealedChannel } from "./adapters/browserSealedChannel.cjs";
2
4
  import { SealedTransport, createSealedTransport, sealedTransport } from "./adapters/sealedTransport.cjs";
3
- export { type OpenResult, type SealResult, type SealedChannel, type SealedTransport, channelFromSecret, connectSealedChannel, createSealedTransport, sealedTransport };
5
+ export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, type BundleAsset, type BundleAssetVerificationFailure, type BundleAssetVerificationResult, type BundleManifest, type BundleVerificationFailure, type BundleVerificationResult, type OpenResult, type SealResult, type SealedChannel, type SealedTransport, type SignedBundleManifest, assetFor, canonicalManifest, channelFromSecret, connectSealedChannel, createSealedTransport, digestFor, isBundleManifest, isSignedBundleManifest, sealedTransport, verifyBundleAsset, verifySignedBundleManifest };
@@ -1,3 +1,5 @@
1
+ import { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, assetFor, canonicalManifest, digestFor, isBundleManifest, isSignedBundleManifest } from "./types/bundleManifest.mjs";
2
+ import { BundleAssetVerificationFailure, BundleAssetVerificationResult, BundleVerificationFailure, BundleVerificationResult, verifyBundleAsset, verifySignedBundleManifest } from "./adapters/browserBundleVerifier.mjs";
1
3
  import { OpenResult, SealResult, SealedChannel, channelFromSecret, connectSealedChannel } from "./adapters/browserSealedChannel.mjs";
2
4
  import { SealedTransport, createSealedTransport, sealedTransport } from "./adapters/sealedTransport.mjs";
3
- export { type OpenResult, type SealResult, type SealedChannel, type SealedTransport, channelFromSecret, connectSealedChannel, createSealedTransport, sealedTransport };
5
+ export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, type BundleAsset, type BundleAssetVerificationFailure, type BundleAssetVerificationResult, type BundleManifest, type BundleVerificationFailure, type BundleVerificationResult, type OpenResult, type SealResult, type SealedChannel, type SealedTransport, type SignedBundleManifest, assetFor, canonicalManifest, channelFromSecret, connectSealedChannel, createSealedTransport, digestFor, isBundleManifest, isSignedBundleManifest, sealedTransport, verifyBundleAsset, verifySignedBundleManifest };
package/dist/browser.mjs CHANGED
@@ -1 +1 @@
1
- import{channelFromSecret as e,connectSealedChannel as t}from"./adapters/browserSealedChannel.mjs";import{createSealedTransport as n,sealedTransport as r}from"./adapters/sealedTransport.mjs";export{e as channelFromSecret,t as connectSealedChannel,n as createSealedTransport,r as sealedTransport};
1
+ import{BUNDLE_MANIFEST_ROUTE as e,BUNDLE_MANIFEST_VERSION as t,assetFor as n,canonicalManifest as r,digestFor as i,isBundleManifest as a,isSignedBundleManifest as o}from"./types/bundleManifest.mjs";import{verifyBundleAsset as s,verifySignedBundleManifest as c}from"./adapters/browserBundleVerifier.mjs";import{channelFromSecret as l,connectSealedChannel as u}from"./adapters/browserSealedChannel.mjs";import{createSealedTransport as d,sealedTransport as f}from"./adapters/sealedTransport.mjs";export{e as BUNDLE_MANIFEST_ROUTE,t as BUNDLE_MANIFEST_VERSION,n as assetFor,r as canonicalManifest,l as channelFromSecret,u as connectSealedChannel,d as createSealedTransport,i as digestFor,a as isBundleManifest,o as isSignedBundleManifest,f as sealedTransport,s as verifyBundleAsset,c as verifySignedBundleManifest};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./types/sealedChannel.cjs"),t=require("./services/serialQueue.cjs"),n=require("./types/bundleManifest.cjs");exports.BUNDLE_MANIFEST_ROUTE=n.BUNDLE_MANIFEST_ROUTE,exports.BUNDLE_MANIFEST_VERSION=n.BUNDLE_MANIFEST_VERSION,exports.CLIENT_TO_SERVER_INFO=e.CLIENT_TO_SERVER_INFO,exports.MAX_MESSAGES_PER_KEY=e.MAX_MESSAGES_PER_KEY,exports.NONCE_BYTES=e.NONCE_BYTES,exports.NONCE_COUNTER_BYTES=e.NONCE_COUNTER_BYTES,exports.NONCE_PREFIX_BYTES=e.NONCE_PREFIX_BYTES,exports.SEALED_BODY_HEADER=e.SEALED_BODY_HEADER,exports.SEALED_CLIENT_KEY_HEADER=e.SEALED_CLIENT_KEY_HEADER,exports.SEALED_KEY_PARAM=e.SEALED_KEY_PARAM,exports.SEALED_VERSION=e.SEALED_VERSION,exports.SERVER_TO_CLIENT_INFO=e.SERVER_TO_CLIENT_INFO,exports.canonicalManifest=n.canonicalManifest,exports.createSerialQueue=t.createSerialQueue,exports.describeSealedFailure=e.describeSealedFailure,exports.digestFor=n.digestFor,exports.infoFor=e.infoFor,exports.isBundleManifest=n.isBundleManifest,exports.isSealedEnvelope=e.isSealedEnvelope;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./types/bundleManifest.cjs"),t=require("./types/sealedChannel.cjs"),n=require("./services/serialQueue.cjs");exports.BUNDLE_MANIFEST_ROUTE=e.BUNDLE_MANIFEST_ROUTE,exports.BUNDLE_MANIFEST_VERSION=e.BUNDLE_MANIFEST_VERSION,exports.CLIENT_TO_SERVER_INFO=t.CLIENT_TO_SERVER_INFO,exports.MAX_MESSAGES_PER_KEY=t.MAX_MESSAGES_PER_KEY,exports.NONCE_BYTES=t.NONCE_BYTES,exports.NONCE_COUNTER_BYTES=t.NONCE_COUNTER_BYTES,exports.NONCE_PREFIX_BYTES=t.NONCE_PREFIX_BYTES,exports.SEALED_BODY_HEADER=t.SEALED_BODY_HEADER,exports.SEALED_CLIENT_KEY_HEADER=t.SEALED_CLIENT_KEY_HEADER,exports.SEALED_KEY_PARAM=t.SEALED_KEY_PARAM,exports.SEALED_VERSION=t.SEALED_VERSION,exports.SERVER_TO_CLIENT_INFO=t.SERVER_TO_CLIENT_INFO,exports.assetFor=e.assetFor,exports.canonicalManifest=e.canonicalManifest,exports.createSerialQueue=n.createSerialQueue,exports.describeSealedFailure=t.describeSealedFailure,exports.digestFor=e.digestFor,exports.infoFor=t.infoFor,exports.isBundleManifest=e.isBundleManifest,exports.isSealedEnvelope=t.isSealedEnvelope,exports.isSignedBundleManifest=e.isSignedBundleManifest;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
+ import { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, assetFor, canonicalManifest, digestFor, isBundleManifest, isSignedBundleManifest } from "./types/bundleManifest.cjs";
1
2
  import { CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, SealedDirection, SealedEnvelope, SealedFailure, describeSealedFailure, infoFor, isSealedEnvelope } from "./types/sealedChannel.cjs";
2
- import { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, canonicalManifest, digestFor, isBundleManifest } from "./types/bundleManifest.cjs";
3
3
  import { SerialQueue, createSerialQueue } from "./services/serialQueue.cjs";
4
- export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, type BundleAsset, type BundleManifest, CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, type SealedDirection, type SealedEnvelope, type SealedFailure, type SerialQueue, type SignedBundleManifest, canonicalManifest, createSerialQueue, describeSealedFailure, digestFor, infoFor, isBundleManifest, isSealedEnvelope };
4
+ export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, type BundleAsset, type BundleManifest, CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, type SealedDirection, type SealedEnvelope, type SealedFailure, type SerialQueue, type SignedBundleManifest, assetFor, canonicalManifest, createSerialQueue, describeSealedFailure, digestFor, infoFor, isBundleManifest, isSealedEnvelope, isSignedBundleManifest };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
+ import { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, assetFor, canonicalManifest, digestFor, isBundleManifest, isSignedBundleManifest } from "./types/bundleManifest.mjs";
1
2
  import { CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, SealedDirection, SealedEnvelope, SealedFailure, describeSealedFailure, infoFor, isSealedEnvelope } from "./types/sealedChannel.mjs";
2
- import { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, canonicalManifest, digestFor, isBundleManifest } from "./types/bundleManifest.mjs";
3
3
  import { SerialQueue, createSerialQueue } from "./services/serialQueue.mjs";
4
- export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, type BundleAsset, type BundleManifest, CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, type SealedDirection, type SealedEnvelope, type SealedFailure, type SerialQueue, type SignedBundleManifest, canonicalManifest, createSerialQueue, describeSealedFailure, digestFor, infoFor, isBundleManifest, isSealedEnvelope };
4
+ export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, type BundleAsset, type BundleManifest, CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, type SealedDirection, type SealedEnvelope, type SealedFailure, type SerialQueue, type SignedBundleManifest, assetFor, canonicalManifest, createSerialQueue, describeSealedFailure, digestFor, infoFor, isBundleManifest, isSealedEnvelope, isSignedBundleManifest };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{CLIENT_TO_SERVER_INFO as e,MAX_MESSAGES_PER_KEY as t,NONCE_BYTES as n,NONCE_COUNTER_BYTES as r,NONCE_PREFIX_BYTES as i,SEALED_BODY_HEADER as a,SEALED_CLIENT_KEY_HEADER as o,SEALED_KEY_PARAM as s,SEALED_VERSION as c,SERVER_TO_CLIENT_INFO as l,describeSealedFailure as u,infoFor as d,isSealedEnvelope as f}from"./types/sealedChannel.mjs";import{createSerialQueue as p}from"./services/serialQueue.mjs";import{BUNDLE_MANIFEST_ROUTE as m,BUNDLE_MANIFEST_VERSION as h,canonicalManifest as g,digestFor as _,isBundleManifest as v}from"./types/bundleManifest.mjs";export{m as BUNDLE_MANIFEST_ROUTE,h as BUNDLE_MANIFEST_VERSION,e as CLIENT_TO_SERVER_INFO,t as MAX_MESSAGES_PER_KEY,n as NONCE_BYTES,r as NONCE_COUNTER_BYTES,i as NONCE_PREFIX_BYTES,a as SEALED_BODY_HEADER,o as SEALED_CLIENT_KEY_HEADER,s as SEALED_KEY_PARAM,c as SEALED_VERSION,l as SERVER_TO_CLIENT_INFO,g as canonicalManifest,p as createSerialQueue,u as describeSealedFailure,_ as digestFor,d as infoFor,v as isBundleManifest,f as isSealedEnvelope};
1
+ import{BUNDLE_MANIFEST_ROUTE as e,BUNDLE_MANIFEST_VERSION as t,assetFor as n,canonicalManifest as r,digestFor as i,isBundleManifest as a,isSignedBundleManifest as o}from"./types/bundleManifest.mjs";import{CLIENT_TO_SERVER_INFO as s,MAX_MESSAGES_PER_KEY as c,NONCE_BYTES as l,NONCE_COUNTER_BYTES as u,NONCE_PREFIX_BYTES as d,SEALED_BODY_HEADER as f,SEALED_CLIENT_KEY_HEADER as p,SEALED_KEY_PARAM as m,SEALED_VERSION as h,SERVER_TO_CLIENT_INFO as g,describeSealedFailure as _,infoFor as v,isSealedEnvelope as y}from"./types/sealedChannel.mjs";import{createSerialQueue as b}from"./services/serialQueue.mjs";export{e as BUNDLE_MANIFEST_ROUTE,t as BUNDLE_MANIFEST_VERSION,s as CLIENT_TO_SERVER_INFO,c as MAX_MESSAGES_PER_KEY,l as NONCE_BYTES,u as NONCE_COUNTER_BYTES,d as NONCE_PREFIX_BYTES,f as SEALED_BODY_HEADER,p as SEALED_CLIENT_KEY_HEADER,m as SEALED_KEY_PARAM,h as SEALED_VERSION,g as SERVER_TO_CLIENT_INFO,n as assetFor,r as canonicalManifest,b as createSerialQueue,_ as describeSealedFailure,i as digestFor,v as infoFor,a as isBundleManifest,y as isSealedEnvelope,o as isSignedBundleManifest};
@@ -13,11 +13,10 @@
13
13
  * Deliberately not a general work pool. A pool with any concurrency above one
14
14
  * reintroduces exactly the reordering this exists to prevent.
15
15
  */
16
- interface SerialQueue {
16
+ export interface SerialQueue {
17
17
  /** Resolves with the task's result once every task queued before it has settled. */
18
18
  run<T>(task: () => Promise<T>): Promise<T>;
19
19
  }
20
- declare function createSerialQueue(): SerialQueue;
20
+ export declare function createSerialQueue(): SerialQueue;
21
21
  //#endregion
22
- export { SerialQueue, createSerialQueue };
23
22
  //# sourceMappingURL=serialQueue.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serialQueue.d.cts","names":[],"sources":["../../src/services/serialQueue.ts"],"mappings":";;;;;;;;;;;;;;;UAciB;;EAEf,IAAI,GAAG,YAAY,QAAQ,KAAK,QAAQ;;iBAG1B,qBAAqB"}
1
+ {"version":3,"file":"serialQueue.d.cts","names":[],"sources":["../../src/services/serialQueue.ts"],"mappings":";;;;;;;;;;;;;;;iBAciB;;EAEf,IAAI,GAAG,YAAY,QAAQ,KAAK,QAAQ;;wBAG1B,qBAAqB"}
@@ -13,11 +13,10 @@
13
13
  * Deliberately not a general work pool. A pool with any concurrency above one
14
14
  * reintroduces exactly the reordering this exists to prevent.
15
15
  */
16
- interface SerialQueue {
16
+ export interface SerialQueue {
17
17
  /** Resolves with the task's result once every task queued before it has settled. */
18
18
  run<T>(task: () => Promise<T>): Promise<T>;
19
19
  }
20
- declare function createSerialQueue(): SerialQueue;
20
+ export declare function createSerialQueue(): SerialQueue;
21
21
  //#endregion
22
- export { SerialQueue, createSerialQueue };
23
22
  //# sourceMappingURL=serialQueue.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serialQueue.d.mts","names":[],"sources":["../../src/services/serialQueue.ts"],"mappings":";;;;;;;;;;;;;;;UAciB;;EAEf,IAAI,GAAG,YAAY,QAAQ,KAAK,QAAQ;;iBAG1B,qBAAqB"}
1
+ {"version":3,"file":"serialQueue.d.mts","names":[],"sources":["../../src/services/serialQueue.ts"],"mappings":";;;;;;;;;;;;;;;iBAciB;;EAEf,IAAI,GAAG,YAAY,QAAQ,KAAK,QAAQ;;wBAG1B,qBAAqB"}
Binary file
@@ -1 +1 @@
1
- {"version":3,"file":"bundleManifest.cjs","names":[],"sources":["../../src/types/bundleManifest.ts"],"sourcesContent":["/**\n * A signed description of cockpit assets for an independently trusted verifier.\n *\n * A manifest does not let a browser SPA defend itself against the server or TLS\n * edge that supplied its executable code. Such an attacker can omit the\n * verifier or substitute its trust key. Consumers need a separately trusted\n * bootstrap and key before these signatures become a delivery guarantee.\n *\n * Lives in types rather than services because any verifier must use the same\n * canonical encoding the server signs, byte for byte.\n */\n\nexport const BUNDLE_MANIFEST_ROUTE = '/bundle-manifest.json';\nexport const BUNDLE_MANIFEST_VERSION = 1;\n\nexport interface BundleAsset {\n /** Path as the browser requests it, leading slash included. */\n path: string;\n /** Lowercase hex SHA-256 of the bytes served at that path. */\n sha256: string;\n}\n\nexport interface BundleManifest {\n version: number;\n /** Milliseconds, so a stale manifest is visible without another lookup. */\n builtAt: number;\n assets: BundleAsset[];\n}\n\nexport interface SignedBundleManifest {\n manifest: BundleManifest;\n /** Base64url ECDSA P-256 signature over the canonical serialization. */\n signature: string;\n /** Base64url SPKI of the key that signed it; trust must be established out of band. */\n publicKey: string;\n}\n\n/**\n * The exact bytes that get signed.\n *\n * Hand-rolled rather than `JSON.stringify` of the whole object, because a\n * signature is only worth anything if both sides agree byte for byte on what\n * was signed. Key order in a JSON object is an implementation detail; a sorted\n * line-per-asset encoding is not.\n */\nexport function canonicalManifest(manifest: BundleManifest): string {\n const assets = [...manifest.assets].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n );\n const lines = assets.map((asset) => `${asset.path}\u0000${asset.sha256}`);\n return [String(manifest.version), String(manifest.builtAt), ...lines].join('\\n');\n}\n\nexport function isBundleManifest(value: unknown): value is BundleManifest {\n if (typeof value !== 'object' || value === null) return false;\n const candidate = value as Partial<BundleManifest>;\n if (candidate.version !== BUNDLE_MANIFEST_VERSION) return false;\n if (typeof candidate.builtAt !== 'number' || !Array.isArray(candidate.assets)) return false;\n return candidate.assets.every(\n (asset: unknown) =>\n typeof asset === 'object' &&\n asset !== null &&\n typeof (asset as BundleAsset).path === 'string' &&\n /^[0-9a-f]{64}$/u.test((asset as BundleAsset).sha256),\n );\n}\n\n/** The recorded digest for one asset, or undefined if the manifest does not cover it. */\nexport function digestFor(manifest: BundleManifest, path: string): string | undefined {\n return manifest.assets.find((asset) => asset.path === path)?.sha256;\n}\n"],"mappings":"AA6CA,SAAgB,EAAkB,EAAkC,CAIlE,IAAM,EAHS,CAAC,GAAG,EAAS,MAAM,CAAC,CAAC,MAAM,EAAM,IAC9C,EAAK,KAAO,EAAM,KAAO,GAAK,IAAK,KAAO,EAAM,KAE/B,CAAC,CAAC,IAAK,GAAU,GAAG,EAAM,KAAK,GAAG,EAAM,QAAQ,EACnE,MAAO,CAAC,OAAO,EAAS,OAAO,EAAG,OAAO,EAAS,OAAO,EAAG,GAAG,CAAK,CAAC,CAAC,KAAK;CAAI,CACjF,CAEA,SAAgB,EAAiB,EAAyC,CACxE,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,IAAM,EAAY,EAGlB,OAFI,EAAU,UAAA,GACV,OAAO,EAAU,SAAY,UAAY,CAAC,MAAM,QAAQ,EAAU,MAAM,EAAU,GAC/E,EAAU,OAAO,MACrB,GACC,OAAO,GAAU,YACjB,GACA,OAAQ,EAAsB,MAAS,UACvC,kBAAkB,KAAM,EAAsB,MAAM,CACxD,CACF,CAGA,SAAgB,EAAU,EAA0B,EAAkC,CACpF,OAAO,EAAS,OAAO,KAAM,GAAU,EAAM,OAAS,CAAI,CAAC,EAAE,MAC/D"}
1
+ {"version":3,"file":"bundleManifest.cjs","names":[],"sources":["../../src/types/bundleManifest.ts"],"sourcesContent":["/**\n * A signed description of cockpit assets for an independently trusted verifier.\n *\n * A manifest does not let a browser SPA defend itself against the server or TLS\n * edge that supplied its executable code. Consumers need a separately trusted\n * bootstrap and key before these signatures become a delivery guarantee.\n */\n\nexport const BUNDLE_MANIFEST_ROUTE = '/bundle-manifest.json';\nexport const BUNDLE_MANIFEST_VERSION = 2;\n\nconst SHA256 = /^[0-9a-f]{64}$/u;\nconst BASE64URL = /^[A-Za-z0-9_-]+$/u;\nconst CONTENT_TYPE = /^[a-z0-9][a-z0-9!#$&^_.+-]*\\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u;\n\nexport interface BundleAsset {\n /** Normalized absolute URL path, without a query or fragment. */\n path: string;\n /** Lowercase hex SHA-256 of the served bytes. */\n sha256: string;\n byteLength: number;\n /** MIME type of the response, without parameters. */\n contentType: string;\n}\n\nexport interface BundleManifest {\n version: typeof BUNDLE_MANIFEST_VERSION;\n /** Monotonically increasing persistent signer revision. */\n revision: number;\n /** Unix time in milliseconds. */\n builtAt: number;\n assets: BundleAsset[];\n}\n\nexport interface SignedBundleManifest {\n manifest: BundleManifest;\n /** Base64url IEEE P1363 ECDSA P-256 signature over the canonical serialization. */\n signature: string;\n /** Base64url SPKI of the signing key. Trust must be established out of band. */\n publicKey: string;\n}\n\nfunction hasExactKeys(value: object, expected: readonly string[]): boolean {\n const keys = Object.keys(value).sort();\n return keys.length === expected.length && keys.every((key, index) => key === expected[index]);\n}\n\nfunction isSafeInteger(value: unknown, minimum: number): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum;\n}\n\nfunction isSafeAssetPath(value: unknown): value is string {\n if (typeof value !== 'string' || value.length < 2 || !value.startsWith('/')) return false;\n if (value.includes('\\\\') || value.includes('\\0') || value.includes('?') || value.includes('#')) return false;\n if (/[^\\x21-\\x7e]/u.test(value) || value.includes('//') || /%(?![0-9a-f]{2})/iu.test(value)) return false;\n if (/%(?:2e|2f|5c)/iu.test(value)) return false;\n return value\n .split('/')\n .slice(1)\n .every((segment) => segment !== '' && segment !== '.' && segment !== '..');\n}\n\n/** The exact bytes signed by Node and verified by WebCrypto. */\nexport function canonicalManifest(manifest: BundleManifest): string {\n const assets = [...manifest.assets].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n );\n const lines = assets.map(\n (asset) => `${asset.path}\\0${asset.sha256}\\0${String(asset.byteLength)}\\0${asset.contentType}`,\n );\n return [String(manifest.version), String(manifest.revision), String(manifest.builtAt), ...lines].join('\\n');\n}\n\nexport function isBundleManifest(value: unknown): value is BundleManifest {\n if (typeof value !== 'object' || value === null) return false;\n if (!hasExactKeys(value, ['assets', 'builtAt', 'revision', 'version'])) return false;\n const candidate = value as Partial<BundleManifest>;\n if (candidate.version !== BUNDLE_MANIFEST_VERSION) return false;\n if (!isSafeInteger(candidate.revision, 1) || !isSafeInteger(candidate.builtAt, 0)) return false;\n if (!Array.isArray(candidate.assets) || candidate.assets.length === 0) return false;\n\n const paths = new Set<string>();\n for (const valueAsset of candidate.assets) {\n if (typeof valueAsset !== 'object' || valueAsset === null) return false;\n if (!hasExactKeys(valueAsset, ['byteLength', 'contentType', 'path', 'sha256'])) return false;\n const asset = valueAsset as Partial<BundleAsset>;\n if (!isSafeAssetPath(asset.path) || paths.has(asset.path)) return false;\n if (typeof asset.sha256 !== 'string' || !SHA256.test(asset.sha256)) return false;\n if (!isSafeInteger(asset.byteLength, 0)) return false;\n if (typeof asset.contentType !== 'string' || !CONTENT_TYPE.test(asset.contentType)) return false;\n paths.add(asset.path);\n }\n return paths.has('/index.html');\n}\n\nexport function isSignedBundleManifest(value: unknown): value is SignedBundleManifest {\n if (typeof value !== 'object' || value === null) return false;\n if (!hasExactKeys(value, ['manifest', 'publicKey', 'signature'])) return false;\n const candidate = value as Partial<SignedBundleManifest>;\n return (\n isBundleManifest(candidate.manifest) &&\n typeof candidate.signature === 'string' &&\n candidate.signature.length === 86 &&\n BASE64URL.test(candidate.signature) &&\n typeof candidate.publicKey === 'string' &&\n candidate.publicKey.length <= 512 &&\n BASE64URL.test(candidate.publicKey)\n );\n}\n\n/** The recorded asset for one path, or undefined if the manifest does not cover it. */\nexport function assetFor(manifest: BundleManifest, path: string): BundleAsset | undefined {\n return manifest.assets.find((asset) => asset.path === path);\n}\n\n/** The recorded digest for one asset, or undefined if the manifest does not cover it. */\nexport function digestFor(manifest: BundleManifest, path: string): string | undefined {\n return assetFor(manifest, path)?.sha256;\n}\n"],"mappings":"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"}
@@ -3,46 +3,42 @@
3
3
  * A signed description of cockpit assets for an independently trusted verifier.
4
4
  *
5
5
  * A manifest does not let a browser SPA defend itself against the server or TLS
6
- * edge that supplied its executable code. Such an attacker can omit the
7
- * verifier or substitute its trust key. Consumers need a separately trusted
6
+ * edge that supplied its executable code. Consumers need a separately trusted
8
7
  * bootstrap and key before these signatures become a delivery guarantee.
9
- *
10
- * Lives in types rather than services because any verifier must use the same
11
- * canonical encoding the server signs, byte for byte.
12
8
  */
13
- declare const BUNDLE_MANIFEST_ROUTE = "/bundle-manifest.json";
14
- declare const BUNDLE_MANIFEST_VERSION = 1;
15
- interface BundleAsset {
16
- /** Path as the browser requests it, leading slash included. */
9
+ export declare const BUNDLE_MANIFEST_ROUTE = "/bundle-manifest.json";
10
+ export declare const BUNDLE_MANIFEST_VERSION = 2;
11
+ export interface BundleAsset {
12
+ /** Normalized absolute URL path, without a query or fragment. */
17
13
  path: string;
18
- /** Lowercase hex SHA-256 of the bytes served at that path. */
14
+ /** Lowercase hex SHA-256 of the served bytes. */
19
15
  sha256: string;
16
+ byteLength: number;
17
+ /** MIME type of the response, without parameters. */
18
+ contentType: string;
20
19
  }
21
- interface BundleManifest {
22
- version: number;
23
- /** Milliseconds, so a stale manifest is visible without another lookup. */
20
+ export interface BundleManifest {
21
+ version: typeof BUNDLE_MANIFEST_VERSION;
22
+ /** Monotonically increasing persistent signer revision. */
23
+ revision: number;
24
+ /** Unix time in milliseconds. */
24
25
  builtAt: number;
25
26
  assets: BundleAsset[];
26
27
  }
27
- interface SignedBundleManifest {
28
+ export interface SignedBundleManifest {
28
29
  manifest: BundleManifest;
29
- /** Base64url ECDSA P-256 signature over the canonical serialization. */
30
+ /** Base64url IEEE P1363 ECDSA P-256 signature over the canonical serialization. */
30
31
  signature: string;
31
- /** Base64url SPKI of the key that signed it; trust must be established out of band. */
32
+ /** Base64url SPKI of the signing key. Trust must be established out of band. */
32
33
  publicKey: string;
33
34
  }
34
- /**
35
- * The exact bytes that get signed.
36
- *
37
- * Hand-rolled rather than `JSON.stringify` of the whole object, because a
38
- * signature is only worth anything if both sides agree byte for byte on what
39
- * was signed. Key order in a JSON object is an implementation detail; a sorted
40
- * line-per-asset encoding is not.
41
- */
42
- declare function canonicalManifest(manifest: BundleManifest): string;
43
- declare function isBundleManifest(value: unknown): value is BundleManifest;
35
+ /** The exact bytes signed by Node and verified by WebCrypto. */
36
+ export declare function canonicalManifest(manifest: BundleManifest): string;
37
+ export declare function isBundleManifest(value: unknown): value is BundleManifest;
38
+ export declare function isSignedBundleManifest(value: unknown): value is SignedBundleManifest;
39
+ /** The recorded asset for one path, or undefined if the manifest does not cover it. */
40
+ export declare function assetFor(manifest: BundleManifest, path: string): BundleAsset | undefined;
44
41
  /** The recorded digest for one asset, or undefined if the manifest does not cover it. */
45
- declare function digestFor(manifest: BundleManifest, path: string): string | undefined;
42
+ export declare function digestFor(manifest: BundleManifest, path: string): string | undefined;
46
43
  //#endregion
47
- export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, canonicalManifest, digestFor, isBundleManifest };
48
44
  //# sourceMappingURL=bundleManifest.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bundleManifest.d.cts","names":[],"sources":["../../src/types/bundleManifest.ts"],"mappings":";;;;;;;;;;;;cAYa;cACA;UAEI;;EAEf;;EAEA;;UAGe;EACf;;EAEA;EACA,QAAQ;;UAGO;EACf,UAAU;;EAEV;;EAEA;;;;;;;;;;iBAWc,kBAAkB,UAAU;iBAQ5B,iBAAiB,iBAAiB,SAAS;;iBAe3C,UAAU,UAAU,gBAAgB"}
1
+ {"version":3,"file":"bundleManifest.d.cts","names":[],"sources":["../../src/types/bundleManifest.ts"],"mappings":";;;;;;;;qBAQa;qBACA;iBAMI;;EAEf;;EAEA;EACA;;EAEA;;iBAGe;EACf,gBAAgB;;EAEhB;;EAEA;EACA,QAAQ;;iBAGO;EACf,UAAU;;EAEV;;EAEA;;;wBAwBc,kBAAkB,UAAU;wBAU5B,iBAAiB,iBAAiB,SAAS;wBAsB3C,uBAAuB,iBAAiB,SAAS;;wBAgBjD,SAAS,UAAU,gBAAgB,eAAe;;wBAKlD,UAAU,UAAU,gBAAgB"}
@@ -3,46 +3,42 @@
3
3
  * A signed description of cockpit assets for an independently trusted verifier.
4
4
  *
5
5
  * A manifest does not let a browser SPA defend itself against the server or TLS
6
- * edge that supplied its executable code. Such an attacker can omit the
7
- * verifier or substitute its trust key. Consumers need a separately trusted
6
+ * edge that supplied its executable code. Consumers need a separately trusted
8
7
  * bootstrap and key before these signatures become a delivery guarantee.
9
- *
10
- * Lives in types rather than services because any verifier must use the same
11
- * canonical encoding the server signs, byte for byte.
12
8
  */
13
- declare const BUNDLE_MANIFEST_ROUTE = "/bundle-manifest.json";
14
- declare const BUNDLE_MANIFEST_VERSION = 1;
15
- interface BundleAsset {
16
- /** Path as the browser requests it, leading slash included. */
9
+ export declare const BUNDLE_MANIFEST_ROUTE = "/bundle-manifest.json";
10
+ export declare const BUNDLE_MANIFEST_VERSION = 2;
11
+ export interface BundleAsset {
12
+ /** Normalized absolute URL path, without a query or fragment. */
17
13
  path: string;
18
- /** Lowercase hex SHA-256 of the bytes served at that path. */
14
+ /** Lowercase hex SHA-256 of the served bytes. */
19
15
  sha256: string;
16
+ byteLength: number;
17
+ /** MIME type of the response, without parameters. */
18
+ contentType: string;
20
19
  }
21
- interface BundleManifest {
22
- version: number;
23
- /** Milliseconds, so a stale manifest is visible without another lookup. */
20
+ export interface BundleManifest {
21
+ version: typeof BUNDLE_MANIFEST_VERSION;
22
+ /** Monotonically increasing persistent signer revision. */
23
+ revision: number;
24
+ /** Unix time in milliseconds. */
24
25
  builtAt: number;
25
26
  assets: BundleAsset[];
26
27
  }
27
- interface SignedBundleManifest {
28
+ export interface SignedBundleManifest {
28
29
  manifest: BundleManifest;
29
- /** Base64url ECDSA P-256 signature over the canonical serialization. */
30
+ /** Base64url IEEE P1363 ECDSA P-256 signature over the canonical serialization. */
30
31
  signature: string;
31
- /** Base64url SPKI of the key that signed it; trust must be established out of band. */
32
+ /** Base64url SPKI of the signing key. Trust must be established out of band. */
32
33
  publicKey: string;
33
34
  }
34
- /**
35
- * The exact bytes that get signed.
36
- *
37
- * Hand-rolled rather than `JSON.stringify` of the whole object, because a
38
- * signature is only worth anything if both sides agree byte for byte on what
39
- * was signed. Key order in a JSON object is an implementation detail; a sorted
40
- * line-per-asset encoding is not.
41
- */
42
- declare function canonicalManifest(manifest: BundleManifest): string;
43
- declare function isBundleManifest(value: unknown): value is BundleManifest;
35
+ /** The exact bytes signed by Node and verified by WebCrypto. */
36
+ export declare function canonicalManifest(manifest: BundleManifest): string;
37
+ export declare function isBundleManifest(value: unknown): value is BundleManifest;
38
+ export declare function isSignedBundleManifest(value: unknown): value is SignedBundleManifest;
39
+ /** The recorded asset for one path, or undefined if the manifest does not cover it. */
40
+ export declare function assetFor(manifest: BundleManifest, path: string): BundleAsset | undefined;
44
41
  /** The recorded digest for one asset, or undefined if the manifest does not cover it. */
45
- declare function digestFor(manifest: BundleManifest, path: string): string | undefined;
42
+ export declare function digestFor(manifest: BundleManifest, path: string): string | undefined;
46
43
  //#endregion
47
- export { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, canonicalManifest, digestFor, isBundleManifest };
48
44
  //# sourceMappingURL=bundleManifest.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bundleManifest.d.mts","names":[],"sources":["../../src/types/bundleManifest.ts"],"mappings":";;;;;;;;;;;;cAYa;cACA;UAEI;;EAEf;;EAEA;;UAGe;EACf;;EAEA;EACA,QAAQ;;UAGO;EACf,UAAU;;EAEV;;EAEA;;;;;;;;;;iBAWc,kBAAkB,UAAU;iBAQ5B,iBAAiB,iBAAiB,SAAS;;iBAe3C,UAAU,UAAU,gBAAgB"}
1
+ {"version":3,"file":"bundleManifest.d.mts","names":[],"sources":["../../src/types/bundleManifest.ts"],"mappings":";;;;;;;;qBAQa;qBACA;iBAMI;;EAEf;;EAEA;EACA;;EAEA;;iBAGe;EACf,gBAAgB;;EAEhB;;EAEA;EACA,QAAQ;;iBAGO;EACf,UAAU;;EAEV;;EAEA;;;wBAwBc,kBAAkB,UAAU;wBAU5B,iBAAiB,iBAAiB,SAAS;wBAsB3C,uBAAuB,iBAAiB,SAAS;;wBAgBjD,SAAS,UAAU,gBAAgB,eAAe;;wBAKlD,UAAU,UAAU,gBAAgB"}
Binary file
@@ -1 +1 @@
1
- {"version":3,"file":"bundleManifest.mjs","names":[],"sources":["../../src/types/bundleManifest.ts"],"sourcesContent":["/**\n * A signed description of cockpit assets for an independently trusted verifier.\n *\n * A manifest does not let a browser SPA defend itself against the server or TLS\n * edge that supplied its executable code. Such an attacker can omit the\n * verifier or substitute its trust key. Consumers need a separately trusted\n * bootstrap and key before these signatures become a delivery guarantee.\n *\n * Lives in types rather than services because any verifier must use the same\n * canonical encoding the server signs, byte for byte.\n */\n\nexport const BUNDLE_MANIFEST_ROUTE = '/bundle-manifest.json';\nexport const BUNDLE_MANIFEST_VERSION = 1;\n\nexport interface BundleAsset {\n /** Path as the browser requests it, leading slash included. */\n path: string;\n /** Lowercase hex SHA-256 of the bytes served at that path. */\n sha256: string;\n}\n\nexport interface BundleManifest {\n version: number;\n /** Milliseconds, so a stale manifest is visible without another lookup. */\n builtAt: number;\n assets: BundleAsset[];\n}\n\nexport interface SignedBundleManifest {\n manifest: BundleManifest;\n /** Base64url ECDSA P-256 signature over the canonical serialization. */\n signature: string;\n /** Base64url SPKI of the key that signed it; trust must be established out of band. */\n publicKey: string;\n}\n\n/**\n * The exact bytes that get signed.\n *\n * Hand-rolled rather than `JSON.stringify` of the whole object, because a\n * signature is only worth anything if both sides agree byte for byte on what\n * was signed. Key order in a JSON object is an implementation detail; a sorted\n * line-per-asset encoding is not.\n */\nexport function canonicalManifest(manifest: BundleManifest): string {\n const assets = [...manifest.assets].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n );\n const lines = assets.map((asset) => `${asset.path}\u0000${asset.sha256}`);\n return [String(manifest.version), String(manifest.builtAt), ...lines].join('\\n');\n}\n\nexport function isBundleManifest(value: unknown): value is BundleManifest {\n if (typeof value !== 'object' || value === null) return false;\n const candidate = value as Partial<BundleManifest>;\n if (candidate.version !== BUNDLE_MANIFEST_VERSION) return false;\n if (typeof candidate.builtAt !== 'number' || !Array.isArray(candidate.assets)) return false;\n return candidate.assets.every(\n (asset: unknown) =>\n typeof asset === 'object' &&\n asset !== null &&\n typeof (asset as BundleAsset).path === 'string' &&\n /^[0-9a-f]{64}$/u.test((asset as BundleAsset).sha256),\n );\n}\n\n/** The recorded digest for one asset, or undefined if the manifest does not cover it. */\nexport function digestFor(manifest: BundleManifest, path: string): string | undefined {\n return manifest.assets.find((asset) => asset.path === path)?.sha256;\n}\n"],"mappings":"AAYA,MAAa,EAAwB,wBACxB,EAA0B,EAgCvC,SAAgB,EAAkB,EAAkC,CAIlE,IAAM,EAHS,CAAC,GAAG,EAAS,MAAM,CAAC,CAAC,MAAM,EAAM,IAC9C,EAAK,KAAO,EAAM,KAAO,GAAK,IAAK,KAAO,EAAM,KAE/B,CAAC,CAAC,IAAK,GAAU,GAAG,EAAM,KAAK,GAAG,EAAM,QAAQ,EACnE,MAAO,CAAC,OAAO,EAAS,OAAO,EAAG,OAAO,EAAS,OAAO,EAAG,GAAG,CAAK,CAAC,CAAC,KAAK;CAAI,CACjF,CAEA,SAAgB,EAAiB,EAAyC,CACxE,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,IAAM,EAAY,EAGlB,OAFI,EAAU,UAAA,GACV,OAAO,EAAU,SAAY,UAAY,CAAC,MAAM,QAAQ,EAAU,MAAM,EAAU,GAC/E,EAAU,OAAO,MACrB,GACC,OAAO,GAAU,YACjB,GACA,OAAQ,EAAsB,MAAS,UACvC,kBAAkB,KAAM,EAAsB,MAAM,CACxD,CACF,CAGA,SAAgB,EAAU,EAA0B,EAAkC,CACpF,OAAO,EAAS,OAAO,KAAM,GAAU,EAAM,OAAS,CAAI,CAAC,EAAE,MAC/D"}
1
+ {"version":3,"file":"bundleManifest.mjs","names":[],"sources":["../../src/types/bundleManifest.ts"],"sourcesContent":["/**\n * A signed description of cockpit assets for an independently trusted verifier.\n *\n * A manifest does not let a browser SPA defend itself against the server or TLS\n * edge that supplied its executable code. Consumers need a separately trusted\n * bootstrap and key before these signatures become a delivery guarantee.\n */\n\nexport const BUNDLE_MANIFEST_ROUTE = '/bundle-manifest.json';\nexport const BUNDLE_MANIFEST_VERSION = 2;\n\nconst SHA256 = /^[0-9a-f]{64}$/u;\nconst BASE64URL = /^[A-Za-z0-9_-]+$/u;\nconst CONTENT_TYPE = /^[a-z0-9][a-z0-9!#$&^_.+-]*\\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u;\n\nexport interface BundleAsset {\n /** Normalized absolute URL path, without a query or fragment. */\n path: string;\n /** Lowercase hex SHA-256 of the served bytes. */\n sha256: string;\n byteLength: number;\n /** MIME type of the response, without parameters. */\n contentType: string;\n}\n\nexport interface BundleManifest {\n version: typeof BUNDLE_MANIFEST_VERSION;\n /** Monotonically increasing persistent signer revision. */\n revision: number;\n /** Unix time in milliseconds. */\n builtAt: number;\n assets: BundleAsset[];\n}\n\nexport interface SignedBundleManifest {\n manifest: BundleManifest;\n /** Base64url IEEE P1363 ECDSA P-256 signature over the canonical serialization. */\n signature: string;\n /** Base64url SPKI of the signing key. Trust must be established out of band. */\n publicKey: string;\n}\n\nfunction hasExactKeys(value: object, expected: readonly string[]): boolean {\n const keys = Object.keys(value).sort();\n return keys.length === expected.length && keys.every((key, index) => key === expected[index]);\n}\n\nfunction isSafeInteger(value: unknown, minimum: number): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum;\n}\n\nfunction isSafeAssetPath(value: unknown): value is string {\n if (typeof value !== 'string' || value.length < 2 || !value.startsWith('/')) return false;\n if (value.includes('\\\\') || value.includes('\\0') || value.includes('?') || value.includes('#')) return false;\n if (/[^\\x21-\\x7e]/u.test(value) || value.includes('//') || /%(?![0-9a-f]{2})/iu.test(value)) return false;\n if (/%(?:2e|2f|5c)/iu.test(value)) return false;\n return value\n .split('/')\n .slice(1)\n .every((segment) => segment !== '' && segment !== '.' && segment !== '..');\n}\n\n/** The exact bytes signed by Node and verified by WebCrypto. */\nexport function canonicalManifest(manifest: BundleManifest): string {\n const assets = [...manifest.assets].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n );\n const lines = assets.map(\n (asset) => `${asset.path}\\0${asset.sha256}\\0${String(asset.byteLength)}\\0${asset.contentType}`,\n );\n return [String(manifest.version), String(manifest.revision), String(manifest.builtAt), ...lines].join('\\n');\n}\n\nexport function isBundleManifest(value: unknown): value is BundleManifest {\n if (typeof value !== 'object' || value === null) return false;\n if (!hasExactKeys(value, ['assets', 'builtAt', 'revision', 'version'])) return false;\n const candidate = value as Partial<BundleManifest>;\n if (candidate.version !== BUNDLE_MANIFEST_VERSION) return false;\n if (!isSafeInteger(candidate.revision, 1) || !isSafeInteger(candidate.builtAt, 0)) return false;\n if (!Array.isArray(candidate.assets) || candidate.assets.length === 0) return false;\n\n const paths = new Set<string>();\n for (const valueAsset of candidate.assets) {\n if (typeof valueAsset !== 'object' || valueAsset === null) return false;\n if (!hasExactKeys(valueAsset, ['byteLength', 'contentType', 'path', 'sha256'])) return false;\n const asset = valueAsset as Partial<BundleAsset>;\n if (!isSafeAssetPath(asset.path) || paths.has(asset.path)) return false;\n if (typeof asset.sha256 !== 'string' || !SHA256.test(asset.sha256)) return false;\n if (!isSafeInteger(asset.byteLength, 0)) return false;\n if (typeof asset.contentType !== 'string' || !CONTENT_TYPE.test(asset.contentType)) return false;\n paths.add(asset.path);\n }\n return paths.has('/index.html');\n}\n\nexport function isSignedBundleManifest(value: unknown): value is SignedBundleManifest {\n if (typeof value !== 'object' || value === null) return false;\n if (!hasExactKeys(value, ['manifest', 'publicKey', 'signature'])) return false;\n const candidate = value as Partial<SignedBundleManifest>;\n return (\n isBundleManifest(candidate.manifest) &&\n typeof candidate.signature === 'string' &&\n candidate.signature.length === 86 &&\n BASE64URL.test(candidate.signature) &&\n typeof candidate.publicKey === 'string' &&\n candidate.publicKey.length <= 512 &&\n BASE64URL.test(candidate.publicKey)\n );\n}\n\n/** The recorded asset for one path, or undefined if the manifest does not cover it. */\nexport function assetFor(manifest: BundleManifest, path: string): BundleAsset | undefined {\n return manifest.assets.find((asset) => asset.path === path);\n}\n\n/** The recorded digest for one asset, or undefined if the manifest does not cover it. */\nexport function digestFor(manifest: BundleManifest, path: string): string | undefined {\n return assetFor(manifest, path)?.sha256;\n}\n"],"mappings":"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"}
@@ -18,15 +18,15 @@
18
18
  * read it identically.
19
19
  */
20
20
  /** Bumped when the envelope layout changes; a mismatch is refused, never guessed at. */
21
- declare const SEALED_VERSION = 1;
21
+ export declare const SEALED_VERSION = 1;
22
22
  /** Fragment key in the pairing URL carrying the host's ephemeral public key. */
23
- declare const SEALED_KEY_PARAM = "k";
23
+ export declare const SEALED_KEY_PARAM = "k";
24
24
  /** AES-GCM standard nonce length. Longer is non-standard, shorter is unsafe. */
25
- declare const NONCE_BYTES = 12;
25
+ export declare const NONCE_BYTES = 12;
26
26
  /** Random per-channel prefix, so two channels never share a nonce space. */
27
- declare const NONCE_PREFIX_BYTES = 4;
27
+ export declare const NONCE_PREFIX_BYTES = 4;
28
28
  /** Monotonic per-direction counter filling the rest of the nonce. */
29
- declare const NONCE_COUNTER_BYTES: number;
29
+ export declare const NONCE_COUNTER_BYTES: number;
30
30
  /**
31
31
  * Rekey well before the counter could wrap.
32
32
  *
@@ -35,43 +35,42 @@ declare const NONCE_COUNTER_BYTES: number;
35
35
  * 64 bits, so this bound is nowhere near it; the point is that the bound exists
36
36
  * and is enforced rather than assumed.
37
37
  */
38
- declare const MAX_MESSAGES_PER_KEY: number;
38
+ export declare const MAX_MESSAGES_PER_KEY: number;
39
39
  /**
40
40
  * HKDF info strings, one per direction.
41
41
  *
42
42
  * Separate keys per direction, not one shared key, so a message the server sent
43
43
  * can never be replayed back at it as though the client had sent it.
44
44
  */
45
- declare const CLIENT_TO_SERVER_INFO = "doompi/sealed/c2s/v1";
46
- declare const SERVER_TO_CLIENT_INFO = "doompi/sealed/s2c/v1";
47
- type SealedDirection = 'c2s' | 's2c';
48
- declare function infoFor(direction: SealedDirection): string;
45
+ export declare const CLIENT_TO_SERVER_INFO = "doompi/sealed/c2s/v1";
46
+ export declare const SERVER_TO_CLIENT_INFO = "doompi/sealed/s2c/v1";
47
+ export type SealedDirection = 'c2s' | 's2c';
48
+ export declare function infoFor(direction: SealedDirection): string;
49
49
  /**
50
50
  * One sealed message, as it travels.
51
51
  *
52
52
  * Base64url rather than binary so the same envelope works on a JSON body and a
53
53
  * text WebSocket frame without a second encoding path to get wrong.
54
54
  */
55
- interface SealedEnvelope {
55
+ export interface SealedEnvelope {
56
56
  v: number;
57
57
  /** Base64url, 4-byte prefix plus 8-byte counter. */
58
58
  n: string;
59
59
  /** Base64url ciphertext with the GCM tag appended. */
60
60
  c: string;
61
61
  }
62
- declare function isSealedEnvelope(value: unknown): value is SealedEnvelope;
62
+ export declare function isSealedEnvelope(value: unknown): value is SealedEnvelope;
63
63
  /** Header naming the client's ephemeral public key during the handshake. */
64
- declare const SEALED_CLIENT_KEY_HEADER = "x-doompi-channel-key";
64
+ export declare const SEALED_CLIENT_KEY_HEADER = "x-doompi-channel-key";
65
65
  /** Header carrying a sealed request body's envelope on a non-JSON request. */
66
- declare const SEALED_BODY_HEADER = "x-doompi-sealed";
67
- type SealedFailure = 'version' | 'malformed' | 'replay' | 'auth' | 'exhausted';
66
+ export declare const SEALED_BODY_HEADER = "x-doompi-sealed";
67
+ export type SealedFailure = 'version' | 'malformed' | 'replay' | 'auth' | 'exhausted';
68
68
  /**
69
69
  * Why an unseal failed, in words a diagnostic can show.
70
70
  *
71
71
  * A decryption failure means a blank cockpit, so every one of these has to name
72
72
  * its cause rather than leaving a dead page and no explanation.
73
73
  */
74
- declare function describeSealedFailure(failure: SealedFailure): string;
74
+ export declare function describeSealedFailure(failure: SealedFailure): string;
75
75
  //#endregion
76
- export { CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, SealedDirection, SealedEnvelope, SealedFailure, describeSealedFailure, infoFor, isSealedEnvelope };
77
76
  //# sourceMappingURL=sealedChannel.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sealedChannel.d.cts","names":[],"sources":["../../src/types/sealedChannel.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;cAoBa;;cAGA;;cAGA;;cAEA;;cAEA;;;;;;;;;cAUA;;;;;;;cAQA;cACA;KAED;iBAEI,QAAQ,WAAW;;;;;;;UAUlB;EACf;;EAEA;;EAEA;;iBAGc,iBAAiB,iBAAiB,SAAS;;cAO9C;;cAEA;KAED;;;;;;;iBAQI,sBAAsB,SAAS"}
1
+ {"version":3,"file":"sealedChannel.d.cts","names":[],"sources":["../../src/types/sealedChannel.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;qBAoBa;;qBAGA;;qBAGA;;qBAEA;;qBAEA;;;;;;;;;qBAUA;;;;;;;qBAQA;qBACA;YAED;wBAEI,QAAQ,WAAW;;;;;;;iBAUlB;EACf;;EAEA;;EAEA;;wBAGc,iBAAiB,iBAAiB,SAAS;;qBAO9C;;qBAEA;YAED;;;;;;;wBAQI,sBAAsB,SAAS"}
@@ -18,15 +18,15 @@
18
18
  * read it identically.
19
19
  */
20
20
  /** Bumped when the envelope layout changes; a mismatch is refused, never guessed at. */
21
- declare const SEALED_VERSION = 1;
21
+ export declare const SEALED_VERSION = 1;
22
22
  /** Fragment key in the pairing URL carrying the host's ephemeral public key. */
23
- declare const SEALED_KEY_PARAM = "k";
23
+ export declare const SEALED_KEY_PARAM = "k";
24
24
  /** AES-GCM standard nonce length. Longer is non-standard, shorter is unsafe. */
25
- declare const NONCE_BYTES = 12;
25
+ export declare const NONCE_BYTES = 12;
26
26
  /** Random per-channel prefix, so two channels never share a nonce space. */
27
- declare const NONCE_PREFIX_BYTES = 4;
27
+ export declare const NONCE_PREFIX_BYTES = 4;
28
28
  /** Monotonic per-direction counter filling the rest of the nonce. */
29
- declare const NONCE_COUNTER_BYTES: number;
29
+ export declare const NONCE_COUNTER_BYTES: number;
30
30
  /**
31
31
  * Rekey well before the counter could wrap.
32
32
  *
@@ -35,43 +35,42 @@ declare const NONCE_COUNTER_BYTES: number;
35
35
  * 64 bits, so this bound is nowhere near it; the point is that the bound exists
36
36
  * and is enforced rather than assumed.
37
37
  */
38
- declare const MAX_MESSAGES_PER_KEY: number;
38
+ export declare const MAX_MESSAGES_PER_KEY: number;
39
39
  /**
40
40
  * HKDF info strings, one per direction.
41
41
  *
42
42
  * Separate keys per direction, not one shared key, so a message the server sent
43
43
  * can never be replayed back at it as though the client had sent it.
44
44
  */
45
- declare const CLIENT_TO_SERVER_INFO = "doompi/sealed/c2s/v1";
46
- declare const SERVER_TO_CLIENT_INFO = "doompi/sealed/s2c/v1";
47
- type SealedDirection = 'c2s' | 's2c';
48
- declare function infoFor(direction: SealedDirection): string;
45
+ export declare const CLIENT_TO_SERVER_INFO = "doompi/sealed/c2s/v1";
46
+ export declare const SERVER_TO_CLIENT_INFO = "doompi/sealed/s2c/v1";
47
+ export type SealedDirection = 'c2s' | 's2c';
48
+ export declare function infoFor(direction: SealedDirection): string;
49
49
  /**
50
50
  * One sealed message, as it travels.
51
51
  *
52
52
  * Base64url rather than binary so the same envelope works on a JSON body and a
53
53
  * text WebSocket frame without a second encoding path to get wrong.
54
54
  */
55
- interface SealedEnvelope {
55
+ export interface SealedEnvelope {
56
56
  v: number;
57
57
  /** Base64url, 4-byte prefix plus 8-byte counter. */
58
58
  n: string;
59
59
  /** Base64url ciphertext with the GCM tag appended. */
60
60
  c: string;
61
61
  }
62
- declare function isSealedEnvelope(value: unknown): value is SealedEnvelope;
62
+ export declare function isSealedEnvelope(value: unknown): value is SealedEnvelope;
63
63
  /** Header naming the client's ephemeral public key during the handshake. */
64
- declare const SEALED_CLIENT_KEY_HEADER = "x-doompi-channel-key";
64
+ export declare const SEALED_CLIENT_KEY_HEADER = "x-doompi-channel-key";
65
65
  /** Header carrying a sealed request body's envelope on a non-JSON request. */
66
- declare const SEALED_BODY_HEADER = "x-doompi-sealed";
67
- type SealedFailure = 'version' | 'malformed' | 'replay' | 'auth' | 'exhausted';
66
+ export declare const SEALED_BODY_HEADER = "x-doompi-sealed";
67
+ export type SealedFailure = 'version' | 'malformed' | 'replay' | 'auth' | 'exhausted';
68
68
  /**
69
69
  * Why an unseal failed, in words a diagnostic can show.
70
70
  *
71
71
  * A decryption failure means a blank cockpit, so every one of these has to name
72
72
  * its cause rather than leaving a dead page and no explanation.
73
73
  */
74
- declare function describeSealedFailure(failure: SealedFailure): string;
74
+ export declare function describeSealedFailure(failure: SealedFailure): string;
75
75
  //#endregion
76
- export { CLIENT_TO_SERVER_INFO, MAX_MESSAGES_PER_KEY, NONCE_BYTES, NONCE_COUNTER_BYTES, NONCE_PREFIX_BYTES, SEALED_BODY_HEADER, SEALED_CLIENT_KEY_HEADER, SEALED_KEY_PARAM, SEALED_VERSION, SERVER_TO_CLIENT_INFO, SealedDirection, SealedEnvelope, SealedFailure, describeSealedFailure, infoFor, isSealedEnvelope };
77
76
  //# sourceMappingURL=sealedChannel.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sealedChannel.d.mts","names":[],"sources":["../../src/types/sealedChannel.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;cAoBa;;cAGA;;cAGA;;cAEA;;cAEA;;;;;;;;;cAUA;;;;;;;cAQA;cACA;KAED;iBAEI,QAAQ,WAAW;;;;;;;UAUlB;EACf;;EAEA;;EAEA;;iBAGc,iBAAiB,iBAAiB,SAAS;;cAO9C;;cAEA;KAED;;;;;;;iBAQI,sBAAsB,SAAS"}
1
+ {"version":3,"file":"sealedChannel.d.mts","names":[],"sources":["../../src/types/sealedChannel.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;qBAoBa;;qBAGA;;qBAGA;;qBAEA;;qBAEA;;;;;;;;;qBAUA;;;;;;;qBAQA;qBACA;YAED;wBAEI,QAAQ,WAAW;;;;;;;iBAUlB;EACf;;EAEA;;EAEA;;wBAGc,iBAAiB,iBAAiB,SAAS;;qBAO9C;;qBAEA;YAED;;;;;;;wBAQI,sBAAsB,SAAS"}