@motebit/state-export-client 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +206 -0
- package/NOTICE +19 -0
- package/README.md +135 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/inner-receipts.d.ts +67 -0
- package/dist/inner-receipts.d.ts.map +1 -0
- package/dist/inner-receipts.js +161 -0
- package/dist/inner-receipts.js.map +1 -0
- package/dist/onchain-anchor.d.ts +93 -0
- package/dist/onchain-anchor.d.ts.map +1 -0
- package/dist/onchain-anchor.js +141 -0
- package/dist/onchain-anchor.js.map +1 -0
- package/dist/transparency-anchor.d.ts +86 -0
- package/dist/transparency-anchor.d.ts.map +1 -0
- package/dist/transparency-anchor.js +142 -0
- package/dist/transparency-anchor.js.map +1 -0
- package/dist/verified-fetch.d.ts +105 -0
- package/dist/verified-fetch.d.ts.map +1 -0
- package/dist/verified-fetch.js +164 -0
- package/dist/verified-fetch.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verified-fetch wrapper for motebit state-export endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Every `app.get(...)` in `services/relay/src/state-export.ts` emits an
|
|
5
|
+
* outer `ContentArtifactManifest` in the `X-Motebit-Content-Manifest`
|
|
6
|
+
* HTTP header (signed by the relay's identity). This module wraps
|
|
7
|
+
* `fetch` to verify the manifest against the response body bytes on
|
|
8
|
+
* every call, optionally pinning the producer key against a trust
|
|
9
|
+
* anchor obtained from `fetchTransparencyAnchor`.
|
|
10
|
+
*
|
|
11
|
+
* The consumer-side primitive that turns producer-side signing into
|
|
12
|
+
* an operational invariant: an operator who silently degrades their
|
|
13
|
+
* own signing breaks their own dashboard. Doctrine:
|
|
14
|
+
* `docs/doctrine/nist-alignment.md` §8, `docs/doctrine/self-attesting-system.md`.
|
|
15
|
+
*/
|
|
16
|
+
import type { ContentArtifactType } from "@motebit/protocol";
|
|
17
|
+
import type { TransparencyAnchor } from "./transparency-anchor.js";
|
|
18
|
+
/** HTTP header carrying the relay-signed content-artifact manifest. */
|
|
19
|
+
export declare const MANIFEST_HEADER = "X-Motebit-Content-Manifest";
|
|
20
|
+
/** Verification outcome accompanying every state-export response body. */
|
|
21
|
+
export type StateExportVerification = {
|
|
22
|
+
readonly valid: true;
|
|
23
|
+
readonly producerPublicKeyHex: string;
|
|
24
|
+
readonly producerDid: string;
|
|
25
|
+
readonly artifactType: ContentArtifactType;
|
|
26
|
+
readonly claimGenerator: string;
|
|
27
|
+
readonly producedAt: string;
|
|
28
|
+
readonly contentHash: string;
|
|
29
|
+
} | {
|
|
30
|
+
readonly valid: false;
|
|
31
|
+
readonly reason: StateExportVerificationFailureReason;
|
|
32
|
+
readonly detail?: string;
|
|
33
|
+
};
|
|
34
|
+
export type StateExportVerificationFailureReason = "manifest_header_missing" | "malformed_manifest_header" | "content_hash_mismatch" | "signature_invalid" | "malformed_public_key" | "malformed_signature" | "unsupported_suite" | "producer_key_mismatch";
|
|
35
|
+
export interface VerifiedStateExportResponse<T> {
|
|
36
|
+
/**
|
|
37
|
+
* Parsed JSON body — present only when verification succeeded.
|
|
38
|
+
* `null` on verification failure: callers MUST check
|
|
39
|
+
* `verification.valid` before consuming the body. Never render
|
|
40
|
+
* unverified state.
|
|
41
|
+
*/
|
|
42
|
+
readonly body: T | null;
|
|
43
|
+
/** Raw bytes the verifier hashed. Exposed so callers that need byte-level access (audit, hashing, re-serialization) don't double-fetch. */
|
|
44
|
+
readonly bodyBytes: Uint8Array;
|
|
45
|
+
/** Structured verification result. Callers branch on `valid` for UI status and `reason` for audit logging. */
|
|
46
|
+
readonly verification: StateExportVerification;
|
|
47
|
+
}
|
|
48
|
+
export interface VerifiedFetchOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Trust anchor obtained from `fetchTransparencyAnchor`. When set,
|
|
51
|
+
* the verifier rejects with `producer_key_mismatch` if the manifest's
|
|
52
|
+
* declared producer key does not match the pinned hex value.
|
|
53
|
+
*
|
|
54
|
+
* Omitting the anchor still verifies the manifest's self-consistency
|
|
55
|
+
* (content_hash + signature against the declared key) — but a verifier
|
|
56
|
+
* with no pin trusts the declared key. Production callers SHOULD
|
|
57
|
+
* always pass an anchor.
|
|
58
|
+
*/
|
|
59
|
+
readonly anchor?: TransparencyAnchor;
|
|
60
|
+
/**
|
|
61
|
+
* Inject the fetch implementation. Defaults to global `fetch`. Tests
|
|
62
|
+
* pass a mock; integrators with auth-proxy or tunneling transports
|
|
63
|
+
* pass a wrapper.
|
|
64
|
+
*/
|
|
65
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
66
|
+
/** Forwarded to the underlying fetch call. */
|
|
67
|
+
readonly init?: RequestInit;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Fetch a state-export endpoint and verify its content-artifact
|
|
71
|
+
* manifest against the response body bytes. Returns the parsed body,
|
|
72
|
+
* the raw bytes, and a typed verification result.
|
|
73
|
+
*
|
|
74
|
+
* The verifier reads `X-Motebit-Content-Manifest` from the response,
|
|
75
|
+
* decodes the base64url-encoded canonical-JSON manifest, recomputes
|
|
76
|
+
* SHA-256 over the body bytes, and verifies the signature against the
|
|
77
|
+
* manifest's declared producer key. With `anchor` set, also enforces
|
|
78
|
+
* a byte-equal match between the declared key and the pinned key.
|
|
79
|
+
*
|
|
80
|
+
* Non-2xx HTTP responses throw — the verifier does not attempt to
|
|
81
|
+
* verify error bodies. A 5xx response from the relay is a service
|
|
82
|
+
* outage, not a signing failure; let the caller's catch handle it.
|
|
83
|
+
*/
|
|
84
|
+
export declare function verifiedStateExportFetch<T>(url: string, options?: VerifiedFetchOptions): Promise<VerifiedStateExportResponse<T>>;
|
|
85
|
+
/**
|
|
86
|
+
* Pure-function verifier: decode the header value, parse the manifest,
|
|
87
|
+
* verify against the body bytes, optionally enforce the producer-key
|
|
88
|
+
* pin. Exposed so tests + audit tooling can replay a captured response
|
|
89
|
+
* without a fresh HTTP round-trip.
|
|
90
|
+
*/
|
|
91
|
+
export declare function verifyManifestAgainstBytes(headerValue: string | null, bodyBytes: Uint8Array, anchor?: TransparencyAnchor): Promise<StateExportVerification>;
|
|
92
|
+
/**
|
|
93
|
+
* Thrown when the underlying HTTP fetch returns non-2xx. The verifier
|
|
94
|
+
* does not attempt to verify error bodies — the relay's error
|
|
95
|
+
* envelope is unsigned by design (signing 5xx pages would be
|
|
96
|
+
* misleading provenance for a service outage).
|
|
97
|
+
*/
|
|
98
|
+
export declare class StateExportFetchError extends Error {
|
|
99
|
+
readonly status: number;
|
|
100
|
+
readonly statusText: string;
|
|
101
|
+
readonly body: string;
|
|
102
|
+
readonly url: string;
|
|
103
|
+
constructor(status: number, statusText: string, body: string, url: string);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=verified-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verified-fetch.d.ts","sourceRoot":"","sources":["../src/verified-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,uEAAuE;AACvE,eAAO,MAAM,eAAe,+BAA+B,CAAC;AAE5D,0EAA0E;AAC1E,MAAM,MAAM,uBAAuB,GAC/B;IACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,oCAAoC,CAAC;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEN,MAAM,MAAM,oCAAoC,GAC5C,yBAAyB,GACzB,2BAA2B,GAC3B,uBAAuB,GACvB,mBAAmB,GACnB,sBAAsB,GACtB,qBAAqB,GACrB,mBAAmB,GACnB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,2BAA2B,CAAC,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACxB,2IAA2I;IAC3I,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,8GAA8G;IAC9G,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;OASG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;CAC7B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,CA6CzC;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,UAAU,EACrB,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,uBAAuB,CAAC,CAoDlC;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;aAE5B,MAAM,EAAE,MAAM;aACd,UAAU,EAAE,MAAM;aAClB,IAAI,EAAE,MAAM;aACZ,GAAG,EAAE,MAAM;gBAHX,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM;CAK9B"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verified-fetch wrapper for motebit state-export endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Every `app.get(...)` in `services/relay/src/state-export.ts` emits an
|
|
5
|
+
* outer `ContentArtifactManifest` in the `X-Motebit-Content-Manifest`
|
|
6
|
+
* HTTP header (signed by the relay's identity). This module wraps
|
|
7
|
+
* `fetch` to verify the manifest against the response body bytes on
|
|
8
|
+
* every call, optionally pinning the producer key against a trust
|
|
9
|
+
* anchor obtained from `fetchTransparencyAnchor`.
|
|
10
|
+
*
|
|
11
|
+
* The consumer-side primitive that turns producer-side signing into
|
|
12
|
+
* an operational invariant: an operator who silently degrades their
|
|
13
|
+
* own signing breaks their own dashboard. Doctrine:
|
|
14
|
+
* `docs/doctrine/nist-alignment.md` §8, `docs/doctrine/self-attesting-system.md`.
|
|
15
|
+
*/
|
|
16
|
+
import { verifyContentArtifact } from "@motebit/crypto";
|
|
17
|
+
/** HTTP header carrying the relay-signed content-artifact manifest. */
|
|
18
|
+
export const MANIFEST_HEADER = "X-Motebit-Content-Manifest";
|
|
19
|
+
/**
|
|
20
|
+
* Fetch a state-export endpoint and verify its content-artifact
|
|
21
|
+
* manifest against the response body bytes. Returns the parsed body,
|
|
22
|
+
* the raw bytes, and a typed verification result.
|
|
23
|
+
*
|
|
24
|
+
* The verifier reads `X-Motebit-Content-Manifest` from the response,
|
|
25
|
+
* decodes the base64url-encoded canonical-JSON manifest, recomputes
|
|
26
|
+
* SHA-256 over the body bytes, and verifies the signature against the
|
|
27
|
+
* manifest's declared producer key. With `anchor` set, also enforces
|
|
28
|
+
* a byte-equal match between the declared key and the pinned key.
|
|
29
|
+
*
|
|
30
|
+
* Non-2xx HTTP responses throw — the verifier does not attempt to
|
|
31
|
+
* verify error bodies. A 5xx response from the relay is a service
|
|
32
|
+
* outage, not a signing failure; let the caller's catch handle it.
|
|
33
|
+
*/
|
|
34
|
+
export async function verifiedStateExportFetch(url, options = {}) {
|
|
35
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
36
|
+
const res = await fetchImpl(url, options.init);
|
|
37
|
+
if (!res.ok) {
|
|
38
|
+
const body = await res.text().catch(() => "");
|
|
39
|
+
throw new StateExportFetchError(res.status, res.statusText, body, url);
|
|
40
|
+
}
|
|
41
|
+
// Read body bytes once — JSON.parse runs over a UTF-8 decode of the
|
|
42
|
+
// same bytes the verifier hashes. ArrayBuffer keeps both views safe.
|
|
43
|
+
const arrayBuffer = await res.arrayBuffer();
|
|
44
|
+
const bodyBytes = new Uint8Array(arrayBuffer);
|
|
45
|
+
// Verify BEFORE JSON-parse: a tampered body can corrupt JSON
|
|
46
|
+
// structure, which would mask the typed crypto reason
|
|
47
|
+
// (`content_hash_mismatch`) behind a generic parse error. Running
|
|
48
|
+
// verification first preserves the structured failure reason for
|
|
49
|
+
// audit logging even when the bytes are wholly garbage.
|
|
50
|
+
const headerValue = res.headers.get(MANIFEST_HEADER);
|
|
51
|
+
const verification = await verifyManifestAgainstBytes(headerValue, bodyBytes, options.anchor);
|
|
52
|
+
// JSON parsing only meaningful when the bytes are what the producer
|
|
53
|
+
// signed. On verification failure, `body` is null — callers MUST
|
|
54
|
+
// check `verification.valid` before rendering; the discriminated
|
|
55
|
+
// union below makes that compile-time enforceable.
|
|
56
|
+
let body = null;
|
|
57
|
+
if (verification.valid) {
|
|
58
|
+
const bodyText = new TextDecoder().decode(bodyBytes);
|
|
59
|
+
try {
|
|
60
|
+
body = JSON.parse(bodyText);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
// Verified bytes that don't parse as JSON are a producer bug —
|
|
64
|
+
// the manifest swore these bytes are the export, but they aren't
|
|
65
|
+
// valid JSON. Surface as a thrown error rather than mixing
|
|
66
|
+
// crypto-valid + parse-failed into the same return shape.
|
|
67
|
+
throw new StateExportFetchError(200, "verified body is not valid JSON", err instanceof Error ? err.message : String(err), url);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { body, bodyBytes, verification };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Pure-function verifier: decode the header value, parse the manifest,
|
|
74
|
+
* verify against the body bytes, optionally enforce the producer-key
|
|
75
|
+
* pin. Exposed so tests + audit tooling can replay a captured response
|
|
76
|
+
* without a fresh HTTP round-trip.
|
|
77
|
+
*/
|
|
78
|
+
export async function verifyManifestAgainstBytes(headerValue, bodyBytes, anchor) {
|
|
79
|
+
if (headerValue == null || headerValue === "") {
|
|
80
|
+
return { valid: false, reason: "manifest_header_missing" };
|
|
81
|
+
}
|
|
82
|
+
let manifest;
|
|
83
|
+
try {
|
|
84
|
+
const manifestBytes = base64UrlDecode(headerValue);
|
|
85
|
+
const manifestJson = new TextDecoder().decode(manifestBytes);
|
|
86
|
+
manifest = JSON.parse(manifestJson);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
return {
|
|
90
|
+
valid: false,
|
|
91
|
+
reason: "malformed_manifest_header",
|
|
92
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Producer-key pin runs BEFORE the crypto check — a key-mismatch
|
|
96
|
+
// rejection is cheaper and more informative than a generic
|
|
97
|
+
// signature_invalid when the verifier knows the expected signer.
|
|
98
|
+
if (anchor !== undefined) {
|
|
99
|
+
const declared = manifest.producer_public_key.toLowerCase();
|
|
100
|
+
if (declared !== anchor.relayPublicKeyHex) {
|
|
101
|
+
return {
|
|
102
|
+
valid: false,
|
|
103
|
+
reason: "producer_key_mismatch",
|
|
104
|
+
detail: `expected ${anchor.relayPublicKeyHex}, got ${declared}`,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const result = await verifyContentArtifact(manifest, bodyBytes);
|
|
109
|
+
if (!result.valid) {
|
|
110
|
+
// Map primitive reasons into the consumer-facing failure union.
|
|
111
|
+
// Both unions share most variants verbatim; the consumer-facing
|
|
112
|
+
// one adds the header- and key-pin-specific reasons above.
|
|
113
|
+
return {
|
|
114
|
+
valid: false,
|
|
115
|
+
reason: result.reason,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
valid: true,
|
|
120
|
+
producerPublicKeyHex: manifest.producer_public_key.toLowerCase(),
|
|
121
|
+
producerDid: manifest.producer,
|
|
122
|
+
artifactType: manifest.artifact_type,
|
|
123
|
+
claimGenerator: manifest.claim_generator,
|
|
124
|
+
producedAt: manifest.produced_at,
|
|
125
|
+
contentHash: manifest.content_hash,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Thrown when the underlying HTTP fetch returns non-2xx. The verifier
|
|
130
|
+
* does not attempt to verify error bodies — the relay's error
|
|
131
|
+
* envelope is unsigned by design (signing 5xx pages would be
|
|
132
|
+
* misleading provenance for a service outage).
|
|
133
|
+
*/
|
|
134
|
+
export class StateExportFetchError extends Error {
|
|
135
|
+
status;
|
|
136
|
+
statusText;
|
|
137
|
+
body;
|
|
138
|
+
url;
|
|
139
|
+
constructor(status, statusText, body, url) {
|
|
140
|
+
super(`state-export fetch ${url} → ${status} ${statusText}`);
|
|
141
|
+
this.status = status;
|
|
142
|
+
this.statusText = statusText;
|
|
143
|
+
this.body = body;
|
|
144
|
+
this.url = url;
|
|
145
|
+
this.name = "StateExportFetchError";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Inline base64url decoder — avoids pulling Buffer (Node-only) or a
|
|
150
|
+
* new dependency. Browsers + Node 20+ have `atob`, but `atob` rejects
|
|
151
|
+
* base64url; we normalize to standard base64 first.
|
|
152
|
+
*/
|
|
153
|
+
function base64UrlDecode(input) {
|
|
154
|
+
const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
155
|
+
// atob requires padded base64. Compute padding from length mod 4.
|
|
156
|
+
const padded = normalized + "=".repeat((4 - (normalized.length % 4)) % 4);
|
|
157
|
+
const binary = atob(padded);
|
|
158
|
+
const bytes = new Uint8Array(binary.length);
|
|
159
|
+
for (let i = 0; i < binary.length; i++) {
|
|
160
|
+
bytes[i] = binary.charCodeAt(i);
|
|
161
|
+
}
|
|
162
|
+
return bytes;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=verified-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verified-fetch.js","sourceRoot":"","sources":["../src/verified-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAKxD,uEAAuE;AACvE,MAAM,CAAC,MAAM,eAAe,GAAG,4BAA4B,CAAC;AAiE5D;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,GAAW,EACX,UAAgC,EAAE;IAElC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IACpD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,qBAAqB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACzE,CAAC;IAED,oEAAoE;IACpE,qEAAqE;IACrE,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAE9C,6DAA6D;IAC7D,sDAAsD;IACtD,kEAAkE;IAClE,iEAAiE;IACjE,wDAAwD;IACxD,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,MAAM,0BAA0B,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAE9F,oEAAoE;IACpE,iEAAiE;IACjE,iEAAiE;IACjE,mDAAmD;IACnD,IAAI,IAAI,GAAa,IAAI,CAAC;IAC1B,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAM,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,+DAA+D;YAC/D,iEAAiE;YACjE,2DAA2D;YAC3D,0DAA0D;YAC1D,MAAM,IAAI,qBAAqB,CAC7B,GAAG,EACH,iCAAiC,EACjC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAChD,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,WAA0B,EAC1B,SAAqB,EACrB,MAA2B;IAE3B,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,KAAK,EAAE,EAAE,CAAC;QAC9C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IAC7D,CAAC;IAED,IAAI,QAAiC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC7D,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAA4B,CAAC;IACjE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,2BAA2B;YACnC,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACzD,CAAC;IACJ,CAAC;IAED,iEAAiE;IACjE,2DAA2D;IAC3D,iEAAiE;IACjE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,CAAC;QAC5D,IAAI,QAAQ,KAAK,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAC1C,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,uBAAuB;gBAC/B,MAAM,EAAE,YAAY,MAAM,CAAC,iBAAiB,SAAS,QAAQ,EAAE;aAChE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,gEAAgE;QAChE,gEAAgE;QAChE,2DAA2D;QAC3D,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,MAAM,CAAC,MAA8C;SAC9D,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,oBAAoB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE;QAChE,WAAW,EAAE,QAAQ,CAAC,QAAQ;QAC9B,YAAY,EAAE,QAAQ,CAAC,aAAa;QACpC,cAAc,EAAE,QAAQ,CAAC,eAAe;QACxC,UAAU,EAAE,QAAQ,CAAC,WAAW;QAChC,WAAW,EAAE,QAAQ,CAAC,YAAY;KACnC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAE5B;IACA;IACA;IACA;IAJlB,YACkB,MAAc,EACd,UAAkB,EAClB,IAAY,EACZ,GAAW;QAE3B,KAAK,CAAC,sBAAsB,GAAG,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC,CAAC;QAL7C,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAQ;QAClB,SAAI,GAAJ,IAAI,CAAQ;QACZ,QAAG,GAAH,GAAG,CAAQ;QAG3B,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/D,kEAAkE;IAClE,MAAM,MAAM,GAAG,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@motebit/state-export-client",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Browser-safe client for verified motebit state-export reads. Wraps fetch with X-Motebit-Content-Manifest verification + Trust-On-First-Use bootstrap from /.well-known/motebit-transparency.json. Apache-2.0; consumes @motebit/crypto + @motebit/protocol only.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/motebit/motebit",
|
|
8
|
+
"directory": "packages/state-export-client"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist/**/*.js",
|
|
21
|
+
"dist/**/*.js.map",
|
|
22
|
+
"dist/**/*.d.ts",
|
|
23
|
+
"dist/**/*.d.ts.map",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"NOTICE",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"license": "Apache-2.0",
|
|
30
|
+
"keywords": [
|
|
31
|
+
"motebit",
|
|
32
|
+
"verification",
|
|
33
|
+
"self-attesting",
|
|
34
|
+
"content-provenance",
|
|
35
|
+
"operator-transparency"
|
|
36
|
+
],
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@motebit/crypto": "1.3.0",
|
|
39
|
+
"@motebit/protocol": "1.3.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^22.0.0",
|
|
43
|
+
"typescript": "^5.6.0",
|
|
44
|
+
"vitest": "^2.1.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc -b",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"test:coverage": "vitest run --coverage",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"lint": "eslint --parser-options=project:tsconfig.eslint.json src/",
|
|
52
|
+
"clean": "rm -rf dist .turbo *.tsbuildinfo"
|
|
53
|
+
}
|
|
54
|
+
}
|