@antseed/antseed-verifier 0.1.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 +674 -0
- package/README.md +86 -0
- package/dist/adapters/aci.d.ts +4 -0
- package/dist/adapters/aci.d.ts.map +1 -0
- package/dist/adapters/aci.js +42 -0
- package/dist/adapters/aci.js.map +1 -0
- package/dist/adapters/chutes.d.ts +4 -0
- package/dist/adapters/chutes.d.ts.map +1 -0
- package/dist/adapters/chutes.js +72 -0
- package/dist/adapters/chutes.js.map +1 -0
- package/dist/adapters/index.d.ts +26 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +19 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/antseed-node-types.d.ts +55 -0
- package/dist/antseed-node-types.d.ts.map +1 -0
- package/dist/antseed-node-types.js +8 -0
- package/dist/antseed-node-types.js.map +1 -0
- package/dist/capability.d.ts +50 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +15 -0
- package/dist/capability.js.map +1 -0
- package/dist/caps/gpu-nvidia.d.ts +66 -0
- package/dist/caps/gpu-nvidia.d.ts.map +1 -0
- package/dist/caps/gpu-nvidia.js +142 -0
- package/dist/caps/gpu-nvidia.js.map +1 -0
- package/dist/caps/index.d.ts +7 -0
- package/dist/caps/index.d.ts.map +1 -0
- package/dist/caps/index.js +21 -0
- package/dist/caps/index.js.map +1 -0
- package/dist/caps/measured-image.d.ts +14 -0
- package/dist/caps/measured-image.d.ts.map +1 -0
- package/dist/caps/measured-image.js +46 -0
- package/dist/caps/measured-image.js.map +1 -0
- package/dist/caps/provider-claims.d.ts +52 -0
- package/dist/caps/provider-claims.d.ts.map +1 -0
- package/dist/caps/provider-claims.js +195 -0
- package/dist/caps/provider-claims.js.map +1 -0
- package/dist/caps/seller-bound.d.ts +9 -0
- package/dist/caps/seller-bound.d.ts.map +1 -0
- package/dist/caps/seller-bound.js +104 -0
- package/dist/caps/seller-bound.js.map +1 -0
- package/dist/caps/tee-tdx.d.ts +107 -0
- package/dist/caps/tee-tdx.d.ts.map +1 -0
- package/dist/caps/tee-tdx.js +210 -0
- package/dist/caps/tee-tdx.js.map +1 -0
- package/dist/collect/configfs.d.ts +6 -0
- package/dist/collect/configfs.d.ts.map +1 -0
- package/dist/collect/configfs.js +38 -0
- package/dist/collect/configfs.js.map +1 -0
- package/dist/collect/dstack.d.ts +8 -0
- package/dist/collect/dstack.d.ts.map +1 -0
- package/dist/collect/dstack.js +79 -0
- package/dist/collect/dstack.js.map +1 -0
- package/dist/collect/http.d.ts +25 -0
- package/dist/collect/http.d.ts.map +1 -0
- package/dist/collect/http.js +83 -0
- package/dist/collect/http.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/nras.d.ts +81 -0
- package/dist/nras.d.ts.map +1 -0
- package/dist/nras.js +190 -0
- package/dist/nras.js.map +1 -0
- package/dist/prover.d.ts +5 -0
- package/dist/prover.d.ts.map +1 -0
- package/dist/prover.js +204 -0
- package/dist/prover.js.map +1 -0
- package/dist/report-data.d.ts +47 -0
- package/dist/report-data.d.ts.map +1 -0
- package/dist/report-data.js +111 -0
- package/dist/report-data.js.map +1 -0
- package/dist/shared.d.ts +89 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +158 -0
- package/dist/shared.js.map +1 -0
- package/dist/verifier.d.ts +21 -0
- package/dist/verifier.d.ts.map +1 -0
- package/dist/verifier.js +149 -0
- package/dist/verifier.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { claimId } from '../shared.js';
|
|
2
|
+
import { collectJsonFieldViaHttp } from '../collect/http.js';
|
|
3
|
+
import { decodeTeeTdxEvidence, PROVIDER_TEE_CAP_ID } from './tee-tdx.js';
|
|
4
|
+
import { getReportDataScheme } from '../report-data.js';
|
|
5
|
+
import { NRAS_GPU_ATTEST_URL_DEFAULT, NRAS_JWKS_URL_DEFAULT, buildNrasRequest, defaultNrasSubmit, verifyEar, } from '../nras.js';
|
|
6
|
+
/**
|
|
7
|
+
* Capability 'seller-provider-gpu-cc': proves the inference provider's GPUs run NVIDIA
|
|
8
|
+
* Confidential Computing, via NVIDIA's Remote Attestation Service (NRAS). The buyer submits
|
|
9
|
+
* the provider's per-GPU CC evidence and the buyer's nonce to NRAS, then verifies the returned
|
|
10
|
+
* EAR (signed JWT): the signature is valid against NVIDIA's JWKS, the overall result is success,
|
|
11
|
+
* the CC mode is on, and the nonce binds this round.
|
|
12
|
+
*
|
|
13
|
+
* Informational, not required: a CPU-only seller (no GPUs) must still verify, so this cap is
|
|
14
|
+
* never in the buyer's required set. The seller offers it only when it configures a provider
|
|
15
|
+
* evidence route and a GPU evidence field; otherwise it omits the cap. The buyer-side check goes
|
|
16
|
+
* through an injectable GpuVerifyFn (see below) so an offline verifier can replace it.
|
|
17
|
+
*/
|
|
18
|
+
export const GPU_CAP_ID = 'seller-provider-gpu-cc';
|
|
19
|
+
/** Mode switch: 'nras' (default, verify via NRAS) or 'local' (offline; not implemented). */
|
|
20
|
+
const GPU_MODE_ENV = 'ANTSEED_VERIFIER_GPU_MODE';
|
|
21
|
+
/** Env overrides for NVIDIA's endpoints (defaults point at NRAS; useful for tests and staging). */
|
|
22
|
+
const NRAS_URL_ENV = 'ANTSEED_VERIFIER_NRAS_URL';
|
|
23
|
+
const NRAS_JWKS_ENV = 'ANTSEED_VERIFIER_NRAS_JWKS_URL';
|
|
24
|
+
/** Decode the provider's GPU evidence bytes (JSON: { arch, evidence_list }). */
|
|
25
|
+
function decodeGpuEvidence(bytes) {
|
|
26
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build a NRAS-backed GpuVerifyFn. It submits the provider evidence and nonce to NRAS and
|
|
30
|
+
* verifies the EAR. Network or service errors are marked transient (retryable). Anything else
|
|
31
|
+
* (malformed evidence, bad signature, failed claim, nonce mismatch) fails closed as a real
|
|
32
|
+
* verdict. jose is imported lazily (only here) so the seller half and CPU-only buyers never load it.
|
|
33
|
+
*/
|
|
34
|
+
export function makeNrasGpuVerify(opts = {}) {
|
|
35
|
+
return async (evidenceBytes, nonce) => {
|
|
36
|
+
const nrasUrl = opts.nrasUrl ?? process.env[NRAS_URL_ENV]?.trim() ?? NRAS_GPU_ATTEST_URL_DEFAULT;
|
|
37
|
+
let request;
|
|
38
|
+
try {
|
|
39
|
+
request = buildNrasRequest(decodeGpuEvidence(evidenceBytes), nonce);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
return { ok: false, detail: `invalid GPU evidence: ${msg(err)}` };
|
|
43
|
+
}
|
|
44
|
+
let response;
|
|
45
|
+
try {
|
|
46
|
+
response = await (opts.submit ?? defaultNrasSubmit)(nrasUrl, request);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
// NRAS unreachable or 5xx — transient, not an attestation verdict.
|
|
50
|
+
return { ok: false, transient: true, detail: `NRAS request failed: ${msg(err)}` };
|
|
51
|
+
}
|
|
52
|
+
let getKey = opts.getKey;
|
|
53
|
+
if (!getKey) {
|
|
54
|
+
const jwksUrl = opts.jwksUrl ?? process.env[NRAS_JWKS_ENV]?.trim() ?? NRAS_JWKS_URL_DEFAULT;
|
|
55
|
+
const jose = await import('jose');
|
|
56
|
+
getKey = jose.createRemoteJWKSet(new URL(jwksUrl));
|
|
57
|
+
}
|
|
58
|
+
const r = await verifyEar(response, nonce, getKey);
|
|
59
|
+
return { ok: r.ok, detail: r.reason };
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** Default NRAS verifier (production). */
|
|
63
|
+
export const nrasGpuVerify = makeNrasGpuVerify();
|
|
64
|
+
/**
|
|
65
|
+
* Offline GPU verifier — reserved for the nvtrust-style local path (report + device cert chain
|
|
66
|
+
* + RIM, no external service). Not implemented: it returns a clear, non-transient error so an
|
|
67
|
+
* operator who sets ANTSEED_VERIFIER_GPU_MODE=local gets an explicit "not implemented", not silence.
|
|
68
|
+
*/
|
|
69
|
+
export const localGpuVerify = async () => ({
|
|
70
|
+
ok: false,
|
|
71
|
+
detail: 'offline GPU verification not yet implemented (ANTSEED_VERIFIER_GPU_MODE=local)',
|
|
72
|
+
});
|
|
73
|
+
/** Dispatch on ANTSEED_VERIFIER_GPU_MODE: 'nras' or 'local'. An unknown mode fails closed. */
|
|
74
|
+
export const defaultGpuVerify = (evidence, nonce) => {
|
|
75
|
+
const mode = (process.env[GPU_MODE_ENV]?.trim() || 'nras').toLowerCase();
|
|
76
|
+
if (mode === 'local')
|
|
77
|
+
return localGpuVerify(evidence, nonce);
|
|
78
|
+
if (mode === 'nras')
|
|
79
|
+
return nrasGpuVerify(evidence, nonce);
|
|
80
|
+
return Promise.resolve({ ok: false, detail: `unknown ${GPU_MODE_ENV} "${mode}" (expected "nras" or "local")` });
|
|
81
|
+
};
|
|
82
|
+
/** Config-key convention for this cap's collector settings (mirrors tee-tdx's tdxConfigKey). */
|
|
83
|
+
export function gpuConfigKey(key) {
|
|
84
|
+
return `${GPU_CAP_ID}.${key}`;
|
|
85
|
+
}
|
|
86
|
+
function msg(err) {
|
|
87
|
+
return err instanceof Error ? err.message : String(err);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The nonce to submit to NRAS this round. A provider that binds its TDX quote with a report_data
|
|
91
|
+
* scheme (e.g. Chutes' nonce-pubkey-sha256-v1) also binds its GPU evidence to that scheme's derived
|
|
92
|
+
* nonce, not the raw round nonce — so the code asks the declared scheme for it. With no scheme, it
|
|
93
|
+
* uses the raw nonce. It reads the provider quote from the bundle; any decode issue falls back to
|
|
94
|
+
* the raw nonce (fail-open is safe here — verifyEar still enforces the eat_nonce match).
|
|
95
|
+
*/
|
|
96
|
+
function nrasNonceFor(nonce, bundle) {
|
|
97
|
+
const providerEvidence = bundle?.[PROVIDER_TEE_CAP_ID];
|
|
98
|
+
if (!providerEvidence)
|
|
99
|
+
return nonce;
|
|
100
|
+
try {
|
|
101
|
+
const { binding } = decodeTeeTdxEvidence(providerEvidence);
|
|
102
|
+
if (!binding)
|
|
103
|
+
return nonce;
|
|
104
|
+
const scheme = getReportDataScheme(binding.scheme);
|
|
105
|
+
return scheme ? scheme.gpuNonce(nonce, binding.ingredients) : nonce;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return nonce;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Mint the GPU-CC capability. `gpuVerify` is the injected buyer-side check (default: NRAS);
|
|
113
|
+
* tests pass a stub. collect fetches the provider's GPU evidence from the same provider
|
|
114
|
+
* evidence route as the TDX quote (config-supplied url and field). It throws when either is
|
|
115
|
+
* absent, so the cap is omitted.
|
|
116
|
+
*/
|
|
117
|
+
export function makeGpuNvidiaCap(gpuVerify = defaultGpuVerify) {
|
|
118
|
+
return {
|
|
119
|
+
id: GPU_CAP_ID,
|
|
120
|
+
async verify(input) {
|
|
121
|
+
const claim = claimId(GPU_CAP_ID);
|
|
122
|
+
// Fail-closed: no evidence means the GPUs cannot be attested.
|
|
123
|
+
if (!input.evidence)
|
|
124
|
+
return { claim, ok: false, detail: 'seller returned no GPU CC evidence' };
|
|
125
|
+
const r = await gpuVerify(input.evidence, nrasNonceFor(input.nonce, input.evidenceBundle));
|
|
126
|
+
// ClaimResult has no transient field; show retryability in the human-readable detail.
|
|
127
|
+
const detail = r.transient ? `[transient] ${r.detail}` : r.detail;
|
|
128
|
+
return { claim, ok: r.ok, detail };
|
|
129
|
+
},
|
|
130
|
+
async collect(input) {
|
|
131
|
+
const url = input.config[gpuConfigKey('url')];
|
|
132
|
+
const field = input.config[gpuConfigKey('field')];
|
|
133
|
+
if (!url || !field)
|
|
134
|
+
throw new Error('seller-provider-gpu-cc requires a provider url + gpu field; not offered');
|
|
135
|
+
// The GPU evidence is a structured JSON object ({ arch, evidence_list }), not a lone
|
|
136
|
+
// base64 blob — collect it as JSON bytes so its shape survives to the NRAS submit.
|
|
137
|
+
return collectJsonFieldViaHttp(url, input.nonce, field);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export const gpuNvidiaCapability = makeGpuNvidiaCap();
|
|
142
|
+
//# sourceMappingURL=gpu-nvidia.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gpu-nvidia.js","sourceRoot":"","sources":["../../src/caps/gpu-nvidia.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { nodeTeeCapability, providerTeeCapability } from './tee-tdx.js';
|
|
2
|
+
import { sellerBoundCapability } from './seller-bound.js';
|
|
3
|
+
import { measuredImageCapability } from './measured-image.js';
|
|
4
|
+
import { gpuNvidiaCapability } from './gpu-nvidia.js';
|
|
5
|
+
import { providerClaimsCapability } from './provider-claims.js';
|
|
6
|
+
export { nodeTeeCapability, providerTeeCapability, sellerBoundCapability, measuredImageCapability, gpuNvidiaCapability, providerClaimsCapability };
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/caps/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAgB/D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { registerCapability } from '../capability.js';
|
|
2
|
+
import { nodeTeeCapability, providerTeeCapability } from './tee-tdx.js';
|
|
3
|
+
import { sellerBoundCapability } from './seller-bound.js';
|
|
4
|
+
import { measuredImageCapability } from './measured-image.js';
|
|
5
|
+
import { gpuNvidiaCapability } from './gpu-nvidia.js';
|
|
6
|
+
import { providerClaimsCapability } from './provider-claims.js';
|
|
7
|
+
/**
|
|
8
|
+
* Registration order defines both the advertised menu order and the seller's collect order.
|
|
9
|
+
* Invariant: seller-bound signs over the whole bundle, so every evidence-producing cap (the
|
|
10
|
+
* TDX caps, gpu-cc and provider-claims) must be registered before seller-bound. They are then
|
|
11
|
+
* already collected when it builds the digest it signs. measured-image derives from the
|
|
12
|
+
* provider quote (no own evidence), so its position does not matter.
|
|
13
|
+
*/
|
|
14
|
+
registerCapability(nodeTeeCapability);
|
|
15
|
+
registerCapability(providerTeeCapability);
|
|
16
|
+
registerCapability(gpuNvidiaCapability);
|
|
17
|
+
registerCapability(providerClaimsCapability);
|
|
18
|
+
registerCapability(sellerBoundCapability);
|
|
19
|
+
registerCapability(measuredImageCapability);
|
|
20
|
+
export { nodeTeeCapability, providerTeeCapability, sellerBoundCapability, measuredImageCapability, gpuNvidiaCapability, providerClaimsCapability };
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/caps/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAE/D;;;;;;GAMG;AACH,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;AACrC,kBAAkB,CAAC,qBAAqB,CAAC,CAAA;AACzC,kBAAkB,CAAC,mBAAmB,CAAC,CAAA;AACvC,kBAAkB,CAAC,wBAAwB,CAAC,CAAA;AAC5C,kBAAkB,CAAC,qBAAqB,CAAC,CAAA;AACzC,kBAAkB,CAAC,uBAAuB,CAAC,CAAA;AAE3C,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Capability } from '../capability.js';
|
|
2
|
+
/** One approved image fingerprint. Hex strings (no 0x); rtmrN optional (checked when present). */
|
|
3
|
+
export interface ApprovedMeasurement {
|
|
4
|
+
mrtd: string;
|
|
5
|
+
rtmr0?: string;
|
|
6
|
+
rtmr1?: string;
|
|
7
|
+
rtmr2?: string;
|
|
8
|
+
rtmr3?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MeasuredImagePolicy {
|
|
11
|
+
approvedMeasurements?: ApprovedMeasurement[];
|
|
12
|
+
}
|
|
13
|
+
export declare const measuredImageCapability: Capability;
|
|
14
|
+
//# sourceMappingURL=measured-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measured-image.d.ts","sourceRoot":"","sources":["../../src/caps/measured-image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAyB,MAAM,kBAAkB,CAAA;AAezE,kGAAkG;AAClG,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAA;CAC7C;AAoBD,eAAO,MAAM,uBAAuB,EAAE,UAoBrC,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { claimId } from '../shared.js';
|
|
2
|
+
/**
|
|
3
|
+
* Capability 'seller-provider-measured-image': proves the inference provider booted a
|
|
4
|
+
* specific, approved software image. It compares the provider TDX quote's authenticated
|
|
5
|
+
* measurements (MRTD + RTMR0-3) to a buyer-supplied allow-list. The approved measurements
|
|
6
|
+
* are pure data passed in via policy — never fetched, never hardcoded — so the SDK stays
|
|
7
|
+
* provider-agnostic. With no policy it returns ok:false; it never passes by default. It
|
|
8
|
+
* derives from the provider quote, so it has no own evidence.
|
|
9
|
+
*/
|
|
10
|
+
const CAP_ID = 'seller-provider-measured-image';
|
|
11
|
+
function hex(b) {
|
|
12
|
+
return Buffer.from(b).toString('hex');
|
|
13
|
+
}
|
|
14
|
+
/** A measurement matches only if every field it specifies equals the quote's value. */
|
|
15
|
+
function matches(m, td) {
|
|
16
|
+
if (!td)
|
|
17
|
+
return false;
|
|
18
|
+
const eq = (expected, actual) => expected === undefined || expected.toLowerCase() === hex(actual);
|
|
19
|
+
return (m.mrtd.toLowerCase() === hex(td.mrTd) &&
|
|
20
|
+
eq(m.rtmr0, td.rtMr0) &&
|
|
21
|
+
eq(m.rtmr1, td.rtMr1) &&
|
|
22
|
+
eq(m.rtmr2, td.rtMr2) &&
|
|
23
|
+
eq(m.rtmr3, td.rtMr3));
|
|
24
|
+
}
|
|
25
|
+
export const measuredImageCapability = {
|
|
26
|
+
id: CAP_ID,
|
|
27
|
+
verify(input) {
|
|
28
|
+
const claim = claimId(CAP_ID);
|
|
29
|
+
const p = input.parsedQuote;
|
|
30
|
+
if (!p || !p.td)
|
|
31
|
+
return { claim, ok: false, detail: 'no TDX measurements available (a verified tee-tdx quote is required)' };
|
|
32
|
+
const policy = input.policy;
|
|
33
|
+
const approved = policy?.approvedMeasurements;
|
|
34
|
+
if (!approved || approved.length === 0) {
|
|
35
|
+
return { claim, ok: false, detail: 'no approved measurement set configured' };
|
|
36
|
+
}
|
|
37
|
+
if (!approved.some((m) => matches(m, p.td))) {
|
|
38
|
+
return { claim, ok: false, detail: `MRTD ${hex(p.td.mrTd).slice(0, 16)}… matches no approved measurement` };
|
|
39
|
+
}
|
|
40
|
+
// A matching measurement alone says nothing about freshness. Without a report_data scheme
|
|
41
|
+
// that binds this quote to the round, it could be a genuine but replayed or borrowed quote.
|
|
42
|
+
const caveat = p.binding ? '' : ' (freshness/instance binding NOT verified — no report_data scheme declared)';
|
|
43
|
+
return { claim, ok: true, detail: `measurements match an approved image (MRTD ${hex(p.td.mrTd).slice(0, 16)}…)${caveat}` };
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=measured-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measured-image.js","sourceRoot":"","sources":["../../src/caps/measured-image.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC;;;;;;;GAOG;AAEH,MAAM,MAAM,GAAG,gCAAgC,CAAA;AAe/C,SAAS,GAAG,CAAC,CAAa;IACxB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACvC,CAAC;AAED,uFAAuF;AACvF,SAAS,OAAO,CAAC,CAAsB,EAAE,EAAwB;IAC/D,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAA;IACrB,MAAM,EAAE,GAAG,CAAC,QAA4B,EAAE,MAAkB,EAAW,EAAE,CACvE,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,MAAM,CAAC,CAAA;IAClE,OAAO,CACL,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;QACrC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;QACrB,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;QACrB,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;QACrB,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CACtB,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,EAAE,EAAE,MAAM;IAEV,MAAM,CAAC,KAA4B;QACjC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QAC7B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAyC,CAAA;QACzD,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;YAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,sEAAsE,EAAE,CAAA;QAC5H,MAAM,MAAM,GAAG,KAAK,CAAC,MAAyC,CAAA;QAC9D,MAAM,QAAQ,GAAG,MAAM,EAAE,oBAAoB,CAAA;QAC7C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAA;QAC/E,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC5C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,mCAAmC,EAAE,CAAA;QAC7G,CAAC;QACD,0FAA0F;QAC1F,4FAA4F;QAC5F,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,6EAA6E,CAAA;QAC7G,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,8CAA8C,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM,EAAE,EAAE,CAAA;IAC5H,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Capability } from '../capability.js';
|
|
2
|
+
/**
|
|
3
|
+
* Capability 'seller-provider-claims': carries the inference provider's claims into the
|
|
4
|
+
* protocol with per-claim granularity — one ClaimResult per claim, namespaced
|
|
5
|
+
* '<verifier>:seller-provider-claims/<name>'. The claims menu is frozen in the SDK
|
|
6
|
+
* (PROVIDER_CLAIMS_MENU below), never supplied by the seller or provider; the provider's
|
|
7
|
+
* document supplies values only ({ "<name>": <value> }).
|
|
8
|
+
*
|
|
9
|
+
* Frozen proof levels:
|
|
10
|
+
* 'asserted' the claim may pass on bundle integrity alone: the document rides in the
|
|
11
|
+
* evidence bundle that seller-bound signs (freshness + seller identity).
|
|
12
|
+
* 'tdx-quote' the claim passes only when the provider's TDX quote (verified this round
|
|
13
|
+
* with DCAP as seller-provider-tee-genuine) commits to this exact document
|
|
14
|
+
* and nonce in its report_data (see claimsReportData). The provider's TEE
|
|
15
|
+
* then attests the claim; it is not merely asserted.
|
|
16
|
+
* When the quote binding holds, asserted-level claims are reported TEE-attested too.
|
|
17
|
+
*
|
|
18
|
+
* The document is provider-authored bytes carried verbatim (base64 field on the same
|
|
19
|
+
* config-driven evidence route as the provider quote). The binding hashes the exact
|
|
20
|
+
* bytes, so no re-encoding is allowed anywhere. No provider specifics live here.
|
|
21
|
+
*/
|
|
22
|
+
export declare const PROVIDER_CLAIMS_CAP_ID = "seller-provider-claims";
|
|
23
|
+
/** Config-key convention for this cap's collector; mirrors tdxConfigKey. */
|
|
24
|
+
export declare function claimsConfigKey(key: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Provider quote report_data layout for TEE-attested claims:
|
|
27
|
+
*
|
|
28
|
+
* report_data[ 0:32] = SHA-256( DOMAIN ‖ nonce(32) ‖ SHA-256(claimsDocBytes) )
|
|
29
|
+
* report_data[32:64] = reserved // gpu-cc binds the GPU via the NRAS nonce, not this half
|
|
30
|
+
*
|
|
31
|
+
* `claimsReportData` returns the 32-byte [0:32] commitment; the verifier compares it against
|
|
32
|
+
* the provider quote's first half.
|
|
33
|
+
*/
|
|
34
|
+
export declare const PROVIDER_REPORT_DATA_DOMAIN = "antseed-provider-report-data-v1";
|
|
35
|
+
export declare function claimsReportData(nonce: Uint8Array, docBytes: Uint8Array): Uint8Array;
|
|
36
|
+
/** One frozen menu entry: what the claim means, how its value must look, what proves it. */
|
|
37
|
+
export interface ProviderClaimDefinition {
|
|
38
|
+
/** Human meaning of the claim, frozen with its verification semantics. */
|
|
39
|
+
description: string;
|
|
40
|
+
/** Minimum proof required to pass: 'asserted' (bundle-bound) or 'tdx-quote' (TEE-bound). */
|
|
41
|
+
proof: 'asserted' | 'tdx-quote';
|
|
42
|
+
/** Frozen value check; returns a failure reason, or null when the value is acceptable. */
|
|
43
|
+
validate(value: unknown): string | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The frozen claims menu for this SDK version. Buyers verify only against these
|
|
47
|
+
* definitions; a document name outside this menu can never pass. Add entries only with
|
|
48
|
+
* an SDK version bump (the CLI trust registry pins the exact version network-wide).
|
|
49
|
+
*/
|
|
50
|
+
export declare const PROVIDER_CLAIMS_MENU: Record<string, ProviderClaimDefinition>;
|
|
51
|
+
export declare const providerClaimsCapability: Capability;
|
|
52
|
+
//# sourceMappingURL=provider-claims.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-claims.d.ts","sourceRoot":"","sources":["../../src/caps/provider-claims.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAiD,MAAM,kBAAkB,CAAA;AAKjG;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,sBAAsB,2BAA2B,CAAA;AAE9D,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,oCAAoC,CAAA;AAE5E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,GAAG,UAAU,CAOpF;AAED,4FAA4F;AAC5F,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAA;IACnB,4FAA4F;IAC5F,KAAK,EAAE,UAAU,GAAG,WAAW,CAAA;IAC/B,0FAA0F;IAC1F,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAA;CACxC;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAiBxE,CAAA;AAwED,eAAO,MAAM,wBAAwB,EAAE,UA0DtC,CAAA"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { claimId } from '../shared.js';
|
|
3
|
+
import { collectViaHttp } from '../collect/http.js';
|
|
4
|
+
import { isTcbAcceptable } from './tee-tdx.js';
|
|
5
|
+
/**
|
|
6
|
+
* Capability 'seller-provider-claims': carries the inference provider's claims into the
|
|
7
|
+
* protocol with per-claim granularity — one ClaimResult per claim, namespaced
|
|
8
|
+
* '<verifier>:seller-provider-claims/<name>'. The claims menu is frozen in the SDK
|
|
9
|
+
* (PROVIDER_CLAIMS_MENU below), never supplied by the seller or provider; the provider's
|
|
10
|
+
* document supplies values only ({ "<name>": <value> }).
|
|
11
|
+
*
|
|
12
|
+
* Frozen proof levels:
|
|
13
|
+
* 'asserted' the claim may pass on bundle integrity alone: the document rides in the
|
|
14
|
+
* evidence bundle that seller-bound signs (freshness + seller identity).
|
|
15
|
+
* 'tdx-quote' the claim passes only when the provider's TDX quote (verified this round
|
|
16
|
+
* with DCAP as seller-provider-tee-genuine) commits to this exact document
|
|
17
|
+
* and nonce in its report_data (see claimsReportData). The provider's TEE
|
|
18
|
+
* then attests the claim; it is not merely asserted.
|
|
19
|
+
* When the quote binding holds, asserted-level claims are reported TEE-attested too.
|
|
20
|
+
*
|
|
21
|
+
* The document is provider-authored bytes carried verbatim (base64 field on the same
|
|
22
|
+
* config-driven evidence route as the provider quote). The binding hashes the exact
|
|
23
|
+
* bytes, so no re-encoding is allowed anywhere. No provider specifics live here.
|
|
24
|
+
*/
|
|
25
|
+
export const PROVIDER_CLAIMS_CAP_ID = 'seller-provider-claims';
|
|
26
|
+
/** Config-key convention for this cap's collector; mirrors tdxConfigKey. */
|
|
27
|
+
export function claimsConfigKey(key) {
|
|
28
|
+
return `${PROVIDER_CLAIMS_CAP_ID}.${key}`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Provider quote report_data layout for TEE-attested claims:
|
|
32
|
+
*
|
|
33
|
+
* report_data[ 0:32] = SHA-256( DOMAIN ‖ nonce(32) ‖ SHA-256(claimsDocBytes) )
|
|
34
|
+
* report_data[32:64] = reserved // gpu-cc binds the GPU via the NRAS nonce, not this half
|
|
35
|
+
*
|
|
36
|
+
* `claimsReportData` returns the 32-byte [0:32] commitment; the verifier compares it against
|
|
37
|
+
* the provider quote's first half.
|
|
38
|
+
*/
|
|
39
|
+
export const PROVIDER_REPORT_DATA_DOMAIN = 'antseed-provider-report-data-v1';
|
|
40
|
+
export function claimsReportData(nonce, docBytes) {
|
|
41
|
+
const docHash = createHash('sha256').update(Buffer.from(docBytes)).digest();
|
|
42
|
+
const h = createHash('sha256');
|
|
43
|
+
h.update(Buffer.from(PROVIDER_REPORT_DATA_DOMAIN, 'utf8'));
|
|
44
|
+
h.update(Buffer.from(nonce));
|
|
45
|
+
h.update(docHash);
|
|
46
|
+
return new Uint8Array(h.digest());
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The frozen claims menu for this SDK version. Buyers verify only against these
|
|
50
|
+
* definitions; a document name outside this menu can never pass. Add entries only with
|
|
51
|
+
* an SDK version bump (the CLI trust registry pins the exact version network-wide).
|
|
52
|
+
*/
|
|
53
|
+
export const PROVIDER_CLAIMS_MENU = {
|
|
54
|
+
'model-id': {
|
|
55
|
+
description: 'the model identifier this provider serves for the routed requests',
|
|
56
|
+
proof: 'asserted',
|
|
57
|
+
validate: (v) => typeof v === 'string' && v.length > 0 && v.length <= 200
|
|
58
|
+
? null
|
|
59
|
+
: 'expected a non-empty string (max 200 chars)',
|
|
60
|
+
},
|
|
61
|
+
'serving-image-digest': {
|
|
62
|
+
description: 'digest of the serving-stack image handling requests inside the provider TEE',
|
|
63
|
+
proof: 'tdx-quote',
|
|
64
|
+
validate: (v) => typeof v === 'string' && /^sha256:[0-9a-f]{64}$/.test(v)
|
|
65
|
+
? null
|
|
66
|
+
: 'expected "sha256:<64 lowercase hex>"',
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
/** Claim names become protocol claim-id path segments; keep them id-safe and bounded. */
|
|
70
|
+
const CLAIM_NAME_RE = /^[a-z0-9][a-z0-9.-]{0,63}$/;
|
|
71
|
+
/** Hard bound on claims per document, so a provider cannot flood the buyer's report. */
|
|
72
|
+
const MAX_CLAIMS = 64;
|
|
73
|
+
/** Hard bound on the claims document size before JSON.parse (a hostile seller must not force an unbounded parse). */
|
|
74
|
+
const MAX_DOC_BYTES = 64 * 1024;
|
|
75
|
+
/** Parse + validate a claims document envelope. Throws with a doc-level reason. */
|
|
76
|
+
function parseClaimsDoc(bytes) {
|
|
77
|
+
if (bytes.length > MAX_DOC_BYTES) {
|
|
78
|
+
throw new Error(`claims document exceeds ${MAX_DOC_BYTES} bytes (${bytes.length})`);
|
|
79
|
+
}
|
|
80
|
+
let root;
|
|
81
|
+
try {
|
|
82
|
+
root = JSON.parse(new TextDecoder().decode(bytes));
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
throw new Error(`malformed claims document: ${err instanceof Error ? err.message : String(err)}`);
|
|
86
|
+
}
|
|
87
|
+
if (root === null || typeof root !== 'object' || Array.isArray(root)) {
|
|
88
|
+
throw new Error('malformed claims document: not a JSON object');
|
|
89
|
+
}
|
|
90
|
+
const { version, claims } = root;
|
|
91
|
+
if (version !== undefined && version !== 1) {
|
|
92
|
+
throw new Error(`unsupported claims document version ${JSON.stringify(version)} (expected 1)`);
|
|
93
|
+
}
|
|
94
|
+
if (claims === null || typeof claims !== 'object' || Array.isArray(claims)) {
|
|
95
|
+
throw new Error('malformed claims document: "claims" is not an object');
|
|
96
|
+
}
|
|
97
|
+
const entries = Object.entries(claims);
|
|
98
|
+
if (entries.length === 0)
|
|
99
|
+
throw new Error('claims document declares no claims');
|
|
100
|
+
if (entries.length > MAX_CLAIMS) {
|
|
101
|
+
throw new Error(`claims document has too many claims (${entries.length} > ${MAX_CLAIMS})`);
|
|
102
|
+
}
|
|
103
|
+
for (const [name] of entries) {
|
|
104
|
+
if (!CLAIM_NAME_RE.test(name)) {
|
|
105
|
+
throw new Error(`invalid claim name "${name}": use lowercase letters, digits, hyphen or dot (max 64 chars)`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return new Map(entries);
|
|
109
|
+
}
|
|
110
|
+
/** Compact human summary of a claim's value for ClaimResult.detail. */
|
|
111
|
+
function summarize(value) {
|
|
112
|
+
const s = JSON.stringify(value) ?? 'undefined';
|
|
113
|
+
return s.length > 80 ? `${s.slice(0, 77)}…` : s;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* One binding verdict per document: is the provider quote genuine and committed to these
|
|
117
|
+
* exact document bytes? Every claim in the document shares it.
|
|
118
|
+
*/
|
|
119
|
+
function quoteBinding(p, nonce, docBytes) {
|
|
120
|
+
if (!p)
|
|
121
|
+
return 'no verified provider TDX quote in this round (this claim requires seller-provider-tee-genuine evidence)';
|
|
122
|
+
if (p.error)
|
|
123
|
+
return p.error;
|
|
124
|
+
if (!isTcbAcceptable(p.status))
|
|
125
|
+
return `provider TCB status not acceptable: ${p.status || 'unknown'}`;
|
|
126
|
+
if (!p.td)
|
|
127
|
+
return 'provider quote is not an Intel TDX quote';
|
|
128
|
+
if (p.td.debug === true)
|
|
129
|
+
return 'provider TDX debug mode is enabled';
|
|
130
|
+
// Compare the canonical [0:32] commitment; [32:64] is reserved (gpu-cc binds via NRAS).
|
|
131
|
+
const expected = claimsReportData(nonce, docBytes);
|
|
132
|
+
const rd = p.td.reportData;
|
|
133
|
+
if (rd.length < 32 || !Buffer.from(rd.subarray(0, 32)).equals(Buffer.from(expected))) {
|
|
134
|
+
return 'provider quote report_data does not commit to this claims document';
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
export const providerClaimsCapability = {
|
|
139
|
+
id: PROVIDER_CLAIMS_CAP_ID,
|
|
140
|
+
verify(input) {
|
|
141
|
+
const parent = claimId(PROVIDER_CLAIMS_CAP_ID);
|
|
142
|
+
if (!input.evidence) {
|
|
143
|
+
return [{ claim: parent, ok: false, detail: 'seller returned no claims document' }];
|
|
144
|
+
}
|
|
145
|
+
let values;
|
|
146
|
+
try {
|
|
147
|
+
values = parseClaimsDoc(input.evidence);
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
return [{ claim: parent, ok: false, detail: err instanceof Error ? err.message : String(err) }];
|
|
151
|
+
}
|
|
152
|
+
// Bind once per document; every claim shares the verdict.
|
|
153
|
+
const p = input.parsedQuote;
|
|
154
|
+
const bindingFailure = quoteBinding(p, input.nonce, input.evidence);
|
|
155
|
+
const results = [];
|
|
156
|
+
for (const [name, value] of values) {
|
|
157
|
+
const claim = `${parent}/${name}`;
|
|
158
|
+
const def = PROVIDER_CLAIMS_MENU[name];
|
|
159
|
+
if (!def) {
|
|
160
|
+
results.push({ claim, ok: false, detail: `unknown claim "${name}": not in this SDK version's frozen claims menu` });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const invalid = def.validate(value);
|
|
164
|
+
if (invalid) {
|
|
165
|
+
results.push({ claim, ok: false, detail: `invalid value: ${invalid}` });
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (def.proof === 'tdx-quote' && bindingFailure) {
|
|
169
|
+
results.push({ claim, ok: false, detail: bindingFailure });
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// An asserted-level pass is a signed self-assertion, not an independent measurement.
|
|
173
|
+
// Label it so buyer UIs and policy cannot render it as "verified".
|
|
174
|
+
results.push({
|
|
175
|
+
claim,
|
|
176
|
+
ok: true,
|
|
177
|
+
detail: bindingFailure
|
|
178
|
+
? `provider-asserted only, NOT independently verified: ${summarize(value)}`
|
|
179
|
+
: `attested by provider TEE (report_data-bound TDX quote): ${summarize(value)}`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return results;
|
|
183
|
+
},
|
|
184
|
+
async collect(input) {
|
|
185
|
+
const url = input.config[claimsConfigKey('url')];
|
|
186
|
+
const field = input.config[claimsConfigKey('field')];
|
|
187
|
+
if (!url || !field) {
|
|
188
|
+
throw new Error(`${PROVIDER_CLAIMS_CAP_ID} requires an evidence url and a claims field; not offered`);
|
|
189
|
+
}
|
|
190
|
+
// collectViaHttp base64-decodes the field — the document bytes arrive verbatim, which
|
|
191
|
+
// the tdx-quote binding depends on (report_data hashes the exact bytes).
|
|
192
|
+
return collectViaHttp(url, input.nonce, field);
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=provider-claims.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-claims.js","sourceRoot":"","sources":["../../src/caps/provider-claims.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Capability } from '../capability.js';
|
|
2
|
+
/** Recover the 40-hex (lowercase, no 0x) EVM address that produced an r‖s‖v signature. */
|
|
3
|
+
export declare function recoverEvmAddress(digest: Uint8Array, sig: Uint8Array): string;
|
|
4
|
+
/** Build a signer over 32-byte digests from a hex private key; it emits r‖s‖v (v = 27/28). */
|
|
5
|
+
export declare function signerFromPrivateKey(privHex: string): (msg: Uint8Array) => Promise<Uint8Array>;
|
|
6
|
+
/** The 40-hex EVM address a private key corresponds to (for seller-side consistency checks). */
|
|
7
|
+
export declare function evmAddressFromPrivateKey(privHex: string): string;
|
|
8
|
+
export declare const sellerBoundCapability: Capability;
|
|
9
|
+
//# sourceMappingURL=seller-bound.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seller-bound.d.ts","sourceRoot":"","sources":["../../src/caps/seller-bound.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAiD,MAAM,kBAAkB,CAAA;AAejG,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAW7E;AAED,8FAA8F;AAC9F,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAW9F;AAED,gGAAgG;AAChG,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIhE;AAED,eAAO,MAAM,qBAAqB,EAAE,UA+CnC,CAAA"}
|