@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,69 +0,0 @@
|
|
|
1
|
-
import { CloudClient, type CloudClientOptions } from "./client.js";
|
|
2
|
-
import { type HistoricalBatch, type HistoricalBegin, type HistoricalEvidence } from "./historical-contract.js";
|
|
3
|
-
export interface HistoricalClientOptions extends CloudClientOptions {
|
|
4
|
-
campaignId: string;
|
|
5
|
-
}
|
|
6
|
-
export declare class HistoricalClient {
|
|
7
|
-
readonly origin: URL;
|
|
8
|
-
readonly projectId: string;
|
|
9
|
-
readonly campaignId: string;
|
|
10
|
-
readonly snapshot: CloudClient["snapshot"];
|
|
11
|
-
private readonly token;
|
|
12
|
-
private readonly ordinary;
|
|
13
|
-
private readonly staged;
|
|
14
|
-
constructor(options: Readonly<HistoricalClientOptions>);
|
|
15
|
-
private get base();
|
|
16
|
-
private importPath;
|
|
17
|
-
begin(command: HistoricalBegin): Promise<import("./historical-contract.js").HistoricalImport>;
|
|
18
|
-
stage(importId: string, evidence: HistoricalEvidence): Promise<import("./historical-contract.js").HistoricalUploadPlan>;
|
|
19
|
-
upload(target: string, filePath: string, bytes: number, contentType: "application/octet-stream" | "application/zip", onProgress?: (bytes: number) => void): Promise<void>;
|
|
20
|
-
completeEvidence(returnedURL: string): Promise<import("./historical-contract.js").HistoricalReceipt>;
|
|
21
|
-
batch(importId: string, command: HistoricalBatch): Promise<import("./historical-contract.js").HistoricalBatchResult>;
|
|
22
|
-
page(importId: string, cursor?: string, limit?: number): Promise<import("./historical-contract.js").HistoricalPage>;
|
|
23
|
-
complete(importId: string): Promise<import("./historical-contract.js").HistoricalPage>;
|
|
24
|
-
repository(): Promise<{
|
|
25
|
-
projectId: string;
|
|
26
|
-
host: string;
|
|
27
|
-
owner: string;
|
|
28
|
-
name: string;
|
|
29
|
-
}>;
|
|
30
|
-
cases(cursor?: string, limit?: number): Promise<import("./historical-contract.js").HistoricalCasePage>;
|
|
31
|
-
caseHistory(caseId: string, cursor?: string, limit?: number): Promise<import("./historical-contract.js").HistoricalCaseHistoryPage>;
|
|
32
|
-
receipt(id: string): Promise<import("./historical-contract.js").HistoricalReceipt>;
|
|
33
|
-
currentReceipt(id: string): Promise<{
|
|
34
|
-
acceptedAt: string;
|
|
35
|
-
commitSha: string;
|
|
36
|
-
decision: "hold" | "ineligible" | "ship";
|
|
37
|
-
decisionReasons: {
|
|
38
|
-
ruleId: string;
|
|
39
|
-
message: string;
|
|
40
|
-
}[];
|
|
41
|
-
fullRun: boolean;
|
|
42
|
-
id: string;
|
|
43
|
-
manifestDigest: string;
|
|
44
|
-
policyId: string;
|
|
45
|
-
policyRevision: number;
|
|
46
|
-
projectId: string;
|
|
47
|
-
regressions: {
|
|
48
|
-
fixed: number;
|
|
49
|
-
known: number;
|
|
50
|
-
new: number;
|
|
51
|
-
returning: number;
|
|
52
|
-
};
|
|
53
|
-
repository: string;
|
|
54
|
-
runId: string;
|
|
55
|
-
runStatus: string;
|
|
56
|
-
testkitVersion: string;
|
|
57
|
-
}>;
|
|
58
|
-
campaign(): Promise<import("./campaigns.js").Campaign>;
|
|
59
|
-
finding(id: string): Promise<import("./campaigns.js").FindingDetail>;
|
|
60
|
-
artifactURL(receiptId: string, path: string): string;
|
|
61
|
-
checkArtifactAvailable(receiptId: string, artifactPath: string): Promise<void>;
|
|
62
|
-
download(target: string, filePath: string, expected: {
|
|
63
|
-
bytes: number;
|
|
64
|
-
sha256: string;
|
|
65
|
-
}): Promise<void>;
|
|
66
|
-
private target;
|
|
67
|
-
private json;
|
|
68
|
-
private read;
|
|
69
|
-
}
|
package/dist/cloud/historical.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import j from"node:fs";import{stat as I}from"node:fs/promises";import{downloadVerifiedArtifact as C}from"./download.js";import{CloudClient as R,CloudResponseError as $}from"./client.js";import{request as p,invalidResponse as n}from"./transport.js";import{attachErrorDiagnostics as b}from"../kernel/error-serialization.js";import{isUnknownRecord as u}from"../kernel/unknown-values.js";import{canonicalHistoricalJson as v}from"./historical-json.js";import{HISTORICAL_BODY_LIMIT as H,parseHistoricalBatchResult as T,parseHistoricalCaseHistory as E,parseHistoricalCases as U,parseHistoricalImport as S,parseHistoricalPage as m,parseHistoricalReceipt as g,parseHistoricalResponse as w,parseHistoricalUploadPlan as P}from"./historical-contract.js";export class HistoricalClient{origin;projectId;campaignId;snapshot;token;ordinary;staged=new Map;constructor(t){const e=new R(t,{decodeJSON:w,maxResponseBytes:33554432});if(this.ordinary=e,this.snapshot=e.snapshot.bind(e),!/^[A-Za-z0-9_-]{1,128}$/.test(t.projectId)||!/^[A-Za-z0-9_-]{1,128}$/.test(t.campaignId))throw new Error("Historical Cloud project and campaign IDs must be valid Cloud identifiers");this.origin=e.origin,this.projectId=e.projectId,this.campaignId=t.campaignId,this.token=t.token}get base(){return`/api/v1/projects/${encodeURIComponent(this.projectId)}/campaigns/${encodeURIComponent(this.campaignId)}/imports`}importPath(t){if(!t.trim())throw new Error("Historical import ID is required");return`${this.base}/${encodeURIComponent(t)}`}async begin(t){const e=S(await this.json("POST",this.base,t),this.projectId,this.campaignId);if(e.namespace!==t.namespace||e.inventoryDigest!==t.inventoryDigest||e.total!==t.inventory.length)throw n("historical begin inventory identity");return e}async stage(t,e){const r=P(await this.json("POST",`${this.importPath(t)}/evidence`,e),e),i=this.target(r.completeUrl).href;for(const o of r.uploads)this.target(o.url);return r.archive&&this.target(r.archive.url),this.staged.set(i,{importId:t,evidence:e,reused:r.reused}),r}async upload(t,e,r,i,o){const c=this.target(t);if(!Number.isSafeInteger(r)||r<0)throw new Error("Historical upload byte length must be a nonnegative safe integer");const a=await I(e);if(!a.isFile()||a.size!==r)throw new Error("Historical upload file size does not match the manifest");const h=j.createReadStream(e),y=new Promise(d=>h.once("close",d));try{const d=await p({body:h,onUploadChunk:o,headers:{Authorization:`Bearer ${this.token}`,"Content-Length":String(r),"Content-Type":i},method:"PUT",timeoutMs:6e5,url:c});if(d.status<200||d.status>=300)throw f(d)}finally{h.destroy(),await y}}async completeEvidence(t){const e=this.target(t);return g(await this.json("POST",e.href),this.projectId,this.staged.get(e.href))}async batch(t,e){const{value:r,status:i}=await this.read("POST",`${this.importPath(t)}/batches`,e,!0),o=T(r,t,e);if(i===422!==o.rejected)throw n("historical batch HTTP status");return o}async page(t,e,r=100){const i=m(await this.json("GET",`${this.importPath(t)}${l(e,r)}`),this.projectId,this.campaignId,t,r);if(e!==void 0&&i.nextCursor===e)throw n("historical repeated cursor");return i}async complete(t){const e=m(await this.json("POST",`${this.importPath(t)}/complete`),this.projectId,this.campaignId,t);if(!e.import.completedAt||Object.values(e.counts).some(r=>Object.entries(r).some(([i,o])=>!["accepted","reused"].includes(i)&&o>0)))throw n("historical completion state");return e}async repository(){const t=await this.json("GET",`/api/v1/projects/${encodeURIComponent(this.projectId)}/repository`);if(!u(t)||t.projectId!==this.projectId||Object.keys(t).length!==4||Object.keys(t).some(r=>!["projectId","host","owner","name"].includes(r)))throw n("project repository identity");const e=r=>{const i=t[r];if(typeof i!="string"||!i.trim()||i.includes("\0")||Buffer.byteLength(i)>256)throw n(`project repository ${r}`);return i};return{projectId:this.projectId,host:e("host"),owner:e("owner"),name:e("name")}}async cases(t,e=100){const r=U(await this.json("GET",`/api/v1/projects/${encodeURIComponent(this.projectId)}/cases${l(t,e)}`),e);if(t!==void 0&&r.nextCursor===t)throw n("historical repeated cursor");return r}async caseHistory(t,e,r=100){const i=E(await this.json("GET",`/api/v1/projects/${encodeURIComponent(this.projectId)}/cases/${encodeURIComponent(t)}/history${l(e,r)}`),r);if(e!==void 0&&i.nextCursor===e)throw n("historical repeated cursor");return i}async receipt(t){const e=await this.json("GET",`/api/v1/receipts/${encodeURIComponent(t)}`);if(!u(e))throw n("historical receipt view");return g(e.receipt,this.projectId,{id:t})}async currentReceipt(t){return this.ordinary.receipt(t)}campaign(){return this.ordinary.campaign(this.campaignId)}finding(t){return this.ordinary.finding(this.campaignId,t)}artifactURL(t,e){if(e.split("/").some(r=>!r||r==="."||r==="..")||e.includes("\\"))throw new Error("Historical artifact path must be a normalized relative path");return`/api/v1/receipts/${encodeURIComponent(t)}/artifacts/${e.split("/").map(encodeURIComponent).join("/")}`}async checkArtifactAvailable(t,e){const r=await p({body:null,headers:{Authorization:`Bearer ${this.token}`,"Accept-Encoding":"identity"},method:"HEAD",timeoutMs:3e4,url:this.target(this.artifactURL(t,e))});if(r.status<200||r.status>=300)throw f(r)}async download(t,e,r){const i=this.target(t);await C(i,this.token,e,r)}target(t){if(!t)throw new Error("Testkit Cloud returned an empty historical URL");const e=new URL(t,this.origin);if(e.origin!==this.origin.origin||e.username||e.password||e.hash)throw new Error("Testkit Cloud returned a historical URL outside its configured origin or containing credentials/fragment");return e}async json(t,e,r){return(await this.read(t,e,r)).value}async read(t,e,r,i=!1){const o=this.target(e),c=r===void 0?null:Buffer.from(v(r));if(c&&c.length>H)throw new Error("Historical Cloud request exceeds 2 MiB; split its records or reduce the source inventory");const a=await p({body:c,headers:{Accept:"application/json",Authorization:`Bearer ${this.token}`,...c?{"Content-Length":String(c.length),"Content-Type":"application/json"}:{}},method:t,timeoutMs:3e4,url:o,maxResponseBytes:32*1024**2});if((a.status<200||a.status>=300)&&!(i&&a.status===422))throw f(a);try{return{value:w(new TextDecoder("utf-8",{fatal:!0}).decode(a.body)),status:a.status}}catch(h){throw n(`historical JSON response: ${h instanceof Error?h.message:String(h)}`)}}}function l(s,t){if(!Number.isSafeInteger(t)||t<1||t>100||s!==void 0&&(!s||Buffer.byteLength(s)>1024))throw new Error("Historical pagination requires limit 1\u2013100 and a cursor of at most 1024 bytes");const e=new URLSearchParams({limit:String(t)});return s!==void 0&&e.set("cursor",s),`?${e}`}function f(s){let t=s.body.toString("utf8").trim(),e=null,r={};try{const i=JSON.parse(t);u(i)&&(r=i,typeof i.detail=="string"&&(t=i.detail),typeof i.code=="string"&&(e=i.code))}catch{}return b(new $(s.status,t||`Testkit Cloud returned HTTP ${String(s.status)}`,e),{source:"cloud",...r})}
|
package/dist/cloud/pagination.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export async function walkCloudPages(t,s){const r=new Set;let n;for(let o=0;o<1e4;o++){const e=await t(n);if(e.nextCursor!==void 0&&(e.items.length===0||r.has(e.nextCursor)))throw new Error("Cloud pagination repeated a cursor or returned an empty continuing page");if(s(e.items),e.nextCursor===void 0)return;r.add(e.nextCursor),n=e.nextCursor}throw new Error("Cloud pagination exceeded 10,000 pages; the read is inconclusive")}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
export interface ResponseDocument {
|
|
3
|
-
body: Buffer;
|
|
4
|
-
status: number;
|
|
5
|
-
}
|
|
6
|
-
interface RequestInput {
|
|
7
|
-
body: Buffer | fs.ReadStream | null;
|
|
8
|
-
headers: Readonly<Record<string, string>>;
|
|
9
|
-
method: string;
|
|
10
|
-
timeoutMs: number;
|
|
11
|
-
url: URL;
|
|
12
|
-
onUploadChunk?: (bytes: number) => void;
|
|
13
|
-
onResponseChunk?: (chunk: Uint8Array) => Promise<void>;
|
|
14
|
-
maxResponseBytes?: number;
|
|
15
|
-
}
|
|
16
|
-
export declare function request(input: Readonly<RequestInput>): Promise<ResponseDocument>;
|
|
17
|
-
export declare function invalidResponse(field: string): Error;
|
|
18
|
-
export {};
|
package/dist/cloud/transport.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import i from"node:fs";import{Agent as f,fetch as h}from"undici";import{attachErrorDiagnostics as l}from"../kernel/error-serialization.js";import{isUnknownRecord as d}from"../kernel/unknown-values.js";const m=new f({connectTimeout:3e4,headersTimeout:10*6e4,bodyTimeout:10*6e4});export async function request(e){const s=new AbortController,a=setTimeout(()=>{s.abort(new Error("Testkit Cloud request timed out"))},e.timeoutMs);if(a.unref(),e.body instanceof i.ReadStream){const o=e.body,t=n=>{s.abort(n)};o.once("error",t),o.once("close",()=>o.off("error",t))}let r;try{const o=await h(e.url,{body:e.body instanceof i.ReadStream&&e.onUploadChunk?b(e.body,e.onUploadChunk):e.body,headers:e.headers,method:e.method,redirect:"manual",signal:s.signal,dispatcher:m,duplex:"half"});r=o.body?.getReader();const t=[];let n=0;for(;r;){const{done:u,value:c}=await r.read();if(u)break;if(e.onResponseChunk&&o.status>=200&&o.status<300){await e.onResponseChunk(c);continue}if(n+=c.byteLength,n>(e.maxResponseBytes??4*1024*1024))throw invalidResponse("response: exceeded byte limit");t.push(c)}return{body:Buffer.concat(t),status:o.status}}catch(o){const t=d(o)&&d(o.cause)?o.cause:o,n=d(t)&&typeof t.code=="string"?t.code:void 0;throw n==="invalid_cloud_response"?o:l(Object.assign(new Error(`Testkit Cloud transport failed: ${t instanceof Error?t.message:String(t)}`,{cause:o}),{code:"cloud_transport_error"}),{source:"transport",...n?{transportCode:n}:{}})}finally{clearTimeout(a),await r?.cancel().catch(()=>{}),r?.releaseLock()}}export function invalidResponse(e){return l(Object.assign(new Error(`Testkit Cloud returned an invalid ${e}`),{code:"invalid_cloud_response"}),{source:"cloud"})}async function*b(e,s){for await(const a of e){const r=a;s(r.byteLength),yield r}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{isUnknownRecord as e}from"../../kernel/unknown-values.js";import{attachErrorDiagnostics as t}from"../../kernel/error-serialization.js";export function minimumConfirmingRuns(o){let i=o;for(const r of["cloud","verification","minimumConfirmingRuns"]){if(!e(i))throw n();if(i=i[r],i===void 0)return 2}if(typeof i!="number"||!Number.isSafeInteger(i)||i<1||i>64)throw n();return i}function n(){return t(Object.assign(new Error("cloud.verification.minimumConfirmingRuns must be an integer from 1 through 64"),{code:"invalid_cloud_verification_config"}),{source:"local",field:"cloud.verification.minimumConfirmingRuns"})}
|
package/docs/cloud-control.md
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
# Cloud command reference
|
|
2
|
-
|
|
3
|
-
The `testkit cloud` commands are deprecated. See the
|
|
4
|
-
[Cloud boundary](testkit-cloud-boundary.md) for the direction.
|
|
5
|
-
|
|
6
|
-
`testkit cloud apply --help` prints the account-command envelope, every supported
|
|
7
|
-
operation, its scope IDs, and its input fields. This reference ships with Testkit.
|
|
8
|
-
|
|
9
|
-
## Account commands
|
|
10
|
-
|
|
11
|
-
`testkit cloud apply --file command.json --json` sends one account command.
|
|
12
|
-
Every command requires `schemaVersion: 1`, an `idempotencyKey`, an `operation`,
|
|
13
|
-
and an `input` object. Add the scope IDs shown below. Omit unrelated scope IDs.
|
|
14
|
-
The key has 1 to 128 characters without surrounding whitespace. The server
|
|
15
|
-
limits files to 256 KiB and rejects unknown input fields.
|
|
16
|
-
|
|
17
|
-
```json
|
|
18
|
-
{
|
|
19
|
-
"schemaVersion": 1,
|
|
20
|
-
"idempotencyKey": "retention-30",
|
|
21
|
-
"operation": "project.retention",
|
|
22
|
-
"projectId": "prj_example",
|
|
23
|
-
"input": { "days": 30 }
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
| Operation | Scope fields | Input fields |
|
|
28
|
-
| --------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
29
|
-
| `account.theme` | None | `theme`: `system`, `light`, or `dark` |
|
|
30
|
-
| `organisation.update` | `organisationId` | `name` |
|
|
31
|
-
| `invitation.create` | `organisationId` | `email`, `role`: `owner`, `admin`, `member`, or `viewer` |
|
|
32
|
-
| `invitation.revoke` | `organisationId`, `resourceId` | `{}` |
|
|
33
|
-
| `provider.create` | `organisationId` | `provider`: `gitea`, `host`: HTTPS origin, `displayName`, `oauthClientId`, `oauthClientSecret`; optional `botToken`, `caBundlePEM` |
|
|
34
|
-
| `provider.delete` | `organisationId`, `resourceId` | `{}` |
|
|
35
|
-
| `project.create` | `organisationId` | `name`, `provider`: `github` or `gitea`, `host`, `repository`: owner/repo; optional `publishDecisions`, default false |
|
|
36
|
-
| `project.publishing` | `projectId` | `enabled`: boolean |
|
|
37
|
-
| `project.baseline` | `projectId` | `branch`; an empty string resets the provider default |
|
|
38
|
-
| `project.retention` | `projectId` | `days`: 1 to 3650 |
|
|
39
|
-
| `project.policy` | `projectId` | `policyId`: string, or null to inherit the organisation default |
|
|
40
|
-
| `policy.create` | `organisationId` | `name`; optional `rules` or `sourcePolicyId`, mutually exclusive |
|
|
41
|
-
| `policy.revise` | `organisationId`, `resourceId` | Complete `rules` array |
|
|
42
|
-
| `policy.default` | `organisationId`, `resourceId` | `{}` |
|
|
43
|
-
| `notification.create` | `projectId` | `kind`: `slack` or `email`, `displayName`, `target`, `events` |
|
|
44
|
-
| `notification.update` | `projectId`, `resourceId` | `enabled`: boolean, `events` |
|
|
45
|
-
| `notification.delete` | `projectId`, `resourceId` | `{}` |
|
|
46
|
-
| `notification.test` | `projectId`, `resourceId` | `{}`; sends a real test notification |
|
|
47
|
-
| `token.create` | `projectId` | `name`; also requires `--secret-output NEW_FILE` |
|
|
48
|
-
| `token.revoke` | `projectId`, `resourceId` | `{}` |
|
|
49
|
-
|
|
50
|
-
Notification events are `baseline_hold`, `case_opened`, and `case_resolved`.
|
|
51
|
-
At least one event is required. An email target is an email address. A Slack
|
|
52
|
-
target is an HTTPS `hooks.slack.com` webhook URL.
|
|
53
|
-
|
|
54
|
-
Policy rules have `id`, `kind`, `mode`, `branches`, and typed `params`.
|
|
55
|
-
`cloud show policy ID --org ORG_ID` returns existing rules. Revisions replace the
|
|
56
|
-
whole rules array. `cloud policy preview ID --org ORG_ID --file preview.json`
|
|
57
|
-
accepts `{"receiptId":"rcpt_example","rules":[...]}` without saving a revision.
|
|
58
|
-
|
|
59
|
-
Secrets belong in private input files. `token.create` reserves a new private
|
|
60
|
-
output file before issuing the token and omits its value from terminal output.
|
|
61
|
-
If saving fails after issuance, the same command and key recover the original
|
|
62
|
-
token with a new `--secret-output` path.
|
|
63
|
-
|
|
64
|
-
Reusing a key with a changed command conflicts. For `outcome_uncertain`, inspect
|
|
65
|
-
the resource and audit history before choosing a new key. Provider publishing is
|
|
66
|
-
opt-in and can require browser consent. CI returns recovery details instead of
|
|
67
|
-
waiting for consent or a processing connection.
|
|
68
|
-
|
|
69
|
-
## Discovery and session management
|
|
70
|
-
|
|
71
|
-
`cloud list --help` and `cloud show --help` list resources and filters.
|
|
72
|
-
Project discovery matches Git origin to accessible Cloud projects when no
|
|
73
|
-
project is selected. A non-JSON TTY can prompt when several choices remain.
|
|
74
|
-
CI and JSON commands require explicit selectors for ambiguous choices.
|
|
75
|
-
|
|
76
|
-
Account project and campaign reads include `dashboardUrl`. Creation results also
|
|
77
|
-
include it when the optional directory lookup succeeds; a failed lookup does not
|
|
78
|
-
turn a completed creation into a failed command. Automation campaign commands
|
|
79
|
-
omit this field because that credential cannot read the account directory.
|
|
80
|
-
Receipt publication includes its stable dashboard link for both account and
|
|
81
|
-
automation credentials.
|
|
82
|
-
|
|
83
|
-
`cloud list sessions` lists your CLI sessions by ID, agent, creation time, and
|
|
84
|
-
expiry. `cloud session revoke SESSION_ID` revokes one session. These commands do
|
|
85
|
-
not refresh the current session's expiry. The agent label is client-supplied
|
|
86
|
-
context, not proof of identity. `cloud logout` revokes the saved session and
|
|
87
|
-
removes its local credential. Project tokens use `cloud list tokens` and
|
|
88
|
-
`token.revoke` instead.
|
|
89
|
-
|
|
90
|
-
## Case and campaign files
|
|
91
|
-
|
|
92
|
-
Case envelopes contain `schemaVersion: 1`, `projectId`, `idempotencyKey`,
|
|
93
|
-
`expectedVersion`, and `commands`. `cloud snapshot` supplies the project version.
|
|
94
|
-
Each command has `caseId` and one of these types:
|
|
95
|
-
|
|
96
|
-
| Type | Other required fields |
|
|
97
|
-
| ----------------- | ---------------------------------------------------------------------------------- |
|
|
98
|
-
| `case.set_state` | `state`: `active` or `resolved` |
|
|
99
|
-
| `case.classify` | `classification`: `untriaged`, `regression`, `flaky`, `expected`, or `quarantined` |
|
|
100
|
-
| `case.link_issue` | `issueRepository`, positive `issueNumber` |
|
|
101
|
-
|
|
102
|
-
The [Cloud boundary](testkit-cloud-boundary.md#report-an-externally-executed-campaign)
|
|
103
|
-
documents campaign report fields. `cloud snapshot --campaign ID` supplies the
|
|
104
|
-
campaign version.
|
|
105
|
-
`cloud apply --campaign ID --file report.json` can load product verification
|
|
106
|
-
configuration from `--dir`, so it retains the product CLI version check.
|
|
107
|
-
Remote-only reads, including `cloud snapshot`, do not require a matching local
|
|
108
|
-
Testkit installation.
|