@agimon-ai/doompi-web-security 0.0.1-alpha.40 → 0.0.1-alpha.42
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/package.json +1 -1
- package/dist/browser.d.cts +0 -5
- package/dist/index.d.cts +0 -4
- package/dist/node.d.cts +0 -3
- package/dist/services/browserBundleVerifier/index.d.cts +0 -44
- package/dist/services/browserBundleVerifier/index.d.cts.map +0 -1
- package/dist/services/browserSealedChannel/index.d.cts +0 -35
- package/dist/services/browserSealedChannel/index.d.cts.map +0 -1
- package/dist/services/bundleSigner/index.d.cts +0 -17
- package/dist/services/bundleSigner/index.d.cts.map +0 -1
- package/dist/services/nodeSealedChannel/index.d.cts +0 -47
- package/dist/services/nodeSealedChannel/index.d.cts.map +0 -1
- package/dist/services/sealedTransport/index.d.cts +0 -42
- package/dist/services/sealedTransport/index.d.cts.map +0 -1
- package/dist/services/serialQueue/index.d.cts +0 -22
- package/dist/services/serialQueue/index.d.cts.map +0 -1
- package/dist/types/bundleManifest.d.cts +0 -44
- package/dist/types/bundleManifest.d.cts.map +0 -1
- package/dist/types/sealedChannel.d.cts +0 -76
- package/dist/types/sealedChannel.d.cts.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-web-security",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.42",
|
|
4
4
|
"description": "Shared security primitives for the DoomPi web cockpit: sealed channels and signed bundle manifests for independently trusted verifiers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
package/dist/browser.d.cts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
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 "./services/browserBundleVerifier/index.cjs";
|
|
3
|
-
import { OpenResult, SealResult, SealedChannel, channelFromSecret, connectSealedChannel } from "./services/browserSealedChannel/index.cjs";
|
|
4
|
-
import { SealedTransport, createSealedTransport, sealedTransport } from "./services/sealedTransport/index.cjs";
|
|
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/index.d.cts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { BUNDLE_MANIFEST_ROUTE, BUNDLE_MANIFEST_VERSION, BundleAsset, BundleManifest, SignedBundleManifest, assetFor, canonicalManifest, digestFor, isBundleManifest, isSignedBundleManifest } from "./types/bundleManifest.cjs";
|
|
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";
|
|
3
|
-
import { SerialQueue, createSerialQueue } from "./services/serialQueue/index.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, assetFor, canonicalManifest, createSerialQueue, describeSealedFailure, digestFor, infoFor, isBundleManifest, isSealedEnvelope, isSignedBundleManifest };
|
package/dist/node.d.cts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { ClientHandshake, HostHandshake, OpenResult, SealResult, SealedChannel, createClientHandshake, createHostHandshake } from "./services/nodeSealedChannel/index.cjs";
|
|
2
|
-
import { BundleSigner, createBundleSigner, publicKeyOf } from "./services/bundleSigner/index.cjs";
|
|
3
|
-
export { type BundleSigner, type ClientHandshake, type HostHandshake, type OpenResult, type SealResult, type SealedChannel, createBundleSigner, createClientHandshake, createHostHandshake, publicKeyOf };
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { BundleManifest } from "../../types/bundleManifest.cjs";
|
|
2
|
-
//#region src/services/browserBundleVerifier/index.d.ts
|
|
3
|
-
export type BundleVerificationFailure = {
|
|
4
|
-
code: 'invalid-envelope';
|
|
5
|
-
} | {
|
|
6
|
-
code: 'untrusted-public-key';
|
|
7
|
-
} | {
|
|
8
|
-
code: 'stale-revision';
|
|
9
|
-
minimumRevision: number;
|
|
10
|
-
actualRevision: number;
|
|
11
|
-
} | {
|
|
12
|
-
code: 'invalid-public-key';
|
|
13
|
-
} | {
|
|
14
|
-
code: 'invalid-signature';
|
|
15
|
-
};
|
|
16
|
-
export type BundleVerificationResult = {
|
|
17
|
-
ok: true;
|
|
18
|
-
manifest: BundleManifest;
|
|
19
|
-
} | {
|
|
20
|
-
ok: false;
|
|
21
|
-
failure: BundleVerificationFailure;
|
|
22
|
-
};
|
|
23
|
-
export type BundleAssetVerificationFailure = {
|
|
24
|
-
code: 'asset-not-listed';
|
|
25
|
-
path: string;
|
|
26
|
-
} | {
|
|
27
|
-
code: 'byte-length-mismatch';
|
|
28
|
-
expected: number;
|
|
29
|
-
actual: number;
|
|
30
|
-
} | {
|
|
31
|
-
code: 'digest-mismatch';
|
|
32
|
-
};
|
|
33
|
-
export type BundleAssetVerificationResult = {
|
|
34
|
-
ok: true;
|
|
35
|
-
} | {
|
|
36
|
-
ok: false;
|
|
37
|
-
failure: BundleAssetVerificationFailure;
|
|
38
|
-
};
|
|
39
|
-
/** Verifies a strict envelope against a separately trusted key and revision floor. */
|
|
40
|
-
export declare function verifySignedBundleManifest(value: unknown, trustedPublicKey: string, minimumRevision?: number): Promise<BundleVerificationResult>;
|
|
41
|
-
/** Verifies fetched raw response bytes against an authenticated manifest. */
|
|
42
|
-
export declare function verifyBundleAsset(manifest: BundleManifest, assetPath: string, bytes: ArrayBuffer): Promise<BundleAssetVerificationResult>;
|
|
43
|
-
//#endregion
|
|
44
|
-
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/browserBundleVerifier/index.ts"],"mappings":";;YAQY;EACN;;EACA;;EACA;EAAwB;EAAyB;;EACjD;;EACA;;YAEM;EACN;EAAU,UAAU;;EACpB;EAAW,SAAS;;YAEd;EACN;EAA0B;;EAC1B;EAA8B;EAAkB;;EAChD;;YAEM;EAAkC;;EAAe;EAAW,SAAS;;;wBAgB3D,2BACpB,gBACA,0BACA,2BACC,QAAQ;;wBAsCW,kBACpB,UAAU,gBACV,mBACA,OAAO,cACN,QAAQ"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { SealedDirection, SealedEnvelope, SealedFailure } from "../../types/sealedChannel.cjs";
|
|
2
|
-
//#region src/services/browserSealedChannel/index.d.ts
|
|
3
|
-
export type SealResult = {
|
|
4
|
-
ok: true;
|
|
5
|
-
envelope: SealedEnvelope;
|
|
6
|
-
} | {
|
|
7
|
-
ok: false;
|
|
8
|
-
failure: SealedFailure;
|
|
9
|
-
};
|
|
10
|
-
export type OpenResult = {
|
|
11
|
-
ok: true;
|
|
12
|
-
plaintext: Uint8Array;
|
|
13
|
-
} | {
|
|
14
|
-
ok: false;
|
|
15
|
-
failure: SealedFailure;
|
|
16
|
-
};
|
|
17
|
-
export interface SealedChannel {
|
|
18
|
-
seal(plaintext: Uint8Array): Promise<SealResult>;
|
|
19
|
-
open(envelope: unknown): Promise<OpenResult>;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Completes the handshake against the host key read out of the QR fragment.
|
|
23
|
-
*
|
|
24
|
-
* That key never travelled through the tunnel, which is what makes this
|
|
25
|
-
* authenticated: a relay can watch the client's public key go past and learn
|
|
26
|
-
* nothing, and it cannot substitute the host's because it never carried it.
|
|
27
|
-
*/
|
|
28
|
-
export declare function connectSealedChannel(hostPublicKey: string): Promise<{
|
|
29
|
-
channel: SealedChannel;
|
|
30
|
-
clientPublicKey: string;
|
|
31
|
-
} | undefined>;
|
|
32
|
-
/** Exposed so a test can build the browser side against a known secret. */
|
|
33
|
-
export declare function channelFromSecret(secret: ArrayBuffer, sendDirection: SealedDirection, noncePrefix: Uint8Array): Promise<SealedChannel>;
|
|
34
|
-
//#endregion
|
|
35
|
-
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/browserSealedChannel/index.ts"],"mappings":";;YA8BY;EAAe;EAAU,UAAU;;EAAqB;EAAW,SAAS;;YAC5E;EAAe;EAAU,WAAW;;EAAiB;EAAW,SAAS;;iBAEpE;EACf,KAAK,WAAW,aAAa,QAAQ;EACrC,KAAK,oBAAoB,QAAQ;;;;;;;;;wBA+Gb,qBACpB,wBACC;EAAU,SAAS;EAAe;;;wBAyBf,kBACpB,QAAQ,aACR,eAAe,iBACf,aAAa,aACZ,QAAQ"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { SignedBundleManifest } from "../../types/bundleManifest.cjs";
|
|
2
|
-
//#region src/services/bundleSigner/index.d.ts
|
|
3
|
-
export interface BundleSigner {
|
|
4
|
-
/** Base64url SPKI for an independently trusted verifier to pin. */
|
|
5
|
-
publicKey(): string;
|
|
6
|
-
/** Hashes and signs once per asset directory. Undefined when the bundle is empty. */
|
|
7
|
-
sign(assetsDir: string): SignedBundleManifest | undefined;
|
|
8
|
-
/** Invalidates and immediately rebuilds one cached manifest. */
|
|
9
|
-
refresh(assetsDir: string): SignedBundleManifest | undefined;
|
|
10
|
-
/** Invalidates one cached directory, or every cached directory when omitted. */
|
|
11
|
-
invalidate(assetsDir?: string): void;
|
|
12
|
-
}
|
|
13
|
-
export declare function createBundleSigner(stateDir: string, _onNotice?: (message: string) => void): BundleSigner;
|
|
14
|
-
/** Re-derives the public key from a stored private key. */
|
|
15
|
-
export declare function publicKeyOf(privateKeyPem: string): string;
|
|
16
|
-
//#endregion
|
|
17
|
-
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/bundleSigner/index.ts"],"mappings":";;iBA8CiB;;EAEf;;EAEA,KAAK,oBAAoB;;EAEzB,QAAQ,oBAAoB;;EAE5B,WAAW;;wBAsJG,mBAAmB,kBAAkB,aAAY,2BAAsC;;wBAoDvF,YAAY"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { SealedEnvelope, SealedFailure } from "../../types/sealedChannel.cjs";
|
|
2
|
-
//#region src/services/nodeSealedChannel/index.d.ts
|
|
3
|
-
export type SealResult = {
|
|
4
|
-
ok: true;
|
|
5
|
-
envelope: SealedEnvelope;
|
|
6
|
-
} | {
|
|
7
|
-
ok: false;
|
|
8
|
-
failure: SealedFailure;
|
|
9
|
-
};
|
|
10
|
-
export type OpenResult = {
|
|
11
|
-
ok: true;
|
|
12
|
-
plaintext: Uint8Array;
|
|
13
|
-
} | {
|
|
14
|
-
ok: false;
|
|
15
|
-
failure: SealedFailure;
|
|
16
|
-
};
|
|
17
|
-
export interface SealedChannel {
|
|
18
|
-
/** Seals one message. Counters advance only on success. */
|
|
19
|
-
seal(plaintext: Uint8Array): SealResult;
|
|
20
|
-
open(envelope: unknown): OpenResult;
|
|
21
|
-
}
|
|
22
|
-
export interface HostHandshake {
|
|
23
|
-
/** Base64url uncompressed P-256 point, printed in the QR. */
|
|
24
|
-
publicKey: string;
|
|
25
|
-
/** Completes the exchange against the peer's key and yields the channel. */
|
|
26
|
-
accept(peerPublicKey: string): SealedChannel | undefined;
|
|
27
|
-
}
|
|
28
|
-
export interface ClientHandshake {
|
|
29
|
-
/** Base64url uncompressed P-256 point sent to the host. */
|
|
30
|
-
publicKey: string;
|
|
31
|
-
/** Completes the exchange against the host's fresh key and yields the channel. */
|
|
32
|
-
accept(hostPublicKey: string): SealedChannel | undefined;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* The host half of the handshake.
|
|
36
|
-
*
|
|
37
|
-
* The ephemeral key pair is generated per tunnel and its public half goes in the
|
|
38
|
-
* QR, which is the out-of-band channel that makes this authenticated. A relay
|
|
39
|
-
* that swaps the client's key gets a channel with itself and nothing from the
|
|
40
|
-
* host, because the host only ever derives against the key the client presents
|
|
41
|
-
* and the client only ever derives against the key it read off the screen.
|
|
42
|
-
*/
|
|
43
|
-
export declare function createHostHandshake(): HostHandshake;
|
|
44
|
-
/** Creates the client half for a single fresh peer handshake. */
|
|
45
|
-
export declare function createClientHandshake(): ClientHandshake;
|
|
46
|
-
//#endregion
|
|
47
|
-
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/nodeSealedChannel/index.ts"],"mappings":";;YAsBY;EAAe;EAAU,UAAU;;EAAqB;EAAW,SAAS;;YAC5E;EAAe;EAAU,WAAW;;EAAiB;EAAW,SAAS;;iBAEpE;;EAEf,KAAK,WAAW,aAAa;EAC7B,KAAK,oBAAoB;;iBAGV;;EAEf;;EAEA,OAAO,wBAAwB;;iBAGhB;;EAEf;;EAEA,OAAO,wBAAwB;;;;;;;;;;;wBA6GjB,uBAAuB;;wBAwBvB,yBAAyB"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
//#region src/services/sealedTransport/index.d.ts
|
|
2
|
-
export interface SealedTransport {
|
|
3
|
-
/** False on loopback and before the handshake completes, where everything passes through. */
|
|
4
|
-
active(): boolean;
|
|
5
|
-
sealText(text: string): Promise<string>;
|
|
6
|
-
/** Undefined when the message could not be opened; `lastFailure` says why. */
|
|
7
|
-
openText(text: string): Promise<string | undefined>;
|
|
8
|
-
sealBinary(bytes: Uint8Array): Promise<Uint8Array>;
|
|
9
|
-
openBinary(bytes: Uint8Array): Promise<Uint8Array | undefined>;
|
|
10
|
-
/** Drop-in for `fetch`, relaying the complete request through the sealed channel when configured. */
|
|
11
|
-
fetch(input: string, init?: RequestInit): Promise<Response>;
|
|
12
|
-
lastFailure(): string | undefined;
|
|
13
|
-
}
|
|
14
|
-
export declare function createSealedTransport(): SealedTransport & {
|
|
15
|
-
/** Completes the handshake against the host key from the QR. */
|
|
16
|
-
connect: (hostPublicKey: string) => Promise<string | undefined>;
|
|
17
|
-
/** Drops the channel, so everything falls back to pass-through. */
|
|
18
|
-
reset: () => void;
|
|
19
|
-
/** Selects the same-origin endpoint that carries sealed HTTP exchanges. */
|
|
20
|
-
relayRequestsThrough: (path: string) => void;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* The page's one sealed channel.
|
|
24
|
-
*
|
|
25
|
-
* A module singleton rather than an instance per caller, because the cockpit
|
|
26
|
-
* and every plugin are bundled into the same page and all of them must share
|
|
27
|
-
* one pair of nonce counters. Two transports over one handshake would each
|
|
28
|
-
* start counting at zero and the receiver would reject the second as a replay.
|
|
29
|
-
*
|
|
30
|
-
* Inactive until a handshake completes, and inactive forever on the loopback
|
|
31
|
-
* listener, so `sealedTransport.fetch` is a plain `fetch` there.
|
|
32
|
-
*/
|
|
33
|
-
export declare const sealedTransport: SealedTransport & {
|
|
34
|
-
/** Completes the handshake against the host key from the QR. */
|
|
35
|
-
connect: (hostPublicKey: string) => Promise<string | undefined>;
|
|
36
|
-
/** Drops the channel, so everything falls back to pass-through. */
|
|
37
|
-
reset: () => void;
|
|
38
|
-
/** Selects the same-origin endpoint that carries sealed HTTP exchanges. */
|
|
39
|
-
relayRequestsThrough: (path: string) => void;
|
|
40
|
-
};
|
|
41
|
-
//#endregion
|
|
42
|
-
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/sealedTransport/index.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,22 +0,0 @@
|
|
|
1
|
-
//#region src/services/serialQueue/index.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Runs async work strictly one at a time, in the order it was handed over.
|
|
4
|
-
*
|
|
5
|
-
* The sealed channel needs this on both directions and it is not an
|
|
6
|
-
* optimisation. Sealing increments a nonce counter and opening enforces that
|
|
7
|
-
* the counter strictly increases, so two overlapping operations are a
|
|
8
|
-
* correctness bug rather than a race worth tolerating: two concurrent seals can
|
|
9
|
-
* resolve out of order and reach the wire with descending counters, and two
|
|
10
|
-
* concurrent opens can advance the high-water mark past a message that has not
|
|
11
|
-
* been read yet, which the receiver then rejects as a replay.
|
|
12
|
-
*
|
|
13
|
-
* Deliberately not a general work pool. A pool with any concurrency above one
|
|
14
|
-
* reintroduces exactly the reordering this exists to prevent.
|
|
15
|
-
*/
|
|
16
|
-
export interface SerialQueue {
|
|
17
|
-
/** Resolves with the task's result once every task queued before it has settled. */
|
|
18
|
-
run<T>(task: () => Promise<T>): Promise<T>;
|
|
19
|
-
}
|
|
20
|
-
export declare function createSerialQueue(): SerialQueue;
|
|
21
|
-
//#endregion
|
|
22
|
-
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/serialQueue/index.ts"],"mappings":";;;;;;;;;;;;;;;iBAciB;;EAEf,IAAI,GAAG,YAAY,QAAQ,KAAK,QAAQ;;wBAG1B,qBAAqB"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
//#region src/types/bundleManifest.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* A signed description of cockpit assets for an independently trusted verifier.
|
|
4
|
-
*
|
|
5
|
-
* A manifest does not let a browser SPA defend itself against the server or TLS
|
|
6
|
-
* edge that supplied its executable code. Consumers need a separately trusted
|
|
7
|
-
* bootstrap and key before these signatures become a delivery guarantee.
|
|
8
|
-
*/
|
|
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. */
|
|
13
|
-
path: string;
|
|
14
|
-
/** Lowercase hex SHA-256 of the served bytes. */
|
|
15
|
-
sha256: string;
|
|
16
|
-
byteLength: number;
|
|
17
|
-
/** MIME type of the response, without parameters. */
|
|
18
|
-
contentType: string;
|
|
19
|
-
}
|
|
20
|
-
export interface BundleManifest {
|
|
21
|
-
version: typeof BUNDLE_MANIFEST_VERSION;
|
|
22
|
-
/** Monotonically increasing persistent signer revision. */
|
|
23
|
-
revision: number;
|
|
24
|
-
/** Unix time in milliseconds. */
|
|
25
|
-
builtAt: number;
|
|
26
|
-
assets: BundleAsset[];
|
|
27
|
-
}
|
|
28
|
-
export interface SignedBundleManifest {
|
|
29
|
-
manifest: BundleManifest;
|
|
30
|
-
/** Base64url IEEE P1363 ECDSA P-256 signature over the canonical serialization. */
|
|
31
|
-
signature: string;
|
|
32
|
-
/** Base64url SPKI of the signing key. Trust must be established out of band. */
|
|
33
|
-
publicKey: string;
|
|
34
|
-
}
|
|
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;
|
|
41
|
-
/** The recorded digest for one asset, or undefined if the manifest does not cover it. */
|
|
42
|
-
export declare function digestFor(manifest: BundleManifest, path: string): string | undefined;
|
|
43
|
-
//#endregion
|
|
44
|
-
//# sourceMappingURL=bundleManifest.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
//#region src/types/sealedChannel.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* The envelope that keeps the tunnel provider out of the payload.
|
|
4
|
-
*
|
|
5
|
-
* Cloudflare terminates TLS at its edge, so everything the cockpit carries
|
|
6
|
-
* (prompts, file previews, model output) is plaintext to them. Sealing the
|
|
7
|
-
* payload underneath their TLS leaves them a relay that can see timing and
|
|
8
|
-
* sizes but not content.
|
|
9
|
-
*
|
|
10
|
-
* The key exchange is anchored on the QR rather than negotiated in band: the
|
|
11
|
-
* host's ephemeral public key is printed on a screen the user is holding, so
|
|
12
|
-
* there is no moment at which a relay could substitute its own. That is the
|
|
13
|
-
* same job Telegram's emoji comparison does for a secret chat, except it
|
|
14
|
-
* happens automatically instead of depending on two people comparing pictures.
|
|
15
|
-
*
|
|
16
|
-
* Declared here because the server seals with `node:crypto` and the browser
|
|
17
|
-
* unseals with WebCrypto, and an envelope is only an envelope if both sides
|
|
18
|
-
* read it identically.
|
|
19
|
-
*/
|
|
20
|
-
/** Bumped when the envelope layout changes; a mismatch is refused, never guessed at. */
|
|
21
|
-
export declare const SEALED_VERSION = 1;
|
|
22
|
-
/** Fragment key in the pairing URL carrying the host's ephemeral public key. */
|
|
23
|
-
export declare const SEALED_KEY_PARAM = "k";
|
|
24
|
-
/** AES-GCM standard nonce length. Longer is non-standard, shorter is unsafe. */
|
|
25
|
-
export declare const NONCE_BYTES = 12;
|
|
26
|
-
/** Random per-channel prefix, so two channels never share a nonce space. */
|
|
27
|
-
export declare const NONCE_PREFIX_BYTES = 4;
|
|
28
|
-
/** Monotonic per-direction counter filling the rest of the nonce. */
|
|
29
|
-
export declare const NONCE_COUNTER_BYTES: number;
|
|
30
|
-
/**
|
|
31
|
-
* Rekey well before the counter could wrap.
|
|
32
|
-
*
|
|
33
|
-
* A repeated nonce under one AES-GCM key is catastrophic, not merely weak: it
|
|
34
|
-
* leaks the XOR of two plaintexts and the authentication subkey. The counter is
|
|
35
|
-
* 64 bits, so this bound is nowhere near it; the point is that the bound exists
|
|
36
|
-
* and is enforced rather than assumed.
|
|
37
|
-
*/
|
|
38
|
-
export declare const MAX_MESSAGES_PER_KEY: number;
|
|
39
|
-
/**
|
|
40
|
-
* HKDF info strings, one per direction.
|
|
41
|
-
*
|
|
42
|
-
* Separate keys per direction, not one shared key, so a message the server sent
|
|
43
|
-
* can never be replayed back at it as though the client had sent it.
|
|
44
|
-
*/
|
|
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
|
-
/**
|
|
50
|
-
* One sealed message, as it travels.
|
|
51
|
-
*
|
|
52
|
-
* Base64url rather than binary so the same envelope works on a JSON body and a
|
|
53
|
-
* text WebSocket frame without a second encoding path to get wrong.
|
|
54
|
-
*/
|
|
55
|
-
export interface SealedEnvelope {
|
|
56
|
-
v: number;
|
|
57
|
-
/** Base64url, 4-byte prefix plus 8-byte counter. */
|
|
58
|
-
n: string;
|
|
59
|
-
/** Base64url ciphertext with the GCM tag appended. */
|
|
60
|
-
c: string;
|
|
61
|
-
}
|
|
62
|
-
export declare function isSealedEnvelope(value: unknown): value is SealedEnvelope;
|
|
63
|
-
/** Header naming the client's ephemeral public key during the handshake. */
|
|
64
|
-
export declare const SEALED_CLIENT_KEY_HEADER = "x-doompi-channel-key";
|
|
65
|
-
/** Header carrying a sealed request body's envelope on a non-JSON request. */
|
|
66
|
-
export declare const SEALED_BODY_HEADER = "x-doompi-sealed";
|
|
67
|
-
export type SealedFailure = 'version' | 'malformed' | 'replay' | 'auth' | 'exhausted';
|
|
68
|
-
/**
|
|
69
|
-
* Why an unseal failed, in words a diagnostic can show.
|
|
70
|
-
*
|
|
71
|
-
* A decryption failure means a blank cockpit, so every one of these has to name
|
|
72
|
-
* its cause rather than leaving a dead page and no explanation.
|
|
73
|
-
*/
|
|
74
|
-
export declare function describeSealedFailure(failure: SealedFailure): string;
|
|
75
|
-
//#endregion
|
|
76
|
-
//# sourceMappingURL=sealedChannel.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|