@gfdelarue/testkit 0.3.6 → 0.4.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/dist/app/run/engine-execution.d.ts +2 -0
- package/dist/app/run/engine-execution.js +1 -1
- package/dist/cli/command-catalog.d.ts +0 -127
- package/dist/cli/command-catalog.js +1 -1
- package/dist/cli/command-registry.d.ts +1 -0
- package/dist/cli/command-registry.js +1 -1
- package/dist/cli/entrypoint.js +1 -1
- package/dist/cli/framework/execute.d.ts +1 -0
- package/dist/cli/framework/execute.js +6 -6
- package/dist/cli/index.js +1 -1
- package/dist/cli/version-drift.js +7 -7
- package/dist/config/authoring/index.d.ts +0 -5
- package/dist/config/loader/index.d.ts +0 -1
- package/dist/config/loader/index.js +1 -1
- package/dist/engines/adapters/node-startup-cache.d.ts +8 -0
- package/dist/engines/adapters/node-startup-cache.js +1 -0
- package/dist/engines/api/execution.d.ts +2 -0
- package/dist/engines/managed-module-resolution.js +8 -1
- package/dist/engines/node-vitest/adapter/adapter.js +1 -1
- package/dist/engines/playwright/adapter/adapter.js +1 -1
- package/dist/environment/ready-environment.d.ts +3 -1
- package/dist/environment/ready-environment.js +1 -1
- package/dist/environment/run-environment.js +1 -1
- package/dist/environment/runtime-contexts.d.ts +1 -0
- package/dist/environment/runtime-contexts.js +1 -1
- package/dist/environment/runtime-manager.js +1 -1
- package/dist/evidence/bundles.d.ts +2 -3
- package/dist/evidence/bundles.js +1 -1
- package/dist/evidence/contracts.d.ts +0 -8
- package/dist/evidence/index.d.ts +1 -1
- package/dist/evidence/index.js +1 -1
- package/dist/process/execa-bundle.json +1 -1
- package/docs/engine-architecture.md +20 -0
- package/package.json +3 -10
- package/testkit-config-schema.md +0 -23
- package/dist/app/cloud/campaigns.d.ts +0 -6
- package/dist/app/cloud/campaigns.js +0 -1
- package/dist/app/cloud/control-actions.d.ts +0 -12
- package/dist/app/cloud/control-actions.js +0 -2
- package/dist/app/cloud/control-links.d.ts +0 -5
- package/dist/app/cloud/control-links.js +0 -1
- package/dist/app/cloud/control-read.d.ts +0 -24
- package/dist/app/cloud/control-read.js +0 -1
- package/dist/app/cloud/control-resources.d.ts +0 -3
- package/dist/app/cloud/control-resources.js +0 -1
- package/dist/app/cloud/control.d.ts +0 -34
- package/dist/app/cloud/control.js +0 -5
- package/dist/app/cloud/credentials.d.ts +0 -11
- package/dist/app/cloud/credentials.js +0 -2
- package/dist/app/cloud/index.d.ts +0 -22
- package/dist/app/cloud/index.js +0 -2
- package/dist/app/cloud/login.d.ts +0 -63
- package/dist/app/cloud/login.js +0 -2
- package/dist/app/cloud/migration/archive.d.ts +0 -13
- package/dist/app/cloud/migration/archive.js +0 -1
- package/dist/app/cloud/migration/commands.d.ts +0 -8
- package/dist/app/cloud/migration/commands.js +0 -1
- package/dist/app/cloud/migration/evidence.d.ts +0 -13
- package/dist/app/cloud/migration/evidence.js +0 -2
- package/dist/app/cloud/migration/files.d.ts +0 -16
- package/dist/app/cloud/migration/files.js +0 -2
- package/dist/app/cloud/migration/index.d.ts +0 -6
- package/dist/app/cloud/migration/index.js +0 -1
- package/dist/app/cloud/migration/journal.d.ts +0 -64
- package/dist/app/cloud/migration/journal.js +0 -1
- package/dist/app/cloud/migration/mapping-dispositions.d.ts +0 -3
- package/dist/app/cloud/migration/mapping-dispositions.js +0 -1
- package/dist/app/cloud/migration/mapping.d.ts +0 -11
- package/dist/app/cloud/migration/mapping.js +0 -2
- package/dist/app/cloud/migration/model.d.ts +0 -175
- package/dist/app/cloud/migration/model.js +0 -1
- package/dist/app/cloud/migration/plan.d.ts +0 -7
- package/dist/app/cloud/migration/plan.js +0 -1
- package/dist/app/cloud/migration/progress.d.ts +0 -19
- package/dist/app/cloud/migration/progress.js +0 -1
- package/dist/app/cloud/migration/reconcile.d.ts +0 -22
- package/dist/app/cloud/migration/reconcile.js +0 -1
- package/dist/app/cloud/migration/reconciliation-spool.d.ts +0 -4
- package/dist/app/cloud/migration/reconciliation-spool.js +0 -1
- package/dist/app/cloud/migration/state.d.ts +0 -15
- package/dist/app/cloud/migration/state.js +0 -1
- package/dist/app/cloud/migration/transfer.d.ts +0 -6
- package/dist/app/cloud/migration/transfer.js +0 -1
- package/dist/cli/cloud-apply-help.d.ts +0 -1
- package/dist/cli/cloud-apply-help.js +0 -56
- package/dist/cli/cloud-selection.d.ts +0 -2
- package/dist/cli/cloud-selection.js +0 -3
- package/dist/cli/commands/cloud/apply.d.ts +0 -5
- package/dist/cli/commands/cloud/apply.js +0 -1
- package/dist/cli/commands/cloud/campaign/create.d.ts +0 -5
- package/dist/cli/commands/cloud/campaign/create.js +0 -1
- package/dist/cli/commands/cloud/download.d.ts +0 -5
- package/dist/cli/commands/cloud/download.js +0 -1
- package/dist/cli/commands/cloud/list.d.ts +0 -5
- package/dist/cli/commands/cloud/list.js +0 -1
- package/dist/cli/commands/cloud/login.d.ts +0 -13
- package/dist/cli/commands/cloud/login.js +0 -2
- package/dist/cli/commands/cloud/logout.d.ts +0 -7
- package/dist/cli/commands/cloud/logout.js +0 -1
- package/dist/cli/commands/cloud/migrate/apply.d.ts +0 -2
- package/dist/cli/commands/cloud/migrate/apply.js +0 -1
- package/dist/cli/commands/cloud/migrate/plan.d.ts +0 -7
- package/dist/cli/commands/cloud/migrate/plan.js +0 -1
- package/dist/cli/commands/cloud/migrate/progress.d.ts +0 -2
- package/dist/cli/commands/cloud/migrate/progress.js +0 -2
- package/dist/cli/commands/cloud/migrate/reconcile.d.ts +0 -2
- package/dist/cli/commands/cloud/migrate/reconcile.js +0 -1
- package/dist/cli/commands/cloud/policy/preview.d.ts +0 -5
- package/dist/cli/commands/cloud/policy/preview.js +0 -1
- package/dist/cli/commands/cloud/project/create.d.ts +0 -5
- package/dist/cli/commands/cloud/project/create.js +0 -1
- package/dist/cli/commands/cloud/publish.d.ts +0 -7
- package/dist/cli/commands/cloud/publish.js +0 -1
- package/dist/cli/commands/cloud/session/revoke.d.ts +0 -8
- package/dist/cli/commands/cloud/session/revoke.js +0 -1
- package/dist/cli/commands/cloud/show.d.ts +0 -5
- package/dist/cli/commands/cloud/show.js +0 -1
- package/dist/cli/commands/cloud/snapshot.d.ts +0 -5
- package/dist/cli/commands/cloud/snapshot.js +0 -1
- package/dist/cli/commands/cloud/status.d.ts +0 -33
- package/dist/cli/commands/cloud/status.js +0 -1
- package/dist/cloud/account.d.ts +0 -34
- package/dist/cloud/account.js +0 -1
- package/dist/cloud/archive-contract.d.ts +0 -1
- package/dist/cloud/archive-contract.js +0 -1
- package/dist/cloud/archive.d.ts +0 -12
- package/dist/cloud/archive.js +0 -1
- package/dist/cloud/campaigns.d.ts +0 -200
- package/dist/cloud/campaigns.js +0 -2
- package/dist/cloud/client.d.ts +0 -68
- package/dist/cloud/client.js +0 -4
- package/dist/cloud/download.d.ts +0 -5
- package/dist/cloud/download.js +0 -1
- package/dist/cloud/historical-contract.d.ts +0 -224
- package/dist/cloud/historical-contract.js +0 -1
- package/dist/cloud/historical-json.d.ts +0 -16
- package/dist/cloud/historical-json.js +0 -1
- package/dist/cloud/historical.d.ts +0 -69
- package/dist/cloud/historical.js +0 -1
- package/dist/cloud/pagination.d.ts +0 -5
- package/dist/cloud/pagination.js +0 -1
- package/dist/cloud/transport.d.ts +0 -18
- package/dist/cloud/transport.js +0 -1
- package/dist/config/loader/cloud.d.ts +0 -2
- package/dist/config/loader/cloud.js +0 -1
- package/docs/cloud-control.md +0 -108
- package/docs/testkit-cloud-boundary.md +0 -628
- package/node_modules/buffer-crc32/LICENSE +0 -19
- package/node_modules/buffer-crc32/README.md +0 -55
- package/node_modules/buffer-crc32/dist/index.cjs +0 -306
- package/node_modules/buffer-crc32/dist/index.d.cts +0 -35
- package/node_modules/buffer-crc32/dist/index.d.mts +0 -35
- package/node_modules/buffer-crc32/dist/index.mjs +0 -304
- package/node_modules/buffer-crc32/index.d.ts +0 -35
- package/node_modules/buffer-crc32/package.json +0 -54
- package/node_modules/yazl/LICENSE +0 -21
- package/node_modules/yazl/README.md +0 -457
- package/node_modules/yazl/index.js +0 -826
- package/node_modules/yazl/package.json +0 -34
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
export interface CampaignReport {
|
|
2
|
-
schemaVersion: 1;
|
|
3
|
-
projectId: string;
|
|
4
|
-
campaignId: string;
|
|
5
|
-
idempotencyKey: string;
|
|
6
|
-
expectedVersion: number;
|
|
7
|
-
command: CampaignCommand;
|
|
8
|
-
}
|
|
9
|
-
export type Actor = {
|
|
10
|
-
userId: string;
|
|
11
|
-
tokenId?: never;
|
|
12
|
-
} | {
|
|
13
|
-
tokenId: string;
|
|
14
|
-
userId?: never;
|
|
15
|
-
};
|
|
16
|
-
export type Relationship = {
|
|
17
|
-
kind: "independent";
|
|
18
|
-
targetId?: never;
|
|
19
|
-
} | {
|
|
20
|
-
kind: "known" | "duplicate";
|
|
21
|
-
targetId: string;
|
|
22
|
-
};
|
|
23
|
-
export interface Verification {
|
|
24
|
-
actor: Actor;
|
|
25
|
-
acceptedAt: string;
|
|
26
|
-
findingRevision: number;
|
|
27
|
-
minimumConfirmingRuns: number;
|
|
28
|
-
confirmingReceiptIds: string[];
|
|
29
|
-
}
|
|
30
|
-
export interface Campaign {
|
|
31
|
-
id: string;
|
|
32
|
-
projectId: string;
|
|
33
|
-
version: number;
|
|
34
|
-
targetBugCount: number;
|
|
35
|
-
minimumConfirmingRuns: number;
|
|
36
|
-
state: "awaiting_reports" | "in_progress" | "finished";
|
|
37
|
-
focus: string;
|
|
38
|
-
reason: string;
|
|
39
|
-
createdAt: string;
|
|
40
|
-
lastReportAt: string | null;
|
|
41
|
-
creator: Actor;
|
|
42
|
-
}
|
|
43
|
-
export interface CampaignResult {
|
|
44
|
-
schemaVersion: 1;
|
|
45
|
-
projectId: string;
|
|
46
|
-
campaignId: string;
|
|
47
|
-
commandId: string;
|
|
48
|
-
version: number;
|
|
49
|
-
acceptedAt: string;
|
|
50
|
-
changed: boolean;
|
|
51
|
-
findingId?: string;
|
|
52
|
-
findingRevision?: number;
|
|
53
|
-
verification?: Verification;
|
|
54
|
-
previousMinimumConfirmingRuns?: number;
|
|
55
|
-
dashboardPath?: string;
|
|
56
|
-
}
|
|
57
|
-
export interface FindingData extends Partial<Record<(typeof dataText)[number], string>> {
|
|
58
|
-
title: string;
|
|
59
|
-
rootCauseKey: string;
|
|
60
|
-
classification: (typeof classifications)[number];
|
|
61
|
-
variants?: string[] | null;
|
|
62
|
-
issueReferences?: string[] | null;
|
|
63
|
-
regressionCaseIds?: string[] | null;
|
|
64
|
-
evidence?: Array<{
|
|
65
|
-
receiptId: string;
|
|
66
|
-
path: string;
|
|
67
|
-
}> | null;
|
|
68
|
-
}
|
|
69
|
-
export type CampaignCommand = {
|
|
70
|
-
reason?: string;
|
|
71
|
-
} & ({
|
|
72
|
-
type: "state.report";
|
|
73
|
-
state: "in_progress" | "finished";
|
|
74
|
-
} | {
|
|
75
|
-
type: "receipt.link";
|
|
76
|
-
receiptId: string;
|
|
77
|
-
} | {
|
|
78
|
-
type: "finding.record" | "finding.update";
|
|
79
|
-
findingId: string;
|
|
80
|
-
finding: FindingData;
|
|
81
|
-
invalidateVerification?: boolean;
|
|
82
|
-
} | {
|
|
83
|
-
type: "finding.verify";
|
|
84
|
-
findingId: string;
|
|
85
|
-
} | {
|
|
86
|
-
type: "finding.relate";
|
|
87
|
-
findingId: string;
|
|
88
|
-
relationship: Relationship;
|
|
89
|
-
} | {
|
|
90
|
-
type: "verification.settings.update";
|
|
91
|
-
minimumConfirmingRuns: number;
|
|
92
|
-
reason: string;
|
|
93
|
-
});
|
|
94
|
-
type HistoryCommand = CampaignCommand | {
|
|
95
|
-
type: "campaign.create";
|
|
96
|
-
} | {
|
|
97
|
-
type: "historical.import";
|
|
98
|
-
} | {
|
|
99
|
-
type: "verification.settings.update";
|
|
100
|
-
minimumConfirmingRuns: number;
|
|
101
|
-
reason?: string;
|
|
102
|
-
};
|
|
103
|
-
export interface HistoricalFindingSource {
|
|
104
|
-
importId: string;
|
|
105
|
-
namespace: string;
|
|
106
|
-
sourceId: string;
|
|
107
|
-
digest: string;
|
|
108
|
-
observedAt: string;
|
|
109
|
-
importedAt: string;
|
|
110
|
-
actor: Actor;
|
|
111
|
-
record: unknown;
|
|
112
|
-
}
|
|
113
|
-
export interface Finding {
|
|
114
|
-
import?: HistoricalFindingSource;
|
|
115
|
-
id: string;
|
|
116
|
-
projectId: string;
|
|
117
|
-
campaignId: string;
|
|
118
|
-
revision: number;
|
|
119
|
-
createdAt: string;
|
|
120
|
-
updatedAt: string;
|
|
121
|
-
data: FindingData;
|
|
122
|
-
relationship: Relationship;
|
|
123
|
-
verification: Verification | null;
|
|
124
|
-
}
|
|
125
|
-
export interface FindingDetail {
|
|
126
|
-
campaignVersion: number;
|
|
127
|
-
finding: Finding;
|
|
128
|
-
relatedCampaignId?: string;
|
|
129
|
-
evidence: Array<{
|
|
130
|
-
receiptId: string;
|
|
131
|
-
path: string;
|
|
132
|
-
available: boolean;
|
|
133
|
-
}>;
|
|
134
|
-
}
|
|
135
|
-
export interface FindingSummary extends Pick<Finding, "id" | "campaignId" | "createdAt" | "relationship">, Pick<FindingData, "title" | "rootCauseKey" | "classification"> {
|
|
136
|
-
campaignVersion: number;
|
|
137
|
-
verified: boolean;
|
|
138
|
-
counted: boolean;
|
|
139
|
-
}
|
|
140
|
-
interface LinkedReceipt {
|
|
141
|
-
receiptId: string;
|
|
142
|
-
runIdPreview: string;
|
|
143
|
-
linkedAt: string;
|
|
144
|
-
actor: Actor;
|
|
145
|
-
evidenceExpiredAt: string | null;
|
|
146
|
-
}
|
|
147
|
-
export interface FindingPage {
|
|
148
|
-
items: FindingSummary[];
|
|
149
|
-
bugCount: number;
|
|
150
|
-
campaign?: Campaign;
|
|
151
|
-
campaignVersion?: number;
|
|
152
|
-
nextCursor?: string;
|
|
153
|
-
}
|
|
154
|
-
export type CampaignPage = FindingPage | {
|
|
155
|
-
items: LinkedReceipt[];
|
|
156
|
-
nextCursor?: string;
|
|
157
|
-
} | {
|
|
158
|
-
items: Array<CampaignResult & {
|
|
159
|
-
actor: Actor;
|
|
160
|
-
command: HistoryCommand;
|
|
161
|
-
}>;
|
|
162
|
-
nextCursor?: string;
|
|
163
|
-
};
|
|
164
|
-
export type CampaignRead = "project" | "campaign" | "findings" | "finding" | "receipts" | "history";
|
|
165
|
-
export interface CampaignSelection {
|
|
166
|
-
campaignId?: string;
|
|
167
|
-
findingId?: string;
|
|
168
|
-
findings?: boolean;
|
|
169
|
-
receipts?: boolean;
|
|
170
|
-
history?: boolean;
|
|
171
|
-
rootCauseKey?: string;
|
|
172
|
-
issueReference?: string;
|
|
173
|
-
view?: string;
|
|
174
|
-
limit?: number;
|
|
175
|
-
cursor?: string;
|
|
176
|
-
}
|
|
177
|
-
export type FindingSelection = Omit<CampaignSelection, "findingId" | "receipts" | "history"> & {
|
|
178
|
-
findingId?: never;
|
|
179
|
-
receipts?: false;
|
|
180
|
-
history?: false;
|
|
181
|
-
} & ({
|
|
182
|
-
campaignId: string;
|
|
183
|
-
} | {
|
|
184
|
-
findings: true;
|
|
185
|
-
});
|
|
186
|
-
declare const classifications: readonly ["product_bug", "testkit_failure", "environment_failure", "stale_assertion", "unproven", "intended_behavior", "observation"];
|
|
187
|
-
declare const dataText: readonly ["surface", "severity", "expectedBehavior", "authority", "observedBehavior", "impact", "reproduction", "limitations"];
|
|
188
|
-
export declare function campaignError(field: string, detail: string): Error;
|
|
189
|
-
export declare function requireCloudId(value: unknown, field: string): string;
|
|
190
|
-
export declare function parseCampaignReport(value: unknown, project: string, campaign: string): CampaignReport;
|
|
191
|
-
export declare function parseCampaign(value: unknown, project: string, campaign: string | undefined): Campaign;
|
|
192
|
-
export declare function parseCampaignResult(value: unknown, project: string, campaign: string | undefined, finding?: string): CampaignResult;
|
|
193
|
-
export declare function parseCampaignReportResult(value: unknown, report: CampaignReport): CampaignResult;
|
|
194
|
-
export declare function parseFindingDetail(value: unknown, project: string, campaign: string, id: string): FindingDetail;
|
|
195
|
-
export declare function campaignReadPath(project: string, selection: CampaignSelection): {
|
|
196
|
-
path: string;
|
|
197
|
-
kind: CampaignRead;
|
|
198
|
-
};
|
|
199
|
-
export declare function parseCampaignPage(value: unknown, kind: CampaignRead, project: string, campaign?: string): CampaignPage;
|
|
200
|
-
export {};
|
package/dist/cloud/campaigns.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{isUnknownRecord as k}from"../kernel/unknown-values.js";import{validateHistoricalSourceRecord as K}from"./historical-contract.js";import{attachErrorDiagnostics as j}from"../kernel/error-serialization.js";const A=["product_bug","testkit_failure","environment_failure","stale_assertion","unproven","intended_behavior","observation"],b=["surface","severity","expectedBehavior","authority","observedBehavior","impact","reproduction","limitations"];export function campaignError(t,i){return j(Object.assign(new Error(`${t}: ${i}`),{code:"invalid_campaign_request"}),{source:"local",field:t})}function d(t,i){if(!t)throw campaignError(i,"invalid campaign value")}function c(t,i){return d(k(t),i),t}function I(t,i,e){d(Object.keys(t).every(n=>i.includes(n)),e)}function a(t,i,e=4096,n=!1){return d(typeof t=="string"&&Buffer.byteLength(t)<=e&&!/[\ud800-\udfff]/u.test(t)&&Array.from(t).every(r=>r.charCodeAt(0)>=32||`
|
|
2
|
-
\r `.includes(r))&&(!n||t.trim().length>0),i),t}export function requireCloudId(t,i){return d(typeof t=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(t),i),t}function f(t,i,e=1,n=Number.MAX_SAFE_INTEGER){return d(typeof t=="number"&&Number.isSafeInteger(t)&&t>=e&&t<=n,i),t}function m(t,i,e){d(typeof t=="string"&&i.includes(t),e)}function v(t,i){d(typeof t=="boolean",i)}function l(t,i,e){return d(Array.isArray(t)&&t.length<=e,i),t}function p(t,i,e){requireCloudId(t,e),i!==void 0&&d(t===i,e)}function C(t){const i=c(t,"evidence");return{receiptId:requireCloudId(i.receiptId,"receiptId"),path:a(i.path,"path",4096,!0)}}function R(t){const i=c(t,"relationship");I(i,["kind","targetId"],"relationship"),m(i.kind,["independent","known","duplicate"],"relationship.kind"),i.kind==="independent"?d(i.targetId===void 0,"relationship.targetId"):requireCloudId(i.targetId,"relationship.targetId")}function V(t){const i=c(t,"finding data");I(i,["title","rootCauseKey","classification",...b,"variants","issueReferences","regressionCaseIds","evidence"],"finding data");for(const n of["title","rootCauseKey"])a(i[n],n,256,!0);m(i.classification,A,"classification");for(const n of b)i[n]!==void 0&&a(i[n],n);for(const n of["variants","issueReferences","regressionCaseIds"])for(const r of l(i[n]??[],n,32)){const s=a(r,n,4096,!0);if(n==="regressionCaseIds"&&requireCloudId(s,n),n==="issueReferences"){const o=URL.parse(s);d(o&&["http:","https:"].includes(o.protocol)&&!o.username&&!o.password,n)}}const e=l(i.evidence??[],"evidence",64).map(n=>(I(c(n,"evidence"),["receiptId","path"],"evidence"),JSON.stringify(C(n))));return d(new Set(e).size===e.length,"evidence"),i}function x(t,i=!0){const e=c(t,"command"),n={"state.report":["state"],"receipt.link":["receiptId"],"finding.record":["findingId","finding"],"finding.update":["findingId","finding","invalidateVerification"],"finding.verify":["findingId"],"finding.relate":["findingId","relationship"],"verification.settings.update":["minimumConfirmingRuns"],...i?{}:{"campaign.create":[],"historical.import":[]}},r=a(e.type,"command.type",128,!0);return d(Object.hasOwn(n,r),"command.type"),I(e,["type","reason",...n[r]],"command"),e.reason!==void 0&&a(e.reason,"reason"),r==="state.report"&&(m(e.state,["in_progress","finished"],"state"),e.state==="finished"&&a(e.reason,"reason",4096,!0)),r==="receipt.link"&&requireCloudId(e.receiptId,"receiptId"),r.startsWith("finding.")&&requireCloudId(e.findingId,"findingId"),(r==="finding.record"||r==="finding.update")&&V(e.finding),e.invalidateVerification!==void 0&&v(e.invalidateVerification,"invalidateVerification"),r==="finding.relate"&&(R(e.relationship),d(c(e.relationship,"relationship").targetId!==e.findingId,"relationship.targetId")),r==="verification.settings.update"&&(f(e.minimumConfirmingRuns,"minimumConfirmingRuns",1,64),i&&a(e.reason,"reason",4096,!0)),e}export function parseCampaignReport(t,i,e){const n=c(t,"report");return I(n,["schemaVersion","projectId","campaignId","idempotencyKey","expectedVersion","command"],"report"),d(n.schemaVersion===1,"schemaVersion"),p(n.projectId,i,"projectId"),p(n.campaignId,e,"campaignId"),d(typeof n.idempotencyKey=="string"&&Buffer.byteLength(n.idempotencyKey)<=128&&n.idempotencyKey.trim()&&!n.idempotencyKey.includes("\0")&&!/[\ud800-\udfff]/u.test(n.idempotencyKey),"idempotencyKey"),f(n.expectedVersion,"expectedVersion"),x(n.command),n}function y(t){const i=c(t,"actor");d(i.userId===void 0!=(i.tokenId===void 0),"actor"),requireCloudId(i.userId||i.tokenId,"actor ID")}function w(t){const i=c(t,"verification");y(i.actor),a(i.acceptedAt,"acceptedAt",128,!0),f(i.findingRevision,"findingRevision"),f(i.minimumConfirmingRuns,"minimumConfirmingRuns",1,64);const e=l(i.confirmingReceiptIds,"confirmingReceiptIds",64);for(const n of e)requireCloudId(n,"confirmingReceiptId");d(new Set(e).size===e.length&&e.length>=Number(i.minimumConfirmingRuns),"confirmingReceiptIds")}export function parseCampaign(t,i,e){const n=c(t,"campaign");return p(n.id,e,"campaignId"),p(n.projectId,i,"projectId"),f(n.version,"version"),f(n.targetBugCount,"targetBugCount",1,2147483647),f(n.minimumConfirmingRuns,"minimumConfirmingRuns",1,64),m(n.state,["awaiting_reports","in_progress","finished"],"state"),a(n.focus,"focus"),a(n.reason,"reason"),a(n.createdAt,"createdAt",128,!0),n.lastReportAt!==null&&a(n.lastReportAt,"lastReportAt",128,!0),y(n.creator),n}export function parseCampaignResult(t,i,e,n){const r=c(t,"campaign result");return d(r.schemaVersion===1,"schemaVersion"),p(r.projectId,i,"projectId"),p(r.campaignId,e,"campaignId"),requireCloudId(r.commandId,"commandId"),f(r.version,"version"),a(r.acceptedAt,"acceptedAt",128,!0),v(r.changed,"changed"),(n!==void 0||r.findingId!==void 0||r.findingRevision!==void 0||r.verification!==void 0)&&(p(r.findingId,n,"findingId"),f(r.findingRevision,"findingRevision")),r.verification!==void 0&&w(r.verification),r.previousMinimumConfirmingRuns!==void 0&&f(r.previousMinimumConfirmingRuns,"previousMinimumConfirmingRuns",1,64),r.dashboardPath!==void 0&&a(r.dashboardPath,"dashboardPath",4096,!0),r}export function parseCampaignReportResult(t,i){const e=parseCampaignResult(t,i.projectId,i.campaignId,"findingId"in i.command?i.command.findingId:void 0);return d(e.version===i.expectedVersion+Number(e.changed),"accepted report version"),d(i.command.type!=="finding.verify"||e.changed&&e.verification!==void 0&&e.verification.findingRevision===e.findingRevision,"accepted verification"),e}export function parseFindingDetail(t,i,e,n){const r=c(t,"finding detail");f(r.campaignVersion,"campaignVersion");const s=c(r.finding,"finding");if(p(s.id,n,"findingId"),p(s.projectId,i,"projectId"),p(s.campaignId,e,"campaignId"),f(s.revision,"revision"),a(s.createdAt,"createdAt",128,!0),a(s.updatedAt,"updatedAt",128,!0),s.import!==void 0){const u=c(s.import,"finding import metadata");for(const h of["importId","namespace","sourceId"])a(u[h],h,128,!0);d(typeof u.digest=="string"&&/^[a-f0-9]{64}$/u.test(u.digest),"source digest"),a(u.observedAt,"observedAt",128,!0),a(u.importedAt,"importedAt",128,!0),y(u.actor),K(u.record)}const o=V(s.data);R(s.relationship),s.verification!==null&&w(s.verification),r.relatedCampaignId!==void 0&&requireCloudId(r.relatedCampaignId,"relatedCampaignId");const g=new Set(l(o.evidence,"evidence",64).map(u=>JSON.stringify(C(u))));return l(r.evidence,"evidence availability",64).forEach(u=>{const h=JSON.stringify(C(u));d(g.delete(h),"evidence availability identity"),v(c(u,"evidence").available,"available")}),d(g.size===0,"evidence availability coverage"),r}export function campaignReadPath(t,i){const e=i;if([e.campaignId,e.findingId,e.findings,e.receipts,e.history,e.rootCauseKey,e.issueReference,e.view,e.limit,e.cursor].every(o=>o===void 0||o===!1))return{path:`/api/v1/projects/${encodeURIComponent(t)}/snapshot`,kind:"project"};requireCloudId(t,"projectId"),e.campaignId!==void 0&&requireCloudId(e.campaignId,"campaignId"),e.findingId!==void 0&&requireCloudId(e.findingId,"findingId"),d([e.findingId!==void 0,e.findings,e.receipts,e.history].filter(Boolean).length<=1,"snapshot selectors");const n=e.findingId!==void 0?"finding":e.receipts?"receipts":e.history?"history":"findings";d(e.campaignId||n==="findings"&&e.findings,"campaign selector");const r=new URLSearchParams;e.limit!==void 0&&r.set("limit",String(f(e.limit,"limit",1,n==="history"?20:100))),e.cursor!==void 0&&r.set("cursor",a(e.cursor,"cursor",1024,!0)),n==="finding"&&d(!r.size,"finding pagination");for(const[o,g]of[["rootCauseKey",e.rootCauseKey],["issueReference",e.issueReference],["view",e.view]])g!==void 0&&(d(n==="findings",o),o==="view"&&m(g,["all","counted","secondary"],"view"),r.set(o,a(g,o,o==="rootCauseKey"?256:4096)));return{path:`${`/api/v1/projects/${t}/campaigns${e.campaignId?`/${e.campaignId}`:""}`}/${n==="finding"?`findings/${e.findingId}`:n}${r.size?`?${r}`:""}`,kind:n}}export function parseCampaignPage(t,i,e,n){const r=c(t,"campaign page");if(r.nextCursor!==void 0&&a(r.nextCursor,"nextCursor",1024,!0),i==="findings"&&(f(r.bugCount,"bugCount",0),n!==void 0||r.campaign!==void 0||r.campaignVersion!==void 0)){const s=parseCampaign(r.campaign,e,n);d(f(r.campaignVersion,"campaignVersion")===s.version,"campaignVersion")}for(const s of l(r.items,"items",i==="history"?20:100)){const o=c(s,"page item");i==="history"?(parseCampaignResult(o,e,n),y(o.actor),x(o.command,!1)):i==="receipts"?(requireCloudId(o.receiptId,"receiptId"),a(o.runIdPreview,"runIdPreview",1024),a(o.linkedAt,"linkedAt",128,!0),y(o.actor),o.evidenceExpiredAt!==null&&a(o.evidenceExpiredAt,"evidenceExpiredAt",128,!0)):(requireCloudId(o.id,"findingId"),p(o.campaignId,n,"campaignId"),f(o.campaignVersion,"campaignVersion"),a(o.title,"title",256,!0),a(o.rootCauseKey,"rootCauseKey",256,!0),m(o.classification,A,"classification"),v(o.verified,"verified"),v(o.counted,"counted"),R(o.relationship),a(o.createdAt,"createdAt",128,!0))}return r}
|
package/dist/cloud/client.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { type ResponseDocument } from "./transport.js";
|
|
2
|
-
import { type Campaign, type CampaignResult, type CampaignReport, type CampaignSelection, type FindingDetail, type FindingPage, type FindingSelection, type CampaignPage } from "./campaigns.js";
|
|
3
|
-
import { type CloudProjectSnapshot } from "./historical-contract.js";
|
|
4
|
-
import type { VerifiedRunBundleUpload } from "../evidence/index.js";
|
|
5
|
-
export interface CloudClientOptions {
|
|
6
|
-
origin: string;
|
|
7
|
-
projectId: string;
|
|
8
|
-
token: string;
|
|
9
|
-
}
|
|
10
|
-
export type CloudReceipt = ReturnType<typeof parseCloudReceipt>;
|
|
11
|
-
export declare class CloudResponseError extends Error {
|
|
12
|
-
readonly code: null | string;
|
|
13
|
-
readonly status: number;
|
|
14
|
-
constructor(status: number, message: string, code?: null | string);
|
|
15
|
-
}
|
|
16
|
-
export declare class CloudClient {
|
|
17
|
-
private readonly responses;
|
|
18
|
-
readonly origin: URL;
|
|
19
|
-
readonly projectId: string;
|
|
20
|
-
private readonly token;
|
|
21
|
-
constructor(options: Readonly<CloudClientOptions>, responses?: {
|
|
22
|
-
decodeJSON?: (text: string) => unknown;
|
|
23
|
-
maxResponseBytes?: number;
|
|
24
|
-
});
|
|
25
|
-
publish(source: VerifiedRunBundleUpload, onProgress?: (message: string) => void): Promise<CloudReceipt>;
|
|
26
|
-
apply(envelope: unknown): Promise<unknown>;
|
|
27
|
-
campaign(id: string): Promise<Campaign>;
|
|
28
|
-
report(report: CampaignReport): Promise<CampaignResult>;
|
|
29
|
-
snapshot(): Promise<CloudProjectSnapshot>;
|
|
30
|
-
snapshot(selection: CampaignSelection & {
|
|
31
|
-
findingId: string;
|
|
32
|
-
campaignId: string;
|
|
33
|
-
}): Promise<FindingDetail>;
|
|
34
|
-
snapshot(selection: FindingSelection): Promise<FindingPage>;
|
|
35
|
-
snapshot(selection: CampaignSelection): Promise<CloudProjectSnapshot | FindingDetail | CampaignPage>;
|
|
36
|
-
finding(campaignId: string, findingId: string): Promise<FindingDetail>;
|
|
37
|
-
receipt(id: string): Promise<CloudReceipt>;
|
|
38
|
-
private decodeCampaign;
|
|
39
|
-
private requestJSON;
|
|
40
|
-
private uploadFile;
|
|
41
|
-
private target;
|
|
42
|
-
}
|
|
43
|
-
export declare function parseResponse(response: ResponseDocument, decodeJSON?: (text: string) => unknown): unknown;
|
|
44
|
-
export declare function parseCloudReceipt(value: unknown): {
|
|
45
|
-
acceptedAt: string;
|
|
46
|
-
commitSha: string;
|
|
47
|
-
decision: "hold" | "ineligible" | "ship";
|
|
48
|
-
decisionReasons: {
|
|
49
|
-
ruleId: string;
|
|
50
|
-
message: string;
|
|
51
|
-
}[];
|
|
52
|
-
fullRun: boolean;
|
|
53
|
-
id: string;
|
|
54
|
-
manifestDigest: string;
|
|
55
|
-
policyId: string;
|
|
56
|
-
policyRevision: number;
|
|
57
|
-
projectId: string;
|
|
58
|
-
regressions: {
|
|
59
|
-
fixed: number;
|
|
60
|
-
known: number;
|
|
61
|
-
new: number;
|
|
62
|
-
returning: number;
|
|
63
|
-
};
|
|
64
|
-
repository: string;
|
|
65
|
-
runId: string;
|
|
66
|
-
runStatus: string;
|
|
67
|
-
testkitVersion: string;
|
|
68
|
-
};
|
package/dist/cloud/client.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{request as f,invalidResponse as o}from"./transport.js";import{isUnknownRecord as p}from"../kernel/unknown-values.js";import{withUploadArchive as w}from"./archive.js";import{MAX_CLOUD_ARCHIVE_BYTES as y}from"./archive-contract.js";import{attachErrorDiagnostics as I}from"../kernel/error-serialization.js";import{campaignReadPath as C,parseCampaign as R,parseCampaignPage as S,parseCampaignReportResult as j,parseFindingDetail as m}from"./campaigns.js";import T from"node:fs";import{parseProjectSnapshot as U}from"./historical-contract.js";export class CloudResponseError extends Error{code;status;constructor(e,r,i=null){super(r),this.name="CloudResponseError",this.code=i,this.status=e}}export class CloudClient{responses;origin;projectId;token;constructor(e,r={}){this.responses=r;const i=new URL(e.origin);if(!["http:","https:"].includes(i.protocol))throw new Error("Testkit Cloud URL must use HTTP or HTTPS");if(i.username||i.password)throw new Error("Testkit Cloud URL must not contain credentials");if(i.pathname!=="/"||i.search||i.hash)throw new Error("Testkit Cloud URL must be an origin without a path, query, or fragment");if(!e.projectId||!e.token)throw new Error("Testkit Cloud project ID and token are required");this.origin=i,this.projectId=e.projectId,this.token=e.token}async publish(e,r=()=>{}){const i=b(await this.requestJSON("POST",`/api/v1/projects/${encodeURIComponent(this.projectId)}/publications`,{evidenceFormat:"zip-v1",idempotencyKey:`bundle:${e.manifest.digest}`,manifest:e.manifest,projectId:this.projectId}));if(i.status==="rejected")throw new Error("Testkit Cloud publication was rejected");if(i.status==="pending"){if(!i.archive)throw new Error("This Cloud server or pending publication does not support zip-v1. Upgrade Cloud before publishing with this Testkit version.");const{url:s,maxBytes:u}=i.archive;this.target(s),r(`Compressing ${String(e.files.length)} evidence files for Cloud...
|
|
2
|
-
`),await w(e,u,async(a,h)=>{r(`Uploading ${String(h)} compressed bytes to Cloud...
|
|
3
|
-
`),await this.uploadFile(s,a,h)}),r(`Cloud is verifying and accepting the run...
|
|
4
|
-
`)}const n=parseCloudReceipt(await this.requestJSON("POST",i.completeUrl));if(n.projectId!==this.projectId||n.runId!==e.runId||n.manifestDigest!==e.manifest.digest)throw new Error("Testkit Cloud receipt does not match the published bundle");return n}async apply(e){return this.requestJSON("POST",`/api/v1/projects/${encodeURIComponent(this.projectId)}/mutations`,e)}async campaign(e){const r=`/api/v1/projects/${encodeURIComponent(this.projectId)}/campaigns/${encodeURIComponent(e)}`;return this.decodeCampaign(()=>this.requestJSON("GET",r),i=>R(i,this.projectId,e))}async report(e){const r=`/api/v1/projects/${encodeURIComponent(e.projectId)}/campaigns/${encodeURIComponent(e.campaignId)}/reports`;return this.decodeCampaign(()=>this.requestJSON("POST",r,e),i=>j(i,e))}async snapshot(e={}){const{path:r,kind:i}=C(this.projectId,e);return i==="project"?U(await this.requestJSON("GET",r),this.projectId):this.decodeCampaign(()=>this.requestJSON("GET",r),n=>e.findingId!==void 0&&e.campaignId!==void 0?m(n,this.projectId,e.campaignId,e.findingId):S(n,i,this.projectId,e.campaignId))}async finding(e,r){return this.decodeCampaign(()=>this.requestJSON("GET",`/api/v1/projects/${encodeURIComponent(this.projectId)}/campaigns/${encodeURIComponent(e)}/findings/${encodeURIComponent(r)}`),i=>m(i,this.projectId,e,r))}async receipt(e){const r=await this.requestJSON("GET",`/api/v1/receipts/${encodeURIComponent(e)}`);if(!p(r))throw o("receipt view");const i=parseCloudReceipt(r.receipt);if(i.id!==e||i.projectId!==this.projectId)throw o("receipt identity");return i}async decodeCampaign(e,r){const i=await e();try{return r(i)}catch(n){throw o(`campaign response: ${n instanceof Error?n.message:String(n)}`)}}async requestJSON(e,r,i){const n=i===void 0?null:Buffer.from(JSON.stringify(i)),s=await f({body:n,headers:{Accept:"application/json",Authorization:`Bearer ${this.token}`,...n?{"Content-Length":String(n.length),"Content-Type":"application/json"}:{}},method:e,timeoutMs:3e4,maxResponseBytes:this.responses.maxResponseBytes,url:this.target(r)});return parseResponse(s,this.responses.decodeJSON)}async uploadFile(e,r,i){const n=this.target(e),s=T.createReadStream(r),u=new Promise(a=>s.once("close",a));try{const a=await f({body:s,headers:{Authorization:`Bearer ${this.token}`,"Content-Length":String(i),"Content-Type":"application/zip"},method:"PUT",timeoutMs:6e5,url:n});if(a.status<200||a.status>=300)throw g(a)}finally{s.destroy(),await u}}target(e){if(!e)throw new Error("Testkit Cloud returned an empty request URL");const r=new URL(e,this.origin);if(r.origin!==this.origin.origin||r.username||r.password)throw new Error("Testkit Cloud returned a URL outside its configured origin");return r}}export function parseResponse(t,e=JSON.parse){if(t.status<200||t.status>=300)throw g(t);if(t.body.length!==0)try{return e(new TextDecoder("utf-8",{fatal:!0}).decode(t.body))}catch{throw o("JSON response")}}function g(t){let e=null;const r={source:"cloud"};let i=t.body.toString("utf8").trim();try{const n=JSON.parse(i);if(p(n)){typeof n.code=="string"&&(e=n.code),typeof n.detail=="string"&&(i=n.detail);for(const s of["field","required","eligible","detail"])(typeof n[s]=="string"||typeof n[s]=="number"&&Number.isSafeInteger(n[s]))&&(r[s]=n[s])}}catch{}return I(new CloudResponseError(t.status,i||`Testkit Cloud returned HTTP ${String(t.status)}`,e),r)}function b(t){if(!p(t))throw o("publication plan");const e=t.status;if(!l(e,["accepted","pending","rejected"]))throw o("publication status");let r=null;if(t.archive!==void 0&&t.archive!==null){if(!p(t.archive)||t.archive.format!=="zip-v1")throw o("archive format");const i=d(t.archive.maxBytes,"archive byte limit");if(i===0)throw o("archive byte limit");r={url:c(t.archive.url,"archive URL"),maxBytes:Math.min(i,y)}}return{completeUrl:c(t.completeUrl,"completion URL"),status:e,archive:r}}export function parseCloudReceipt(t){if(!p(t))throw o("receipt");const e=t.decision;if(!l(e,["hold","ineligible","ship"]))throw o("receipt decision");if(!Array.isArray(t.decisionReasons))throw o("receipt decision reasons");const r=t.decisionReasons.map(n=>{if(!p(n))throw o("receipt decision reason");return{ruleId:c(n.ruleId,"receipt decision rule ID"),message:c(n.message,"receipt decision message")}}),i=d(t.policyRevision,"receipt policy revision");if(i===0)throw o("receipt policy revision");if(!p(t.regressions))throw o("receipt regressions");return{acceptedAt:c(t.acceptedAt,"receipt acceptance time"),commitSha:c(t.commitSha,"receipt commit SHA",!0),decision:e,decisionReasons:r,fullRun:k(t.fullRun,"receipt full-run flag"),id:c(t.id,"receipt ID"),manifestDigest:c(t.manifestDigest,"receipt manifest digest"),policyId:c(t.policyId,"receipt policy ID"),policyRevision:i,projectId:c(t.projectId,"receipt project ID"),regressions:{fixed:d(t.regressions.fixed,"fixed regression count"),known:d(t.regressions.known,"known regression count"),new:d(t.regressions.new,"new regression count"),returning:d(t.regressions.returning,"returning regression count")},repository:c(t.repository,"receipt repository"),runId:c(t.runId,"receipt run ID"),runStatus:c(t.runStatus,"receipt run status"),testkitVersion:c(t.testkitVersion,"receipt Testkit version")}}function l(t,e){return typeof t=="string"&&e.includes(t)}function k(t,e){if(typeof t!="boolean")throw o(e);return t}function d(t,e){if(!Number.isSafeInteger(t)||t<0)throw o(e);return t}function c(t,e,r=!1){if(typeof t!="string"||!r&&t.length===0)throw o(e);return t}
|
package/dist/cloud/download.d.ts
DELETED
package/dist/cloud/download.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{open as h,link as m,rm as p}from"node:fs/promises";import{createHash as u,randomUUID as b}from"node:crypto";import{request as d,invalidResponse as l}from"./transport.js";import{parseResponse as A}from"./client.js";export async function downloadVerifiedArtifact(a,o,w,t){if(!Number.isSafeInteger(t.bytes)||t.bytes<0||!/^[a-f0-9]{64}$/u.test(t.sha256))throw new Error("Artifact download requires an exact byte count and SHA-256");const i=`${w}.${b()}.partial`,s=await h(i,"wx",384),c=u("sha256");let n=0;try{const f=await d({body:null,headers:{Authorization:`Bearer ${o}`,"Accept-Encoding":"identity"},method:"GET",timeoutMs:6e5,url:a,onResponseChunk:async e=>{if(n+=e.byteLength,n>t.bytes)throw l("artifact exceeds expected bytes");c.update(e);let r=0;for(;r<e.length;){const y=await s.write(e,r,e.length-r);if(!y.bytesWritten)throw new Error("Artifact write made no progress");r+=y.bytesWritten}}});if((f.status<200||f.status>=300)&&A(f),n!==t.bytes||c.digest("hex")!==t.sha256)throw l("artifact byte count or SHA-256");await s.close(),await publishArtifactFile(i,w)}finally{await s.close(),await p(i,{force:!0})}}export async function publishArtifactFile(a,o){await m(a,o)}
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import type { Actor, FindingData, Relationship } from "./campaigns.js";
|
|
2
|
-
export interface HistoricalSource {
|
|
3
|
-
kind: "run" | "case" | "finding";
|
|
4
|
-
id: string;
|
|
5
|
-
digest: string;
|
|
6
|
-
}
|
|
7
|
-
export interface HistoricalBegin {
|
|
8
|
-
schemaVersion: 1;
|
|
9
|
-
idempotencyKey: string;
|
|
10
|
-
namespace: string;
|
|
11
|
-
inventoryDigest: string;
|
|
12
|
-
inventory: HistoricalSource[];
|
|
13
|
-
}
|
|
14
|
-
export interface HistoricalImport {
|
|
15
|
-
id: string;
|
|
16
|
-
projectId: string;
|
|
17
|
-
campaignId: string;
|
|
18
|
-
namespace: string;
|
|
19
|
-
inventoryDigest: string;
|
|
20
|
-
actor: Actor;
|
|
21
|
-
createdAt: string;
|
|
22
|
-
completedAt?: string;
|
|
23
|
-
total: number;
|
|
24
|
-
}
|
|
25
|
-
export interface HistoricalArtifact {
|
|
26
|
-
path: string;
|
|
27
|
-
originalPath: string;
|
|
28
|
-
originalSha256: string;
|
|
29
|
-
originalBytes: number;
|
|
30
|
-
transformation?: string;
|
|
31
|
-
}
|
|
32
|
-
export interface HistoricalManifest {
|
|
33
|
-
algorithm: "sha256";
|
|
34
|
-
schemaVersion: 1 | 2;
|
|
35
|
-
createdAt: string;
|
|
36
|
-
runId: string;
|
|
37
|
-
digest: string;
|
|
38
|
-
files: Array<{
|
|
39
|
-
path: string;
|
|
40
|
-
bytes: number;
|
|
41
|
-
sha256: string;
|
|
42
|
-
}>;
|
|
43
|
-
redaction?: unknown;
|
|
44
|
-
storage?: unknown;
|
|
45
|
-
}
|
|
46
|
-
export interface HistoricalEvidence {
|
|
47
|
-
schemaVersion: 1;
|
|
48
|
-
source: HistoricalSource;
|
|
49
|
-
sourceRecord: unknown;
|
|
50
|
-
manifest: HistoricalManifest;
|
|
51
|
-
artifacts: HistoricalArtifact[];
|
|
52
|
-
evidenceFormat?: "zip-v1";
|
|
53
|
-
}
|
|
54
|
-
export interface HistoricalCase {
|
|
55
|
-
classification: "untriaged" | "regression" | "flaky" | "expected" | "quarantined";
|
|
56
|
-
engineId: string;
|
|
57
|
-
failureKey: string;
|
|
58
|
-
fingerprint: string;
|
|
59
|
-
firstSeenAt: string;
|
|
60
|
-
id: string;
|
|
61
|
-
lastSeenAt: string;
|
|
62
|
-
path: string;
|
|
63
|
-
profileId: string;
|
|
64
|
-
service: string;
|
|
65
|
-
state: "active" | "resolved" | "fixed_pending_verification";
|
|
66
|
-
testType: string;
|
|
67
|
-
title: string;
|
|
68
|
-
version?: number;
|
|
69
|
-
issueNumber?: number;
|
|
70
|
-
issueRepository?: string;
|
|
71
|
-
}
|
|
72
|
-
export interface HistoricalRecord {
|
|
73
|
-
source: HistoricalSource;
|
|
74
|
-
sourceRecord: unknown;
|
|
75
|
-
observedAt: string;
|
|
76
|
-
finding?: FindingData;
|
|
77
|
-
relationship?: Relationship;
|
|
78
|
-
verify?: boolean;
|
|
79
|
-
case?: HistoricalCase;
|
|
80
|
-
exception?: string;
|
|
81
|
-
}
|
|
82
|
-
export interface HistoricalBatch {
|
|
83
|
-
schemaVersion: 1;
|
|
84
|
-
idempotencyKey: string;
|
|
85
|
-
expectedVersion: number;
|
|
86
|
-
records: HistoricalRecord[];
|
|
87
|
-
}
|
|
88
|
-
export interface HistoricalOutcome extends HistoricalSource {
|
|
89
|
-
status: "pending" | "accepted" | "reused" | "rejected" | "unmapped";
|
|
90
|
-
cloudId?: string;
|
|
91
|
-
detail?: string;
|
|
92
|
-
required?: number;
|
|
93
|
-
eligible?: number;
|
|
94
|
-
evidenceAvailable?: boolean;
|
|
95
|
-
}
|
|
96
|
-
export interface HistoricalBatchResult {
|
|
97
|
-
importId: string;
|
|
98
|
-
version: number;
|
|
99
|
-
acceptedAt: string;
|
|
100
|
-
rejected: boolean;
|
|
101
|
-
items: HistoricalOutcome[];
|
|
102
|
-
}
|
|
103
|
-
export interface HistoricalPage {
|
|
104
|
-
import: HistoricalImport;
|
|
105
|
-
counts: Record<string, Record<string, number>>;
|
|
106
|
-
items: HistoricalOutcome[];
|
|
107
|
-
nextCursor?: string;
|
|
108
|
-
}
|
|
109
|
-
export interface HistoricalUploadPlan {
|
|
110
|
-
completeUrl: string;
|
|
111
|
-
publicationId: string;
|
|
112
|
-
reused: boolean;
|
|
113
|
-
status: "pending" | "accepted" | "rejected";
|
|
114
|
-
uploads: Array<{
|
|
115
|
-
bytes: number;
|
|
116
|
-
index: number;
|
|
117
|
-
path: string;
|
|
118
|
-
sha256: string;
|
|
119
|
-
url: string;
|
|
120
|
-
}>;
|
|
121
|
-
archive?: {
|
|
122
|
-
format: "zip-v1";
|
|
123
|
-
url: string;
|
|
124
|
-
maxBytes: number;
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
export interface HistoricalReceipt {
|
|
128
|
-
kind: "historical";
|
|
129
|
-
baseline: boolean;
|
|
130
|
-
baselineBranch: string;
|
|
131
|
-
branch: string;
|
|
132
|
-
commitSha: string;
|
|
133
|
-
decisionReasons: Array<{
|
|
134
|
-
ruleId: string;
|
|
135
|
-
message: string;
|
|
136
|
-
}> | null;
|
|
137
|
-
fullRun: boolean;
|
|
138
|
-
pullRequest: number | null;
|
|
139
|
-
regressions: {
|
|
140
|
-
fixed: number;
|
|
141
|
-
known: number;
|
|
142
|
-
new: number;
|
|
143
|
-
returning: number;
|
|
144
|
-
};
|
|
145
|
-
id: string;
|
|
146
|
-
projectId: string;
|
|
147
|
-
runId: string;
|
|
148
|
-
manifestDigest: string;
|
|
149
|
-
acceptedAt: string;
|
|
150
|
-
repository: string;
|
|
151
|
-
runStatus: string;
|
|
152
|
-
testkitVersion: string;
|
|
153
|
-
tokenId: string;
|
|
154
|
-
historical: {
|
|
155
|
-
importId: string;
|
|
156
|
-
sourceId: string;
|
|
157
|
-
sourceDigest: string;
|
|
158
|
-
manifestVersion: 1 | 2;
|
|
159
|
-
run: Record<string, unknown>;
|
|
160
|
-
sourceRecord: unknown;
|
|
161
|
-
artifacts: Array<HistoricalArtifact & {
|
|
162
|
-
originalVerified: boolean;
|
|
163
|
-
}>;
|
|
164
|
-
};
|
|
165
|
-
[key: string]: unknown;
|
|
166
|
-
}
|
|
167
|
-
export interface HistoricalCaseObservation {
|
|
168
|
-
importId: string;
|
|
169
|
-
sourceId: string;
|
|
170
|
-
observedAt: string;
|
|
171
|
-
importedAt: string;
|
|
172
|
-
actorTokenId: string;
|
|
173
|
-
sourceRecord: unknown;
|
|
174
|
-
case: HistoricalCase;
|
|
175
|
-
}
|
|
176
|
-
export interface HistoricalCaseView extends Omit<HistoricalCase, "state" | "version"> {
|
|
177
|
-
state: "active" | "resolved" | "historical";
|
|
178
|
-
version: number;
|
|
179
|
-
historical?: HistoricalCaseObservation;
|
|
180
|
-
}
|
|
181
|
-
export interface HistoricalCaseEvent {
|
|
182
|
-
id: string;
|
|
183
|
-
actor: string;
|
|
184
|
-
appliedAt: string;
|
|
185
|
-
commandType: string;
|
|
186
|
-
state: string;
|
|
187
|
-
classification: string;
|
|
188
|
-
issueRepository: string;
|
|
189
|
-
issueNumber: number;
|
|
190
|
-
historical?: HistoricalCaseObservation;
|
|
191
|
-
}
|
|
192
|
-
export interface HistoricalCasePage {
|
|
193
|
-
items: HistoricalCaseView[];
|
|
194
|
-
nextCursor?: string;
|
|
195
|
-
}
|
|
196
|
-
export interface HistoricalCaseHistoryPage {
|
|
197
|
-
items: HistoricalCaseEvent[];
|
|
198
|
-
nextCursor?: string;
|
|
199
|
-
}
|
|
200
|
-
export declare const HISTORICAL_BODY_LIMIT: number;
|
|
201
|
-
export declare const HISTORICAL_SOURCE_LIMIT: number;
|
|
202
|
-
export declare function validateHistoricalSourceRecord(value: unknown, expectedDigest?: string): void;
|
|
203
|
-
export declare function parseHistoricalResponse(text: string): unknown;
|
|
204
|
-
export declare function validateHistoricalBegin(input: unknown): asserts input is HistoricalBegin;
|
|
205
|
-
export declare function validateHistoricalBatch(input: unknown): asserts input is HistoricalBatch;
|
|
206
|
-
export declare function parseHistoricalImport(value: unknown, project: string, campaign: string, id?: string): HistoricalImport;
|
|
207
|
-
export declare function parseHistoricalBatchResult(value: unknown, importId: string, command: HistoricalBatch): HistoricalBatchResult;
|
|
208
|
-
export declare function parseHistoricalPage(value: unknown, project: string, campaign: string, id: string, limit?: number): HistoricalPage;
|
|
209
|
-
export declare function parseHistoricalUploadPlan(value: unknown, evidence: HistoricalEvidence): HistoricalUploadPlan;
|
|
210
|
-
export declare function validateHistoricalEvidence(input: unknown): asserts input is HistoricalEvidence;
|
|
211
|
-
export declare function parseHistoricalReceipt(value: unknown, project: string, expected?: {
|
|
212
|
-
id?: string;
|
|
213
|
-
importId?: string;
|
|
214
|
-
evidence?: HistoricalEvidence;
|
|
215
|
-
reused?: boolean;
|
|
216
|
-
}): HistoricalReceipt;
|
|
217
|
-
export declare function parseHistoricalCases(value: unknown, limit?: number): HistoricalCasePage;
|
|
218
|
-
export declare function parseHistoricalCaseHistory(value: unknown, limit?: number): HistoricalCaseHistoryPage;
|
|
219
|
-
export interface CloudProjectSnapshot {
|
|
220
|
-
projectId: string;
|
|
221
|
-
version: number;
|
|
222
|
-
cases: HistoricalCaseView[];
|
|
223
|
-
}
|
|
224
|
-
export declare function parseProjectSnapshot(value: unknown, projectId: string): CloudProjectSnapshot;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{isUnknownRecord as H}from"../kernel/unknown-values.js";import{invalidResponse as _}from"./transport.js";import{MAX_CLOUD_ARCHIVE_BYTES as q}from"./archive-contract.js";import{canonicalHistoricalJson as S,historicalDigest as V,HistoricalJsonNumber as w,parseHistoricalJson as O}from"./historical-json.js";const D=["run","case","finding"],B=["pending","accepted","reused","rejected","unmapped"];export const HISTORICAL_BODY_LIMIT=2*1024**2,HISTORICAL_SOURCE_LIMIT=128*1024;function s(i,e){if(!i)throw _(`historical ${e}`)}function c(i,e){return s(H(i),e),i}function a(i,e,t=4096,n=!1){return s(typeof i=="string"&&(n||i.trim().length>0)&&Buffer.byteLength(i)<=t&&!i.includes("\0"),e),i}function m(i,e,t=0,n=Number.MAX_SAFE_INTEGER){return s(typeof i=="number"&&Number.isSafeInteger(i)&&i>=t&&i<=n,e),i}function v(i,e,t){s(typeof i=="string"&&e.includes(i),t)}function A(i,e){s(typeof i=="boolean",e)}function I(i,e){s(typeof i=="string"&&/^[a-f0-9]{64}$/.test(i),e)}function g(i,e){const t=a(i,e,128);s(/^\d{4}-\d\d-\d\dT/.test(t)&&Number.isFinite(Date.parse(t)),e)}function y(i,e,t,n=0){return s(Array.isArray(i)&&i.length>=n&&i.length<=t,e),i}function L(i){const e=c(i,"actor");s(e.userId===void 0!=(e.tokenId===void 0),"actor identity"),a(e.userId??e.tokenId,"actor ID",128)}function k(i){const e=c(i,"source");return v(e.kind,D,"source.kind"),a(e.id,"source.id",128),I(e.digest,"source.digest"),e}function R(i){s(new Set(i.map(e=>`${e.kind}\0${e.id}`)).size===i.length,"duplicate source identity")}export function validateHistoricalSourceRecord(i,e){c(i,"source record"),s(!(i instanceof w),"source record must be an object"),s(Buffer.byteLength(S(i))<=HISTORICAL_SOURCE_LIMIT,"source record exceeds 128 KiB"),e!==void 0&&s(V(i)===e,"source record digest")}export function parseHistoricalResponse(i){function e(t,n=!1){if(n)return t;if(t instanceof w){const o=Number(t.lexeme);return s(Number.isFinite(o)&&(!Number.isInteger(o)||Number.isSafeInteger(o)),"unsafe response number"),o}return Array.isArray(t)?t.map(o=>e(o)):H(t)?Object.fromEntries(Object.entries(t).map(([o,r])=>[o,e(r,o==="sourceRecord"||o==="record")])):t}return e(O(i,{maxBytes:32*1024**2}))}export function validateHistoricalBegin(i){const e=c(i,"begin request");s(e.schemaVersion===1,"schemaVersion"),a(e.idempotencyKey,"idempotencyKey",128),a(e.namespace,"namespace",128);const t=y(e.inventory,"inventory",1e4,1).map(k);R(t),I(e.inventoryDigest,"inventoryDigest"),s(V(e.inventory)===e.inventoryDigest,"inventory digest")}export function validateHistoricalBatch(i){const e=c(i,"batch request");s(e.schemaVersion===1,"schemaVersion"),a(e.idempotencyKey,"idempotencyKey",128),m(e.expectedVersion,"expectedVersion",1);const t=y(e.records,"records",25,1).map(n=>{const o=c(n,"record"),r=k(o.source);return s(r.kind!=="run","batch source kind"),validateHistoricalSourceRecord(o.sourceRecord,r.digest),g(o.observedAt,"observedAt"),o.verify!==void 0&&A(o.verify,"verify"),o.exception!==void 0&&a(o.exception,"exception"),r});R(t)}export function parseHistoricalImport(i,e,t,n){const o=c(i,"import");return a(o.id,"import.id",128),s(n===void 0||o.id===n,"import identity"),s(o.projectId===e&&o.campaignId===t,"project/campaign identity"),a(o.namespace,"namespace",128),I(o.inventoryDigest,"inventoryDigest"),L(o.actor),g(o.createdAt,"createdAt"),o.completedAt!==void 0&&g(o.completedAt,"completedAt"),m(o.total,"total",1,1e4),o}function $(i){const e=c(i,"outcome");k(e),v(e.status,B,"outcome status"),e.cloudId!==void 0&&a(e.cloudId,"cloudId",1024),e.detail!==void 0&&a(e.detail,"detail",65536,!0);for(const t of["required","eligible"])e[t]!==void 0&&m(e[t],t);return e.evidenceAvailable!==void 0&&(s(e.kind==="run","evidence availability kind"),A(e.evidenceAvailable,"evidenceAvailable")),(e.status==="accepted"||e.status==="reused")&&a(e.cloudId,"accepted cloudId",1024),e}export function parseHistoricalBatchResult(i,e,t){const n=c(i,"batch result");s(n.importId===e,"batch import identity"),m(n.version,"version",1),g(n.acceptedAt,"acceptedAt"),A(n.rejected,"rejected");const o=y(n.items,"batch items",25,1).map($);R(o);const r=new Map(t.records.map(d=>[`${d.source.kind}\0${d.source.id}`,d.source.digest]));s(o.length===r.size,"batch outcome coverage");for(const d of o)s(r.get(`${d.kind}\0${d.id}`)===d.digest,"batch outcome identity");return s(n.rejected?n.version===t.expectedVersion:n.version===t.expectedVersion||n.version===t.expectedVersion+1,"batch version"),n.rejected||s(o.every(d=>["accepted","reused"].includes(d.status)),"accepted batch statuses"),n}function j(i,e){i.nextCursor!==void 0&&a(i.nextCursor,"nextCursor",1024);const t=y(i.items,"page items",e);return s(i.nextCursor===void 0||t.length>0,"empty page with cursor"),t}export function parseHistoricalPage(i,e,t,n,o=100){const r=c(i,"page"),d=parseHistoricalImport(r.import,e,t,n),u=j(r,o).map($);R(u);const h=c(r.counts,"counts");let p=0;for(const[f,l]of Object.entries(h)){v(f,D,"count kind");for(const[b,x]of Object.entries(c(l,"kind counts")))v(b,B,"count status"),p+=m(x,"count",0,1e4)}s(p===d.total,"count total");for(const f of u)s(m(c(h[f.kind],"item kind counts")[f.status],"item status count",1)>=u.filter(l=>l.kind===f.kind&&l.status===f.status).length,"page status counts");return r}export function parseHistoricalUploadPlan(i,e){const t=c(i,"upload plan");a(t.completeUrl,"completeUrl"),a(t.publicationId,"publicationId",128),A(t.reused,"reused"),v(t.status,["pending","accepted","rejected"],"upload status");const n=new Set;for(const o of y(t.uploads,"uploads",1e4)){const r=c(o,"upload"),d=m(r.index,"upload index",0,e.manifest.files.length-1),u=e.manifest.files[d];s(r.path===u.path&&r.bytes===u.bytes&&r.sha256===u.sha256,"upload manifest identity"),s(!n.has(u.path),"duplicate upload path"),n.add(u.path),a(r.url,"upload URL")}if(t.archive!==void 0){const o=c(t.archive,"archive");s(o.format==="zip-v1","archive format"),a(o.url,"archive URL"),m(o.maxBytes,"archive limit",1,q)}return t}function N(i,e=!1){const t=c(i,"artifact");a(t.path,"artifact path"),a(t.originalPath,"originalPath",1024),I(t.originalSha256,"originalSha256"),m(t.originalBytes,"originalBytes"),t.transformation!==void 0&&a(t.transformation,"transformation"),e&&(A(t.originalVerified,"originalVerified"),s(t.originalVerified===!t.transformation,"artifact original verification"))}export function validateHistoricalEvidence(i){const e=c(i,"evidence request");s(e.schemaVersion===1,"schemaVersion");const t=k(e.source);s(t.kind==="run","evidence source kind"),validateHistoricalSourceRecord(e.sourceRecord,t.digest);const n=c(e.manifest,"manifest");s(n.schemaVersion===1||n.schemaVersion===2,"manifest schemaVersion"),s(n.algorithm==="sha256","manifest algorithm"),I(n.digest,"manifest digest"),a(n.runId,"runId",1024),g(n.createdAt,"manifest createdAt");const o=y(n.files,"manifest files",1e4,1),r=new Set;for(const d of o){const u=c(d,"manifest file"),h=a(u.path,"manifest file path");s(!h.startsWith("/")&&!h.includes("\\")&&!h.split("/").some(p=>["",".",".."].includes(p)),"manifest relative path"),s(!r.has(h),"manifest duplicate path"),r.add(h),m(u.bytes,"manifest file bytes",0,2*1024**3),I(u.sha256,"manifest file sha256")}s(o.reduce((d,u)=>d+c(u,"manifest file").bytes,0)<=2*1024**3,"manifest total bytes"),s(V(o)===n.digest,"manifest digest identity");for(const d of y(e.artifacts,"artifacts",1e4,1)){N(d);const u=c(d,"artifact");s(r.delete(u.path),"artifact manifest identity");const h=o.map(p=>c(p,"manifest file")).find(p=>p.path===u.path);s(u.transformation||h&&h.bytes===u.originalBytes&&h.sha256===u.originalSha256,"changed artifact requires transformation")}s(r.size===0,"artifact coverage"),e.evidenceFormat!==void 0&&s(e.evidenceFormat==="zip-v1","evidence format")}export function parseHistoricalReceipt(i,e,t){const n=c(i,"receipt");s(n.kind==="historical"&&n.projectId===e,"receipt kind/project"),s(n.decision===void 0&&n.policyId===void 0&&n.policyRevision===void 0,"historical receipt release policy");for(const f of["id","runId","repository","runStatus","tokenId"])a(n[f],`receipt ${f}`,1024);a(n.testkitVersion,"receipt testkitVersion",1024,!0),g(n.acceptedAt,"receipt acceptedAt"),A(n.baseline,"receipt baseline"),A(n.fullRun,"receipt fullRun");for(const f of["baselineBranch","branch","commitSha"])a(n[f],`receipt ${f}`,4096,!0);if(n.pullRequest!==null&&m(n.pullRequest,"receipt pullRequest",1),n.decisionReasons!==null)for(const f of y(n.decisionReasons,"receipt decisionReasons",1e4)){const l=c(f,"receipt decision reason");a(l.ruleId,"receipt decision ruleId"),a(l.message,"receipt decision message")}const o=c(n.regressions,"receipt regressions");for(const f of["fixed","known","new","returning"])m(o[f],`receipt regressions ${f}`);I(n.manifestDigest,"receipt manifestDigest"),t?.id!==void 0&&s(n.id===t.id,"receipt identity");const r=c(n.historical,"receipt historical metadata");a(r.importId,"receipt importId",128),a(r.sourceId,"receipt sourceId",128),I(r.sourceDigest,"receipt sourceDigest"),s(r.manifestVersion===1||r.manifestVersion===2,"receipt manifestVersion");const d=c(r.run,"receipt run");s(d.schemaVersion===(r.manifestVersion===1?16:19),"receipt run schemaVersion");const u=c(d.run,"receipt original run");s(u.id===n.runId&&u.status===n.runStatus,"receipt original run identity"),g(u.startedAt,"receipt original run startedAt"),validateHistoricalSourceRecord(r.sourceRecord,r.sourceDigest);const h=new Set;for(const f of y(r.artifacts,"receipt artifacts",1e4,1)){N(f,!0);const l=c(f,"artifact").path;s(!h.has(l),"duplicate receipt artifact path"),h.add(l)}t?.importId!==void 0&&!t.reused&&s(r.importId===t.importId,"receipt import identity");const p=t?.evidence;if(p){s(n.runId===p.manifest.runId&&n.manifestDigest===p.manifest.digest&&(t.reused||r.sourceId===p.source.id)&&r.sourceDigest===p.source.digest&&r.manifestVersion===p.manifest.schemaVersion,"receipt evidence identity"),s(S(r.sourceRecord)===S(p.sourceRecord),"receipt source identity");const f=r.artifacts;s(f.length===p.artifacts.length,"receipt artifact coverage");for(const l of f){const b=p.artifacts.find(x=>x.path===l.path);s(b&&l.originalPath===b.originalPath&&l.originalBytes===b.originalBytes&&l.originalSha256===b.originalSha256&&l.transformation===b.transformation&&l.originalVerified===!b.transformation,"receipt artifact identity")}}return n}function T(i,e){const t=c(i,"case");for(const n of["id","engineId","failureKey","fingerprint","path","profileId","service","testType","title"])a(t[n],`case ${n}`,65536,!["id","fingerprint"].includes(n));v(t.classification,["untriaged","regression","flaky","expected","quarantined"],"case classification"),v(t.state,e?["active","resolved","fixed_pending_verification"]:["active","resolved","historical"],"case state"),g(t.firstSeenAt,"firstSeenAt"),g(t.lastSeenAt,"lastSeenAt"),(!e||t.version!==void 0)&&m(t.version,"case version"),t.issueNumber!==void 0&&m(t.issueNumber,"case issueNumber",1),t.issueRepository!==void 0&&a(t.issueRepository,"case issueRepository")}function C(i){const e=c(i,"case historical metadata");for(const t of["importId","sourceId","actorTokenId"])a(e[t],t,128);g(e.observedAt,"observedAt"),g(e.importedAt,"importedAt"),validateHistoricalSourceRecord(e.sourceRecord),T(e.case,!0),s(c(e.case,"historical case").id===e.sourceId,"historical case source identity")}export function parseHistoricalCases(i,e=100){const t=c(i,"case page"),n=new Set;for(const o of j(t,e)){T(o,!1);const r=c(o,"case"),d=r.id;s(!n.has(d),"duplicate case identity"),n.add(d),r.historical!==void 0&&C(r.historical),s(r.state!=="historical"||r.historical!==void 0,"historical case observation")}return t}export function parseHistoricalCaseHistory(i,e=100){const t=c(i,"case history page"),n=new Set;for(const o of j(t,e)){const r=c(o,"case event");for(const u of["id","actor","commandType","state","classification","issueRepository"])a(r[u],`case event ${u}`,4096,["state","classification","issueRepository"].includes(u));g(r.appliedAt,"appliedAt"),m(r.issueNumber,"issueNumber");const d=`${String(r.id)}\0${String(r.commandType)}`;s(!n.has(d),"duplicate case event"),n.add(d),r.historical!==void 0&&C(r.historical),s(r.commandType!=="case.import"||r.historical!==void 0,"case import observation")}return t}export function parseProjectSnapshot(i,e){const t=c(i,"project snapshot");return s(t.projectId===e,"project snapshot identity"),m(t.version,"project snapshot version"),parseHistoricalCases({items:t.cases},1e5),t}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/** A JSON number's spelling is part of its historical source identity. */
|
|
2
|
-
export declare class HistoricalJsonNumber {
|
|
3
|
-
readonly lexeme: string;
|
|
4
|
-
constructor(lexeme: string);
|
|
5
|
-
toJSON(): never;
|
|
6
|
-
}
|
|
7
|
-
export type HistoricalJsonValue = null | boolean | string | number | HistoricalJsonNumber | HistoricalJsonValue[] | {
|
|
8
|
-
[key: string]: HistoricalJsonValue;
|
|
9
|
-
};
|
|
10
|
-
/** Parse external JSON without rounding numbers or accepting duplicate keys. */
|
|
11
|
-
export declare function parseHistoricalJson(text: string, options?: {
|
|
12
|
-
maxBytes?: number;
|
|
13
|
-
}): HistoricalJsonValue;
|
|
14
|
-
/** Cloud's Go encoding/json canonical form, not RFC 8785. */
|
|
15
|
-
export declare function canonicalHistoricalJson(value: unknown): string;
|
|
16
|
-
export declare function historicalDigest(value: unknown): string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createHash as N}from"node:crypto";const p=/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/,g=256,F=16*1024*1024;export class HistoricalJsonNumber{lexeme;constructor(n){if(this.lexeme=n,!p.test(n))throw new Error("Invalid historical JSON number");Object.freeze(this)}toJSON(){throw new Error("Use canonicalHistoricalJson to preserve historical numbers")}}function l(e){return e.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g,"\uFFFD")}export function parseHistoricalJson(e,n={}){const t=n.maxBytes??F;if(!Number.isSafeInteger(t)||t<1||t>128*1024*1024)throw new Error("Historical JSON byte limit must be between 1 byte and 128 MiB");if(Buffer.byteLength(e)>t)throw new Error(`Historical JSON exceeds ${String(t/(1024*1024))} MiB`);let r=0;const i=()=>{throw new Error(`Invalid historical JSON at offset ${String(r)}`)},s=()=>{for(;/[\x20\t\r\n]/.test(e[r]??"");)r++},b=()=>{const u=r++;for(;r<e.length;){const c=e[r++];if(c==='"')try{return l(JSON.parse(e.slice(u,r)))}catch{return i()}c==="\\"&&r++}return i()},o=u=>{if(u>g)throw new Error("Historical JSON exceeds nesting limit");s();const c=e[r];if(c==='"')return b();if(c==="{"||c==="["){r++;const h=Object.create(null),m=[],w=c==="{"?"}":"]";if(s(),e[r]!==w)for(;;){if(c==="{"){if(s(),e[r]!=='"')return i();const O=b();if(Object.hasOwn(h,O))throw new Error("Duplicate historical JSON object key");if(s(),e[r++]!==":")return i();h[O]=o(u+1)}else m.push(o(u+1));if(s(),e[r]!==",")break;r++}return e[r++]!==w?i():c==="{"?h:m}const J=r;for(;r<e.length&&!/[\x20\t\r\n,\]}]/.test(e[r]);)r++;const f=e.slice(J,r);return f==="true"?!0:f==="false"?!1:f==="null"?null:p.test(f)?new HistoricalJsonNumber(f):i()},a=o(0);return s(),r!==e.length?i():a}function S(e){return JSON.stringify(l(e)).replace(/[<>&\u2028\u2029]/g,n=>`\\u${n.charCodeAt(0).toString(16).padStart(4,"0")}`)}export function canonicalHistoricalJson(e){const n=(t,r)=>{if(r>g)throw new Error("Historical JSON exceeds nesting limit");if(t instanceof HistoricalJsonNumber)return t.lexeme;if(t===null)return"null";if(typeof t=="string")return S(t);if(typeof t=="boolean")return String(t);if(typeof t=="number"&&Number.isFinite(t))return JSON.stringify(t);if(Array.isArray(t))return`[${Array.from(t,i=>n(i,r+1)).join(",")}]`;if(typeof t=="object"&&(Object.getPrototypeOf(t)===Object.prototype||Object.getPrototypeOf(t)===null)){const i=t,s=Object.keys(i).map(o=>({key:o,normalized:l(o),bytes:Buffer.from(l(o))}));return s.sort((o,a)=>Buffer.compare(o.bytes,a.bytes)),`{${s.map(({key:o,normalized:a},u)=>{if(u>0&&a===s[u-1].normalized)throw new Error("Duplicate historical JSON object key");return`${S(a)}:${n(i[o],r+1)}`}).join(",")}}`}throw new Error("Historical JSON requires finite numbers and JSON values")};return n(e,0)}export function historicalDigest(e){return N("sha256").update(canonicalHistoricalJson(e)).digest("hex")}
|