@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.
Files changed (159) hide show
  1. package/dist/app/run/engine-execution.d.ts +2 -0
  2. package/dist/app/run/engine-execution.js +1 -1
  3. package/dist/cli/command-catalog.d.ts +0 -127
  4. package/dist/cli/command-catalog.js +1 -1
  5. package/dist/cli/command-registry.d.ts +1 -0
  6. package/dist/cli/command-registry.js +1 -1
  7. package/dist/cli/entrypoint.js +1 -1
  8. package/dist/cli/framework/execute.d.ts +1 -0
  9. package/dist/cli/framework/execute.js +6 -6
  10. package/dist/cli/index.js +1 -1
  11. package/dist/cli/version-drift.js +7 -7
  12. package/dist/config/authoring/index.d.ts +0 -5
  13. package/dist/config/loader/index.d.ts +0 -1
  14. package/dist/config/loader/index.js +1 -1
  15. package/dist/engines/adapters/node-startup-cache.d.ts +8 -0
  16. package/dist/engines/adapters/node-startup-cache.js +1 -0
  17. package/dist/engines/api/execution.d.ts +2 -0
  18. package/dist/engines/managed-module-resolution.js +8 -1
  19. package/dist/engines/node-vitest/adapter/adapter.js +1 -1
  20. package/dist/engines/playwright/adapter/adapter.js +1 -1
  21. package/dist/environment/ready-environment.d.ts +3 -1
  22. package/dist/environment/ready-environment.js +1 -1
  23. package/dist/environment/run-environment.js +1 -1
  24. package/dist/environment/runtime-contexts.d.ts +1 -0
  25. package/dist/environment/runtime-contexts.js +1 -1
  26. package/dist/environment/runtime-manager.js +1 -1
  27. package/dist/evidence/bundles.d.ts +2 -3
  28. package/dist/evidence/bundles.js +1 -1
  29. package/dist/evidence/contracts.d.ts +0 -8
  30. package/dist/evidence/index.d.ts +1 -1
  31. package/dist/evidence/index.js +1 -1
  32. package/dist/process/execa-bundle.json +1 -1
  33. package/docs/engine-architecture.md +20 -0
  34. package/package.json +3 -10
  35. package/testkit-config-schema.md +0 -23
  36. package/dist/app/cloud/campaigns.d.ts +0 -6
  37. package/dist/app/cloud/campaigns.js +0 -1
  38. package/dist/app/cloud/control-actions.d.ts +0 -12
  39. package/dist/app/cloud/control-actions.js +0 -2
  40. package/dist/app/cloud/control-links.d.ts +0 -5
  41. package/dist/app/cloud/control-links.js +0 -1
  42. package/dist/app/cloud/control-read.d.ts +0 -24
  43. package/dist/app/cloud/control-read.js +0 -1
  44. package/dist/app/cloud/control-resources.d.ts +0 -3
  45. package/dist/app/cloud/control-resources.js +0 -1
  46. package/dist/app/cloud/control.d.ts +0 -34
  47. package/dist/app/cloud/control.js +0 -5
  48. package/dist/app/cloud/credentials.d.ts +0 -11
  49. package/dist/app/cloud/credentials.js +0 -2
  50. package/dist/app/cloud/index.d.ts +0 -22
  51. package/dist/app/cloud/index.js +0 -2
  52. package/dist/app/cloud/login.d.ts +0 -63
  53. package/dist/app/cloud/login.js +0 -2
  54. package/dist/app/cloud/migration/archive.d.ts +0 -13
  55. package/dist/app/cloud/migration/archive.js +0 -1
  56. package/dist/app/cloud/migration/commands.d.ts +0 -8
  57. package/dist/app/cloud/migration/commands.js +0 -1
  58. package/dist/app/cloud/migration/evidence.d.ts +0 -13
  59. package/dist/app/cloud/migration/evidence.js +0 -2
  60. package/dist/app/cloud/migration/files.d.ts +0 -16
  61. package/dist/app/cloud/migration/files.js +0 -2
  62. package/dist/app/cloud/migration/index.d.ts +0 -6
  63. package/dist/app/cloud/migration/index.js +0 -1
  64. package/dist/app/cloud/migration/journal.d.ts +0 -64
  65. package/dist/app/cloud/migration/journal.js +0 -1
  66. package/dist/app/cloud/migration/mapping-dispositions.d.ts +0 -3
  67. package/dist/app/cloud/migration/mapping-dispositions.js +0 -1
  68. package/dist/app/cloud/migration/mapping.d.ts +0 -11
  69. package/dist/app/cloud/migration/mapping.js +0 -2
  70. package/dist/app/cloud/migration/model.d.ts +0 -175
  71. package/dist/app/cloud/migration/model.js +0 -1
  72. package/dist/app/cloud/migration/plan.d.ts +0 -7
  73. package/dist/app/cloud/migration/plan.js +0 -1
  74. package/dist/app/cloud/migration/progress.d.ts +0 -19
  75. package/dist/app/cloud/migration/progress.js +0 -1
  76. package/dist/app/cloud/migration/reconcile.d.ts +0 -22
  77. package/dist/app/cloud/migration/reconcile.js +0 -1
  78. package/dist/app/cloud/migration/reconciliation-spool.d.ts +0 -4
  79. package/dist/app/cloud/migration/reconciliation-spool.js +0 -1
  80. package/dist/app/cloud/migration/state.d.ts +0 -15
  81. package/dist/app/cloud/migration/state.js +0 -1
  82. package/dist/app/cloud/migration/transfer.d.ts +0 -6
  83. package/dist/app/cloud/migration/transfer.js +0 -1
  84. package/dist/cli/cloud-apply-help.d.ts +0 -1
  85. package/dist/cli/cloud-apply-help.js +0 -56
  86. package/dist/cli/cloud-selection.d.ts +0 -2
  87. package/dist/cli/cloud-selection.js +0 -3
  88. package/dist/cli/commands/cloud/apply.d.ts +0 -5
  89. package/dist/cli/commands/cloud/apply.js +0 -1
  90. package/dist/cli/commands/cloud/campaign/create.d.ts +0 -5
  91. package/dist/cli/commands/cloud/campaign/create.js +0 -1
  92. package/dist/cli/commands/cloud/download.d.ts +0 -5
  93. package/dist/cli/commands/cloud/download.js +0 -1
  94. package/dist/cli/commands/cloud/list.d.ts +0 -5
  95. package/dist/cli/commands/cloud/list.js +0 -1
  96. package/dist/cli/commands/cloud/login.d.ts +0 -13
  97. package/dist/cli/commands/cloud/login.js +0 -2
  98. package/dist/cli/commands/cloud/logout.d.ts +0 -7
  99. package/dist/cli/commands/cloud/logout.js +0 -1
  100. package/dist/cli/commands/cloud/migrate/apply.d.ts +0 -2
  101. package/dist/cli/commands/cloud/migrate/apply.js +0 -1
  102. package/dist/cli/commands/cloud/migrate/plan.d.ts +0 -7
  103. package/dist/cli/commands/cloud/migrate/plan.js +0 -1
  104. package/dist/cli/commands/cloud/migrate/progress.d.ts +0 -2
  105. package/dist/cli/commands/cloud/migrate/progress.js +0 -2
  106. package/dist/cli/commands/cloud/migrate/reconcile.d.ts +0 -2
  107. package/dist/cli/commands/cloud/migrate/reconcile.js +0 -1
  108. package/dist/cli/commands/cloud/policy/preview.d.ts +0 -5
  109. package/dist/cli/commands/cloud/policy/preview.js +0 -1
  110. package/dist/cli/commands/cloud/project/create.d.ts +0 -5
  111. package/dist/cli/commands/cloud/project/create.js +0 -1
  112. package/dist/cli/commands/cloud/publish.d.ts +0 -7
  113. package/dist/cli/commands/cloud/publish.js +0 -1
  114. package/dist/cli/commands/cloud/session/revoke.d.ts +0 -8
  115. package/dist/cli/commands/cloud/session/revoke.js +0 -1
  116. package/dist/cli/commands/cloud/show.d.ts +0 -5
  117. package/dist/cli/commands/cloud/show.js +0 -1
  118. package/dist/cli/commands/cloud/snapshot.d.ts +0 -5
  119. package/dist/cli/commands/cloud/snapshot.js +0 -1
  120. package/dist/cli/commands/cloud/status.d.ts +0 -33
  121. package/dist/cli/commands/cloud/status.js +0 -1
  122. package/dist/cloud/account.d.ts +0 -34
  123. package/dist/cloud/account.js +0 -1
  124. package/dist/cloud/archive-contract.d.ts +0 -1
  125. package/dist/cloud/archive-contract.js +0 -1
  126. package/dist/cloud/archive.d.ts +0 -12
  127. package/dist/cloud/archive.js +0 -1
  128. package/dist/cloud/campaigns.d.ts +0 -200
  129. package/dist/cloud/campaigns.js +0 -2
  130. package/dist/cloud/client.d.ts +0 -68
  131. package/dist/cloud/client.js +0 -4
  132. package/dist/cloud/download.d.ts +0 -5
  133. package/dist/cloud/download.js +0 -1
  134. package/dist/cloud/historical-contract.d.ts +0 -224
  135. package/dist/cloud/historical-contract.js +0 -1
  136. package/dist/cloud/historical-json.d.ts +0 -16
  137. package/dist/cloud/historical-json.js +0 -1
  138. package/dist/cloud/historical.d.ts +0 -69
  139. package/dist/cloud/historical.js +0 -1
  140. package/dist/cloud/pagination.d.ts +0 -5
  141. package/dist/cloud/pagination.js +0 -1
  142. package/dist/cloud/transport.d.ts +0 -18
  143. package/dist/cloud/transport.js +0 -1
  144. package/dist/config/loader/cloud.d.ts +0 -2
  145. package/dist/config/loader/cloud.js +0 -1
  146. package/docs/cloud-control.md +0 -108
  147. package/docs/testkit-cloud-boundary.md +0 -628
  148. package/node_modules/buffer-crc32/LICENSE +0 -19
  149. package/node_modules/buffer-crc32/README.md +0 -55
  150. package/node_modules/buffer-crc32/dist/index.cjs +0 -306
  151. package/node_modules/buffer-crc32/dist/index.d.cts +0 -35
  152. package/node_modules/buffer-crc32/dist/index.d.mts +0 -35
  153. package/node_modules/buffer-crc32/dist/index.mjs +0 -304
  154. package/node_modules/buffer-crc32/index.d.ts +0 -35
  155. package/node_modules/buffer-crc32/package.json +0 -54
  156. package/node_modules/yazl/LICENSE +0 -21
  157. package/node_modules/yazl/README.md +0 -457
  158. package/node_modules/yazl/index.js +0 -826
  159. 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
- }
@@ -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})}
@@ -1,5 +0,0 @@
1
- /** Bound a complete read even if Cloud keeps issuing fresh cursors. */
2
- export declare function walkCloudPages<T>(read: (cursor?: string) => Promise<{
3
- items: T[];
4
- nextCursor?: string;
5
- }>, visit: (items: T[]) => void): Promise<void>;
@@ -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 {};
@@ -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,2 +0,0 @@
1
- /** Local submission policy only. Cloud independently owns acceptance. */
2
- export declare function minimumConfirmingRuns(config: object): number;
@@ -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"})}
@@ -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.