@moonglade/provenance 0.0.0-stage → 2.6.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 +21 -0
- package/NOTICE.md +9 -0
- package/README.md +76 -2
- package/SPEC.md +176 -0
- package/TIMESTAMP.md +21 -0
- package/dist/artifact-cli.d.ts +2 -0
- package/dist/artifact-cli.js +108 -0
- package/dist/artifactEnvelope.d.ts +38 -0
- package/dist/artifactEnvelope.js +61 -0
- package/dist/artifactHook.d.ts +30 -0
- package/dist/artifactHook.js +114 -0
- package/dist/badge.d.ts +83 -0
- package/dist/badge.js +403 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.js +782 -0
- package/dist/mcp.d.ts +87 -0
- package/dist/mcp.js +352 -0
- package/dist/merkle.d.ts +71 -0
- package/dist/merkle.js +176 -0
- package/dist/self-test.d.ts +21 -0
- package/dist/self-test.js +280 -0
- package/dist/timestamp.d.ts +274 -0
- package/dist/timestamp.js +1103 -0
- package/package.json +75 -4
- package/trust/README.md +19 -0
- package/trust/registry.json +12 -0
- package/trust/root-public.asc +10 -0
- package/wasm/mgc_wasm.d.ts +53 -0
- package/wasm/mgc_wasm.js +389 -0
- package/wasm/mgc_wasm_bg.wasm +0 -0
- package/wasm/mgc_wasm_bg.wasm.d.ts +20 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/** RFC 3161 signature/imprint checks and optional caller-anchored chain validation.
|
|
2
|
+
* Acquisition probe tiers describe routing; only verified tokens supply timestamp evidence.
|
|
3
|
+
* Revocation checking is outside this implementation.
|
|
4
|
+
*/
|
|
5
|
+
export interface TSAProbeResult {
|
|
6
|
+
tier: 'L1_CRYPTO_PRIMARY' | 'L2_CRYPTO_FALLBACK' | 'L3_NETWORK_CONSENSUS' | 'L4_HOST_UNAUTHENTICATED';
|
|
7
|
+
method: 'RFC3161' | 'HTTP_DATE' | 'KERNEL_UTC';
|
|
8
|
+
server: string;
|
|
9
|
+
status: 'SUCCESS' | 'ERROR' | 'TIMEOUT';
|
|
10
|
+
timestamp_iso?: string;
|
|
11
|
+
token_b64?: string;
|
|
12
|
+
token_bytes?: Buffer;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface DTAResult {
|
|
16
|
+
tier: 'INTEGRITY_ONLY' | 'L3_NETWORK_CONSENSUS' | 'L4_HOST_UNAUTHENTICATED';
|
|
17
|
+
tsa?: string;
|
|
18
|
+
tsa_time: string;
|
|
19
|
+
token_b64?: string;
|
|
20
|
+
token_bytes?: Buffer;
|
|
21
|
+
probes: TSAProbeResult[];
|
|
22
|
+
}
|
|
23
|
+
export interface DTAOptions {
|
|
24
|
+
/** If specified, bypasses multi-tier fanout and queries only this specific TSA server URL or network host */
|
|
25
|
+
specifiedServer?: string;
|
|
26
|
+
/** If specified, restricts queries to this tier only */
|
|
27
|
+
specifiedTier?: 'L1_CRYPTO_PRIMARY' | 'L2_CRYPTO_FALLBACK' | 'L3_NETWORK_CONSENSUS' | 'L4_HOST_UNAUTHENTICATED';
|
|
28
|
+
/**
|
|
29
|
+
* Number of probes to simultaneously seek from each tier (default: 1 for the TSA tiers,
|
|
30
|
+
* min(3, distinct hosts) for the L3 network tier, because one probe can never reach quorum)
|
|
31
|
+
*/
|
|
32
|
+
probesPerTier?: number;
|
|
33
|
+
/** Whether to rotate through available endpoints (default: true) */
|
|
34
|
+
rotate?: boolean;
|
|
35
|
+
primaryEndpoints?: string[];
|
|
36
|
+
fallbackEndpoints?: string[];
|
|
37
|
+
networkEndpoints?: string[];
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
certReq?: boolean;
|
|
40
|
+
nonce?: Buffer | bigint;
|
|
41
|
+
circuitBreaker?: EndpointCircuitBreaker;
|
|
42
|
+
maxParallelProbes?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Distinct agreeing network hosts needed for L3_NETWORK_CONSENSUS (default 2). A single host
|
|
45
|
+
* is never L3 unless this is explicitly set to 1.
|
|
46
|
+
*/
|
|
47
|
+
quorumThreshold?: number;
|
|
48
|
+
/** Maximum spread between the earliest and latest L3 probe, in milliseconds (default 3000). */
|
|
49
|
+
maxDriftMs?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface TierEndpointConfig {
|
|
52
|
+
default: string;
|
|
53
|
+
fallbacks: string[];
|
|
54
|
+
}
|
|
55
|
+
export declare const TIER_CONFIGS: {
|
|
56
|
+
L1: TierEndpointConfig;
|
|
57
|
+
L2: TierEndpointConfig;
|
|
58
|
+
L3: TierEndpointConfig;
|
|
59
|
+
};
|
|
60
|
+
export declare const DEFAULT_PRIMARY_TSAS: string[];
|
|
61
|
+
export declare const DEFAULT_FALLBACK_TSAS: string[];
|
|
62
|
+
export declare const DEFAULT_NETWORK_HOSTS: string[];
|
|
63
|
+
export interface ServerPolicy {
|
|
64
|
+
url: string;
|
|
65
|
+
name: string;
|
|
66
|
+
tier: 'L1_CRYPTO_PRIMARY' | 'L2_CRYPTO_FALLBACK' | 'L3_NETWORK_CONSENSUS';
|
|
67
|
+
/** Minimum interval in ms between consecutive requests to this endpoint (rate-limit compliance) */
|
|
68
|
+
minIntervalMs: number;
|
|
69
|
+
}
|
|
70
|
+
export declare const DEFAULT_SERVER_POLICIES: ServerPolicy[];
|
|
71
|
+
export interface EndpointHealth {
|
|
72
|
+
url?: string;
|
|
73
|
+
name?: string;
|
|
74
|
+
consecutiveFailures: number;
|
|
75
|
+
nextAvailableTime: number;
|
|
76
|
+
lastRequestTime?: number;
|
|
77
|
+
lastSuccessTime?: number;
|
|
78
|
+
lastError?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface ServerStatusSnapshot {
|
|
81
|
+
url: string;
|
|
82
|
+
name?: string;
|
|
83
|
+
status: 'READY' | 'COOLDOWN' | 'BACKOFF';
|
|
84
|
+
consecutiveFailures: number;
|
|
85
|
+
remainingCooldownMs: number;
|
|
86
|
+
lastError?: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Circuit breaker & Server Pool Manager.
|
|
90
|
+
* Manages:
|
|
91
|
+
* 1. Endpoint health and consecutive failure tracking
|
|
92
|
+
* 2. Exponential backoff for failing/down servers
|
|
93
|
+
* 3. Individual server policies (e.g. FreeTSA 15s rate-limit cooldown)
|
|
94
|
+
* 4. Fair round-robin rotation queue ("who's next")
|
|
95
|
+
* 5. Telemetry for ready vs disabled/cooldown servers
|
|
96
|
+
*/
|
|
97
|
+
export declare class EndpointCircuitBreaker {
|
|
98
|
+
private health;
|
|
99
|
+
private policies;
|
|
100
|
+
private queuePointers;
|
|
101
|
+
readonly baseBackoffMs: number;
|
|
102
|
+
readonly maxBackoffMs: number;
|
|
103
|
+
constructor(options?: {
|
|
104
|
+
baseBackoffMs?: number;
|
|
105
|
+
maxBackoffMs?: number;
|
|
106
|
+
policies?: ServerPolicy[];
|
|
107
|
+
});
|
|
108
|
+
getPolicy(url: string): ServerPolicy;
|
|
109
|
+
setPolicy(policy: ServerPolicy): void;
|
|
110
|
+
isAvailable(url: string, now?: number): boolean;
|
|
111
|
+
getServerStatus(url: string, now?: number): 'READY' | 'COOLDOWN' | 'BACKOFF';
|
|
112
|
+
recordRequest(url: string, now?: number): void;
|
|
113
|
+
recordSuccess(url: string, now?: number): void;
|
|
114
|
+
recordFailure(url: string, error: string, now?: number): number;
|
|
115
|
+
getHealth(url: string): EndpointHealth | undefined;
|
|
116
|
+
reset(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Return ordered candidate queue starting with "who's next".
|
|
119
|
+
*/
|
|
120
|
+
getQueue(urls: string[], queueKey?: string): string[];
|
|
121
|
+
/**
|
|
122
|
+
* Return servers currently on cooldown or in failure backoff.
|
|
123
|
+
*/
|
|
124
|
+
getDisabledEndpoints(urls: string[], now?: number): ServerStatusSnapshot[];
|
|
125
|
+
/**
|
|
126
|
+
* Return servers currently READY to serve requests immediately.
|
|
127
|
+
*/
|
|
128
|
+
getReadyEndpoints(urls: string[], now?: number): ServerStatusSnapshot[];
|
|
129
|
+
/**
|
|
130
|
+
* Fair rotating endpoint selection.
|
|
131
|
+
* Cycles through the array in round-robin order, picking healthy/available endpoints,
|
|
132
|
+
* skipping those in failure backoff or policy cooldown, and advancing the queue pointer.
|
|
133
|
+
*/
|
|
134
|
+
selectRotatingEndpoints(urls: string[], count?: number, queueKey?: string, now?: number): string[];
|
|
135
|
+
/**
|
|
136
|
+
* Prioritized selection (used for targeted or non-rotating requests).
|
|
137
|
+
*/
|
|
138
|
+
selectEndpoints(urls: string[], maxCount?: number, now?: number): string[];
|
|
139
|
+
}
|
|
140
|
+
export declare const globalCircuitBreaker: EndpointCircuitBreaker;
|
|
141
|
+
/**
|
|
142
|
+
* Helper to encode ASN.1 DER length octets.
|
|
143
|
+
*/
|
|
144
|
+
export declare function encodeDerLength(len: number): Buffer;
|
|
145
|
+
/**
|
|
146
|
+
* Helper to wrap elements in an ASN.1 DER SEQUENCE (tag 0x30).
|
|
147
|
+
*/
|
|
148
|
+
export declare function encodeDerSequence(items: Buffer[]): Buffer;
|
|
149
|
+
/**
|
|
150
|
+
* Helper to decode ASN.1 DER length octets from a buffer at a given offset.
|
|
151
|
+
* Returns the parsed length and the number of octets consumed by the length header.
|
|
152
|
+
*/
|
|
153
|
+
export declare function decodeDerLength(buf: Buffer, offset: number): {
|
|
154
|
+
length: number;
|
|
155
|
+
headerLength: number;
|
|
156
|
+
};
|
|
157
|
+
export declare const PKI_STATUS_TEXT: Record<number, string>;
|
|
158
|
+
export interface ValidateTimeStampRespOptions {
|
|
159
|
+
expectedDigest?: Buffer;
|
|
160
|
+
expectedNonce?: Buffer | bigint;
|
|
161
|
+
}
|
|
162
|
+
export interface ValidationResultRFC3161 {
|
|
163
|
+
valid: boolean;
|
|
164
|
+
status: number;
|
|
165
|
+
statusText: string;
|
|
166
|
+
error?: string;
|
|
167
|
+
genTime?: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Parse the RFC 3161 PKIStatusInfo integer code from TimeStampResp.
|
|
171
|
+
* RFC 3161 §2.4.2:
|
|
172
|
+
* TimeStampResp ::= SEQUENCE {
|
|
173
|
+
* status PKIStatusInfo,
|
|
174
|
+
* timeStampToken TimeStampToken OPTIONAL
|
|
175
|
+
* }
|
|
176
|
+
* PKIStatusInfo ::= SEQUENCE {
|
|
177
|
+
* status PKIStatus,
|
|
178
|
+
* statusString PKIFreeText OPTIONAL,
|
|
179
|
+
* failInfo PKIFailureInfo OPTIONAL
|
|
180
|
+
* }
|
|
181
|
+
*/
|
|
182
|
+
export declare function parsePkiStatus(respBuffer: Buffer): {
|
|
183
|
+
status: number;
|
|
184
|
+
statusText: string;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* In-band RFC 3161 TimeStampResp validator.
|
|
188
|
+
* Enforces:
|
|
189
|
+
* 1. PKIStatusInfo is granted (0) or grantedWithMods (1)
|
|
190
|
+
* 2. TimeStampToken presence
|
|
191
|
+
* 3. MessageImprint digest equality (asserts TSA stamped the exact requested file hash)
|
|
192
|
+
* 4. Cryptographic nonce echo match (asserts replay attack protection)
|
|
193
|
+
*/
|
|
194
|
+
export declare function validateTimeStampResp(respBuffer: Buffer, options?: ValidateTimeStampRespOptions): ValidationResultRFC3161;
|
|
195
|
+
export interface TimestampTokenVerificationResult {
|
|
196
|
+
verified: boolean;
|
|
197
|
+
signerVerified?: boolean;
|
|
198
|
+
trusted?: boolean;
|
|
199
|
+
trust?: 'ANCHORED' | 'INTEGRITY_ONLY';
|
|
200
|
+
signerSubject?: string;
|
|
201
|
+
genTime?: string;
|
|
202
|
+
error?: string;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Cryptographically verifies an RFC 3161 TimeStampToken or TimeStampResp buffer using PKI.js.
|
|
206
|
+
* Validates CMS SignedData signature over signedAttrs (including 0x31 SET OF re-encoding),
|
|
207
|
+
* confirms message-digest matches the encapsulated TSTInfo, and asserts the stamped
|
|
208
|
+
* document digest matches documentBytes.
|
|
209
|
+
*/
|
|
210
|
+
export declare function verifyTimeStampToken(tsrBuffer: Buffer, documentBytes: Buffer, options?: {
|
|
211
|
+
trustAnchors?: string[];
|
|
212
|
+
expectedDigest?: Buffer;
|
|
213
|
+
}): Promise<TimestampTokenVerificationResult>;
|
|
214
|
+
/**
|
|
215
|
+
* Build an RFC 3161 TimeStampReq ASN.1 DER structure.
|
|
216
|
+
* RFC 3161 §2.4.1:
|
|
217
|
+
* TimeStampReq ::= SEQUENCE {
|
|
218
|
+
* version INTEGER { v1(1) },
|
|
219
|
+
* messageImprint MessageImprint,
|
|
220
|
+
* nonce INTEGER OPTIONAL,
|
|
221
|
+
* certReq BOOLEAN DEFAULT FALSE
|
|
222
|
+
* }
|
|
223
|
+
*/
|
|
224
|
+
export declare function buildTimeStampReq(sha256Digest: Buffer, options?: {
|
|
225
|
+
certReq?: boolean;
|
|
226
|
+
nonce?: Buffer | bigint;
|
|
227
|
+
}): Buffer;
|
|
228
|
+
/**
|
|
229
|
+
* Extract GeneralizedTime (tag 0x18) from ASN.1 DER TimeStampResp buffer.
|
|
230
|
+
* Returns ISO 8601 formatted string or null if not found.
|
|
231
|
+
*/
|
|
232
|
+
export declare function extractGenTime(tsrBuffer: Buffer): string | null;
|
|
233
|
+
/**
|
|
234
|
+
* Execute HTTP POST query to an RFC 3161 TSA endpoint.
|
|
235
|
+
*/
|
|
236
|
+
export declare function queryTsa(tsaUrl: string, tsqBuffer: Buffer, timeoutMs?: number): Promise<Buffer>;
|
|
237
|
+
/**
|
|
238
|
+
* Probe a single TSA server and return a structured telemetry record.
|
|
239
|
+
* Automatically performs in-band RFC 3161 verification on successful responses:
|
|
240
|
+
* - Checks PKIStatus is granted (0) or grantedWithMods (1)
|
|
241
|
+
* - Verifies TimeStampToken exists
|
|
242
|
+
* - Asserts messageImprint digest matches expectedDigest (if provided)
|
|
243
|
+
* - Asserts returned nonce matches expectedNonce (if provided)
|
|
244
|
+
*/
|
|
245
|
+
export declare function probeTsa(tsaUrl: string, tsqBuffer: Buffer, tier: 'L1_CRYPTO_PRIMARY' | 'L2_CRYPTO_FALLBACK', timeoutMs?: number, expectedDigest?: Buffer, expectedNonce?: Buffer | bigint, circuitBreaker?: EndpointCircuitBreaker): Promise<TSAProbeResult>;
|
|
246
|
+
/**
|
|
247
|
+
* Parse an RFC 7231 section 7.1.1.1 HTTP-date: IMF-fixdate, or the obsolete RFC 850 and asctime
|
|
248
|
+
* forms a recipient must still accept. The grammar is case-sensitive, the day name must agree
|
|
249
|
+
* with the date, and the date must exist (no 31 February, no 24:00:00, no leap second).
|
|
250
|
+
* Returns epoch milliseconds, or null for anything else - including ISO-8601 and bare numbers
|
|
251
|
+
* that `new Date(...)` would happily accept.
|
|
252
|
+
*/
|
|
253
|
+
export declare function parseHttpDate(value: string, now?: number): number | null;
|
|
254
|
+
/**
|
|
255
|
+
* Probe network time via HTTP Date header. The header must be an RFC 7231 HTTP-date.
|
|
256
|
+
*/
|
|
257
|
+
export declare function probeNetworkTime(host: string, timeoutMs?: number): Promise<TSAProbeResult>;
|
|
258
|
+
/**
|
|
259
|
+
* Evaluates whether successful L3 network probes form a Byzantine-tolerant quorum.
|
|
260
|
+
* Requirements:
|
|
261
|
+
* 1. At least 2 successful HTTP Date probes (or >= quorumThreshold).
|
|
262
|
+
* 2. Absolute time drift between min and max probe timestamps is within maxDriftMs (default: 3000ms).
|
|
263
|
+
* Returns the median timestamp and participating servers if quorum is reached, otherwise null.
|
|
264
|
+
*/
|
|
265
|
+
export declare function resolveNetworkConsensus(probes: TSAProbeResult[], quorumThreshold?: number, maxDriftMs?: number): {
|
|
266
|
+
consensusTime: string;
|
|
267
|
+
server: string;
|
|
268
|
+
} | null;
|
|
269
|
+
/**
|
|
270
|
+
* Execute Concurrent Multi-Source Degrading Timestamping Architecture (DTA) fan-out.
|
|
271
|
+
* Default pattern: simultaneously seeks 1 probe from each tier (L1, L2, L3, L4).
|
|
272
|
+
* If specifiedServer or specifiedTier is requested, executes targeted query instead.
|
|
273
|
+
*/
|
|
274
|
+
export declare function concurrentDegradingTimestamp(sha256Digest: Buffer, options?: DTAOptions): Promise<DTAResult>;
|