From 2eb3a3973dba91cce1961b1c664ac40508e50a3e Mon Sep 17 00:00:00 2001 From: finalerock44 Date: Tue, 4 Aug 2026 16:31:52 +0100 Subject: [PATCH 1/2] fix(deps): resolve three new transitive security advisories pnpm audit --audit-level moderate started failing CI on every branch, including a clean dev - these advisories were published after dev's last green run, so nothing in the tree had to change to break it. - brace-expansion: the existing override pinned 5.0.8, which GHSA-rgw5-rvv9-x895 now covers (vulnerable <5.0.9). Range and target bumped to 5.0.9. - fast-uri (via @modelcontextprotocol/sdk > ajv): GHSA-7p8r-x3mc-p8w7, pinned 3.1.5. - hono (via @modelcontextprotocol/sdk): GHSA-8j4g-w8fx-2239, pinned 4.12.34. All three pinned to the lowest patched version within their current major, following the existing exact-pin overrides. A first pass using open '>=' ranges pulled fast-uri 4.1.2 - a major jump inside ajv - for no benefit; these land on 3.1.5 and 4.12.34 instead. audit clean; lint, typecheck, build and all 194 tests pass. fast-uri and hono are both MCP SDK dependencies, so also smoke-tested dist/mcp/index.js over stdio: initialize and tools/list both return, all five tools registered. --- package.json | 4 +++- pnpm-lock.yaml | 40 +++++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index c46c51c..83e841f 100644 --- a/package.json +++ b/package.json @@ -105,9 +105,11 @@ "diff@>=6.0.0": "8.0.3", "brace-expansion@<1.1.16": "1.1.16", "brace-expansion@>=2.0.0 <2.0.3": "2.0.3", - "brace-expansion@>=3.0.0 <5.0.8": "5.0.8", + "brace-expansion@>=3.0.0 <5.0.9": "5.0.9", "ws@>=8.0.0 <8.21.0": "8.21.0", "esbuild@<0.28.1": ">=0.28.1", + "fast-uri@>=3.0.0 <3.1.5": "3.1.5", + "hono@>=4.0.0 <4.12.34": "4.12.34", "micromatch>picomatch": "^2.3.2", "tinyglobby>picomatch": "^4.0.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3d9a3f8..a75f3d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,9 +26,11 @@ overrides: diff@>=6.0.0: 8.0.3 brace-expansion@<1.1.16: 1.1.16 brace-expansion@>=2.0.0 <2.0.3: 2.0.3 - brace-expansion@>=3.0.0 <5.0.8: 5.0.8 + brace-expansion@>=3.0.0 <5.0.9: 5.0.9 ws@>=8.0.0 <8.21.0: 8.21.0 esbuild@<0.28.1: '>=0.28.1' + fast-uri@>=3.0.0 <3.1.5: 3.1.5 + hono@>=4.0.0 <4.12.34: 4.12.34 micromatch>picomatch: ^2.3.2 tinyglobby>picomatch: ^4.0.4 @@ -344,7 +346,7 @@ packages: resolution: {integrity: sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==} engines: {node: '>=20'} peerDependencies: - hono: ^4 + hono: 4.12.34 '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} @@ -589,8 +591,8 @@ packages: resolution: {integrity: sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==} engines: {node: '>= 5.10.0'} - brace-expansion@5.0.8: - resolution: {integrity: sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} engines: {node: 20 || >=22} braces@3.0.3: @@ -906,8 +908,8 @@ packages: fast-string-width@3.0.2: resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} - fast-uri@3.1.4: - resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + fast-uri@3.1.5: + resolution: {integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==} fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} @@ -1035,8 +1037,8 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - hono@4.12.32: - resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==} + hono@4.12.34: + resolution: {integrity: sha512-GqXJqY/xJkJmuloTrnV1ZEXG3fqte+VjkUqoRNZXcrUidiUOP4fMSIHHY4tsqZBK++kVyWmt/AAfSUuy57/eSA==} engines: {node: '>=16.9.0'} http-errors@2.0.1: @@ -1919,9 +1921,9 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 - '@hono/node-server@2.0.12(hono@4.12.32)': + '@hono/node-server@2.0.12(hono@4.12.34)': dependencies: - hono: 4.12.32 + hono: 4.12.34 '@humanfs/core@0.19.2': dependencies: @@ -1954,7 +1956,7 @@ snapshots: '@modelcontextprotocol/sdk@1.30.0(zod@4.4.3)': dependencies: - '@hono/node-server': 2.0.12(hono@4.12.32) + '@hono/node-server': 2.0.12(hono@4.12.34) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 @@ -1964,7 +1966,7 @@ snapshots: eventsource-parser: 3.1.0 express: 5.2.1 express-rate-limit: 8.6.1(express@5.2.1) - hono: 4.12.32 + hono: 4.12.34 jose: 6.2.5 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -2164,7 +2166,7 @@ snapshots: ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.4 + fast-uri: 3.1.5 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -2206,7 +2208,7 @@ snapshots: dependencies: big-integer: 1.6.52 - brace-expansion@5.0.8: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -2575,7 +2577,7 @@ snapshots: dependencies: fast-string-truncated-width: 3.0.3 - fast-uri@3.1.4: {} + fast-uri@3.1.5: {} fast-wrap-ansi@0.2.2: dependencies: @@ -2697,7 +2699,7 @@ snapshots: he@1.2.0: {} - hono@4.12.32: {} + hono@4.12.34: {} http-errors@2.0.1: dependencies: @@ -2873,15 +2875,15 @@ snapshots: minimatch@10.2.3: dependencies: - brace-expansion: 5.0.8 + brace-expansion: 5.0.9 minimatch@10.2.6: dependencies: - brace-expansion: 5.0.8 + brace-expansion: 5.0.9 minimatch@9.0.7: dependencies: - brace-expansion: 5.0.8 + brace-expansion: 5.0.9 minimist@1.2.8: {} From c4fd01b2e6911b54a7519014def3489b5976e79e Mon Sep 17 00:00:00 2001 From: finalerock44 Date: Tue, 4 Aug 2026 16:09:59 +0100 Subject: [PATCH 2/2] chore: regenerate schema types from the current API swagger The generated types were stale by several releases (the compatibility example still showed latestVersion 2.1.0, defaultVersion 1.41.0) - they had not been regenerated since before the 2.5/2.6 additions. Regenerated with openapi-typescript against the swagger carrying Maestro 2.7.0/2.8.0, per the repo rule that this file is never hand-edited. Doc-comment and shape churn only; typecheck, build and the full test suite pass. --- src/types/generated/schema.types.ts | 4411 +++++++++++++++++++++------ 1 file changed, 3541 insertions(+), 870 deletions(-) diff --git a/src/types/generated/schema.types.ts b/src/types/generated/schema.types.ts index f1bcbc0..1fd27da 100644 --- a/src/types/generated/schema.types.ts +++ b/src/types/generated/schema.types.ts @@ -70,6 +70,22 @@ export interface paths { patch?: never; trace?: never; }; + "/uploads/getFlowUploadUrl": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["UploadsController_getFlowUploadUrl"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/uploads/flow": { parameters: { query?: never; @@ -86,6 +102,55 @@ export interface paths { patch?: never; trace?: never; }; + "/uploads/submitFlowTest": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Client-direct flow submission (JSON). The flow zip has already been + * uploaded straight to storage via getFlowUploadUrl, so nothing is buffered + * in API memory here — we just create the uploads row from the stored + * reference and run the shared submission flow. + */ + post: operations["UploadsController_submitFlowTest"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/uploads/estimateMatrix": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Dry-run cost + cell-count estimate for a (possibly device-matrix) + * submission. Runs the exact same resolve → validate → fan-out → price core as + * the submit path (so the quote equals the charge) but never persists and + * never touches credits. Lets the CLI print the cell count and estimated cost, + * and surface validation errors, before uploading the flow ZIP. + * + * The dollar estimate is exact for non-Google-Play cells; a Google Play + * column's price is path-dependent until #1100 unifies the parallel and + * sequential Play tiering. + */ + post: operations["UploadsController_estimateMatrix"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/uploads/retryTest": { parameters: { query?: never; @@ -166,23 +231,23 @@ export interface paths { patch?: never; trace?: never; }; - "/results/{uploadId}": { + "/org/paddle-webhook": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["ResultsController_getResults"]; + get?: never; put?: never; - post?: never; + post: operations["OrgController_handlePaddleWebhook"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/results/{uploadId}/download": { + "/org/update-name": { parameters: { query?: never; header?: never; @@ -191,14 +256,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["ResultsController_getTestRunArtifacts"]; + post: operations["OrgController_updateOrgName"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/results/notify/{uploadId}": { + "/org/invite-team-member": { parameters: { query?: never; header?: never; @@ -207,114 +272,110 @@ export interface paths { }; get?: never; put?: never; - post: operations["ResultsController_notifyTestRunComplete"]; + post: operations["OrgController_inviteTeamMember"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/results/{uploadId}/report": { + "/org/accept-invite": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["ResultsController_downloadReport"]; + get?: never; put?: never; - post?: never; + post: operations["OrgController_acceptInvite"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/results/{uploadId}/html-report": { + "/org/revoke-invite": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["ResultsController_downloadHtmlReport"]; + get?: never; put?: never; - post?: never; + post: operations["OrgController_revokeInvite"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/results/{resultId}/html-report-single": { + "/org/change-team-member-role": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["ResultsController_downloadSingleHtmlReport"]; + get?: never; put?: never; - post?: never; + post: operations["OrgController_changeTeamMemberRole"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/results/compatibility/data": { + "/org/remove-team-member": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["ResultsController_getCompatibilityData"]; + get?: never; put?: never; - post?: never; + post: operations["OrgController_removeTeamMember"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/allure/{uploadId}/download": { + "/org/leave-team": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** - * Download Allure report as HTML - * @description Downloads a single-file Allure report as HTML containing all test results. Report is generated once and stored in Supabase Storage for subsequent downloads. - */ - get: operations["AllureController_downloadAllureReport"]; + get?: never; put?: never; - post?: never; + post: operations["OrgController_leaveTeam"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/webhooks": { + "/org/delete-team": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["WebhooksController_getWebhook"]; + get?: never; put?: never; - post: operations["WebhooksController_setWebhook"]; - delete: operations["WebhooksController_deleteWebhook"]; + post: operations["OrgController_deleteTeam"]; + delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/webhooks/regenerate-secret": { + "/org/subscriptions": { parameters: { query?: never; header?: never; @@ -323,14 +384,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["WebhooksController_regenerateWebhookSecret"]; + post: operations["OrgController_getAllSubscriptions"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/webhooks/test": { + "/org/update-overage-limit": { parameters: { query?: never; header?: never; @@ -339,14 +400,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["WebhooksController_testWebhook"]; + post: operations["OrgController_updateOverageLimit"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/org/paddle-webhook": { + "/org/usage-history": { parameters: { query?: never; header?: never; @@ -355,14 +416,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["OrgController_handlePaddleWebhook"]; + post: operations["OrgController_getUsageHistory"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/org/update-name": { + "/org/update-gpu-retries": { parameters: { query?: never; header?: never; @@ -371,14 +432,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["OrgController_updateOrgName"]; + post: operations["OrgController_updateGpuRetries"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/org/invite-team-member": { + "/org/update-billing-email": { parameters: { query?: never; header?: never; @@ -387,14 +448,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["OrgController_inviteTeamMember"]; + post: operations["OrgController_updateBillingEmail"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/org/accept-invite": { + "/org/invoices": { parameters: { query?: never; header?: never; @@ -403,14 +464,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["OrgController_acceptInvite"]; + post: operations["OrgController_getInvoices"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/org/subscriptions": { + "/org/invoice-url": { parameters: { query?: never; header?: never; @@ -419,14 +480,14 @@ export interface paths { }; get?: never; put?: never; - post: operations["OrgController_getAllSubscriptions"]; + post: operations["OrgController_getInvoiceUrl"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/org/update-overage-limit": { + "/org/bill-daily-overages": { parameters: { query?: never; header?: never; @@ -435,30 +496,30 @@ export interface paths { }; get?: never; put?: never; - post: operations["OrgController_updateOverageLimit"]; + post: operations["OrgController_billDailyOverages"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/org/usage-history": { + "/results/{uploadId}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + get: operations["ResultsController_getResults"]; put?: never; - post: operations["OrgController_getUsageHistory"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/frontend/check-domain-saml": { + "/results/{uploadId}/download": { parameters: { query?: never; header?: never; @@ -467,37 +528,37 @@ export interface paths { }; get?: never; put?: never; - post: operations["FrontendController_checkDomainSaml"]; + post: operations["ResultsController_getTestRunArtifacts"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/frontend/validate-email": { + "/results/{uploadId}/report": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + get: operations["ResultsController_downloadReport"]; put?: never; - post: operations["FrontendController_validateEmail"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/health": { + "/results/{uploadId}/html-report": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["HealthController_health"]; + get: operations["ResultsController_downloadHtmlReport"]; put?: never; post?: never; delete?: never; @@ -506,30 +567,36 @@ export interface paths { patch?: never; trace?: never; }; - "/billing/create-subscription": { + "/results/{resultId}/html-report-single": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + get: operations["ResultsController_downloadSingleHtmlReport"]; put?: never; - post: operations["BillingController_createSubscription"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/stats/marketing": { + "/results/{uploadId}/artifacts-bundle": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["StatsController_getMarketingStats"]; + /** + * CDN-Worker bundle manifests (dcd#1137). These return a signed manifest the + * client POSTs to the Worker, which streams the ZIP from B2 — the artifact + * bytes bypass the API. A `501` means the CDN Worker isn't configured on this + * deployment; the client falls back to the inline download endpoints. + */ + get: operations["ResultsController_getArtifactsBundleManifest"]; put?: never; post?: never; delete?: never; @@ -538,887 +605,3582 @@ export interface paths { patch?: never; trace?: never; }; -} -export type webhooks = Record; -export interface components { - schemas: { - IDBResult: { - binary_upload_id: string; - cost: number | null; - created_at: string; - env: Record; - id: number; - org_id: number; - platform: string; - simulator_name: string; - status: string; - test_file_name: string; - test_upload_id: string; - }; - IGetBinaryUploadUrlArgs: { - /** - * @description Platform for the binary upload (ios or android) - * @enum {string} - */ - platform: "ios" | "android"; - /** @description File size in bytes (optional, for Backblaze upload strategy) */ - fileSize?: number; - /** @description Whether client uses TUS resumable uploads (true for new clients, undefined/false for legacy) */ - useTus?: boolean; + "/results/{uploadId}/report-bundle": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - B2SimpleUpload: { - uploadUrl: string; - authorizationToken: string; + get: operations["ResultsController_getReportBundleManifest"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/results/{resultId}/report-bundle-single": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - B2UploadPartUrl: { - uploadUrl: string; - authorizationToken: string; + get: operations["ResultsController_getSingleReportBundleManifest"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/results/compatibility/data": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - B2LargeUpload: { - fileId: string; - fileName: string; - uploadPartUrls: components["schemas"]["B2UploadPartUrl"][]; + get: operations["ResultsController_getCompatibilityData"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/allure/{uploadId}/download": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - B2UploadStrategy: { - /** @enum {string} */ - strategy: "simple" | "large"; - simple?: components["schemas"]["B2SimpleUpload"]; - large?: components["schemas"]["B2LargeUpload"]; + /** + * Download Allure report as HTML + * @description Downloads a single-file Allure report as HTML containing all test results. Report is generated once and stored in Supabase Storage for subsequent downloads. + */ + get: operations["AllureController_downloadAllureReport"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/webhooks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - IGetBinaryUploadUrlResponse: { - /** @description Temporary upload path in uploads/ folder for TUS upload */ - path: string; - /** @description Temporary upload path (same as path) */ - tempPath: string; - /** @description Final path where file will be moved after upload completes */ - finalPath: string; - /** @description Upload ID */ - id: string; - /** @description Backblaze upload strategy if configured */ + get: operations["WebhooksController_getWebhook"]; + put?: never; + post: operations["WebhooksController_setWebhook"]; + delete: operations["WebhooksController_deleteWebhook"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/webhooks/regenerate-secret": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["WebhooksController_regenerateWebhookSecret"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/webhooks/test": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["WebhooksController_testWebhook"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/slack/oauth/start": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["SlackController_oauthStart"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/slack": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["SlackController_getConnection"]; + put?: never; + post?: never; + delete: operations["SlackController_disconnect"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/slack/channels": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["SlackController_getChannels"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/slack/config": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["SlackController_setConfig"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/slack/test": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["SlackController_test"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/github/oauth/start": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["GithubController_oauthStart"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/github": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["GithubController_getConnection"]; + put?: never; + post?: never; + delete: operations["GithubController_disconnect"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/notices": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Active notify notices (deprecation/warn/info/marketing) for the calling + * client. Block notices are never returned here — they are enforced + * server-side at submit time. The consumer applies any `match` gating it alone + * can evaluate (e.g. the selected device version). + */ + get: operations["NoticesController_getNotices"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api-keys": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["ApiKeysController_list"]; + put?: never; + post: operations["ApiKeysController_create"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api-keys/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["ApiKeysController_revoke"]; + options?: never; + head?: never; + patch: operations["ApiKeysController_update"]; + trace?: never; + }; + "/api-keys/{id}/rotate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["ApiKeysController_rotate"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/ip-addresses": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["NetworkController_getIpAddresses"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/check-domain-saml": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["FrontendController_checkDomainSaml"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/validate-email": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["FrontendController_validateEmail"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/binary-download-url": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["FrontendController_getBinaryDownloadUrl"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/binaries/{binaryId}/download": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["FrontendController_downloadBinary"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/artifact-download-url": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["FrontendController_getArtifactDownloadUrl"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/result-detail/{resultId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["FrontendController_getResultDetail"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["FrontendController_ingestLogs"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/frontend/logs/anon": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["FrontendController_ingestLogsAnonymous"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["HealthController_health"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/billing/create-subscription": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["BillingController_createSubscription"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/billing/update-subscription": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["BillingController_updateSubscription"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/stats/marketing": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["StatsController_getMarketingStats"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/flows": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["FlowsController_getFlows"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/flows/runs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["FlowsController_getFlowRuns"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/live": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["LiveController_createSession"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/live/{identifier}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["LiveController_getSession"]; + put?: never; + post?: never; + delete: operations["LiveController_stopSession"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/live/{identifier}/exec": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["LiveController_execTest"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/live/{identifier}/commands/{commandId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["LiveController_getCommandStatus"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/live/{identifier}/keepalive": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["LiveController_keepalive"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/live/{identifier}/install": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["LiveController_installBinary"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/me/orgs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["MeController_listOrgs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/me/sessions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** The caller's active auth sessions (for the Settings "Active sessions" panel). */ + get: operations["MeController_listSessions"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/me/sessions/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** + * Revoke one of the caller's active auth sessions (per-row "Sign out" in the panel). JWT-authed; + * the service scopes the delete to the caller's own id, so you can only kill your own sessions. + * Throttled since it mutates auth state. + */ + delete: operations["MeController_revokeSession"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/me/personal-team": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Provision a personal team for the caller — backs the "Create a personal team" button on the + * no-teams empty state (a user who left/was removed from their last org). Throttled. + */ + post: operations["MeController_createPersonalTeam"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/me/team": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Create an additional, named team for the caller — backs the "+ New team" org-switcher action. + * Always creates (vs /personal-team which is idempotent). Throttled. + */ + post: operations["MeController_createTeam"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/me/delete": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Irreversibly delete the caller's own account. JWT-authed; the body must echo the + * account email as a defence-in-depth confirmation (the UI also type-confirms). Throttled + * hard since it's destructive. + */ + post: operations["MeController_deleteAccount"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/cli-login/handoff": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["CliLoginController_handoff"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/cli-login/claim": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["CliLoginController_claim"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/cli/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["CliLogsController_ingestLogs"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/email-change/start": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["EmailChangeController_start"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/email-change/verify-current": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["EmailChangeController_verifyCurrent"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/email-change/verify-new": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["EmailChangeController_verifyNew"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/email-change/cancel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["EmailChangeController_cancel"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + IDBResult: { + binary_upload_id: string; + cost: number | null; + created_at: string; + env: Record; + id: number; + org_id: number; + platform: string; + simulator_name: string; + status: string; + test_file_name: string; + test_upload_id: string; + }; + IGetBinaryUploadUrlArgs: { + /** + * @description Platform for the binary upload (ios or android) + * @enum {string} + */ + platform: "ios" | "android"; + /** @description File size in bytes (optional, for Backblaze upload strategy) */ + fileSize?: number; + /** @description Whether client uses TUS resumable uploads (true for new clients, undefined/false for legacy) */ + useTus?: boolean; + }; + B2SimpleUpload: { + uploadUrl: string; + authorizationToken: string; + }; + B2UploadPartUrl: { + uploadUrl: string; + authorizationToken: string; + }; + B2LargeUpload: { + fileId: string; + fileName: string; + uploadPartUrls: components["schemas"]["B2UploadPartUrl"][]; + }; + B2UploadStrategy: { + /** @enum {string} */ + strategy: "simple" | "large"; + simple?: components["schemas"]["B2SimpleUpload"]; + large?: components["schemas"]["B2LargeUpload"]; + }; + IGetBinaryUploadUrlResponse: { + /** + * @description Temporary upload path in uploads/ folder for TUS upload + * @example uploads/123e4567-e89b-12d3-a456-426614174000/123e4567-e89b-12d3-a456-426614174000.apk + */ + path: string; + /** + * @description Temporary upload path (same as path) + * @example uploads/123e4567-e89b-12d3-a456-426614174000/123e4567-e89b-12d3-a456-426614174000.apk + */ + tempPath: string; + /** + * @description Final path where file will be moved after upload completes + * @example 1/binaries/android/123e4567-e89b-12d3-a456-426614174000.apk + */ + finalPath: string; + /** + * @description Upload ID + * @example 123e4567-e89b-12d3-a456-426614174000 + */ + id: string; + /** @description Backblaze upload strategy if configured */ b2?: components["schemas"]["B2UploadStrategy"]; /** @description Signed upload URL token for legacy clients (deprecated) */ token?: string; }; - ICheckForExistingUploadArgs: { - /** @description SHA-256 hash of the binary file */ - sha: string; + ICheckForExistingUploadArgs: { + /** @description SHA-256 hash of the binary file as uploaded. Required unless `encrypted` is true, in which case `shaPlain` is the lookup key (the ciphertext hash is not yet known at dedup time). */ + sha?: string; + /** @description SHA-256 hash of the PLAINTEXT binary. The lookup key when `encrypted` is true (#1168): encrypted uploads wrap under a fresh random DEK, so the ciphertext hash differs on every upload of identical input and cannot dedup. */ + shaPlain?: string; + /** + * @description Whether the caller intends to upload an encrypted binary. When true the lookup uses `shaPlain` and only ever matches rows that carry an encryption envelope, so an encrypting client can never be handed back a plaintext binary. + * @default false + */ + encrypted: boolean; + }; + ICheckForExistingUploadResponse: { + appBinaryId: string; + exists: boolean; + /** + * @description Whether the matched binary is stored encrypted (#1168). Lets an encrypting + * client assert the invariant it cares about client-side instead of trusting + * the server to have applied the right predicate — so an older or misbehaving + * deployment cannot quietly hand it a plaintext binary. + */ + encrypted?: boolean; + }; + IFinaliseUploadArgs: { + /** @description Unique upload identifier */ + id: string; + /** @description Storage path for the uploaded file */ + path: string; + /** @description File metadata (bundle ID, package name, platform) - required for new clients */ + metadata?: Record; + /** @description SHA-256 hash of the file - required for new clients */ + sha?: string; + /** @description SHA-256 hash of the PLAINTEXT file. Sent only by clients uploading an encrypted binary (#1168), where `sha` is the ciphertext hash; persisted as binaries.sha_plain so later encrypted uploads of the same input can dedup. */ + shaPlain?: string; + /** + * @description Whether the Supabase upload was successful + * @default true + */ + supabaseSuccess: boolean; + /** + * @description Whether the Backblaze upload was successful + * @default false + */ + backblazeSuccess: boolean; + /** @description Whether client uses TUS resumable uploads (true for new clients, undefined/false for legacy) */ + useTus?: boolean; + /** @description File size in bytes */ + bytes?: number; + }; + IFinaliseUploadResponse: Record; + IFinishLargeFileArgs: { + /** + * @description The Backblaze file ID from the large file upload + * @example abc123xyz + */ + fileId: string; + /** + * @description Array of SHA1 hashes for each uploaded part + * @example [ + * "sha1hash1", + * "sha1hash2" + * ] + */ + partSha1Array: string[]; + }; + IFinishLargeFileResponse: { + success: boolean; + result: Record; + }; + IGetFlowUploadUrlArgs: { + /** @description File size in bytes (optional, for Backblaze upload strategy) */ + fileSize?: number; + /** @description Whether client uses TUS resumable uploads (true for new clients, undefined/false for legacy) */ + useTus?: boolean; + }; + ICreateTestUploadArgs: { + testFileNames?: string; + sequentialFlows?: string; + /** @enum {string} */ + androidApiLevel?: "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36"; + /** @enum {string} */ + androidDevice?: "pixel-6" | "pixel-6-pro" | "pixel-7" | "pixel-7-pro" | "generic-tablet"; + apiKey?: string; + apiUrl?: string; + appBinaryId: string; + appFile?: string; + env: string; + /** @enum {string} */ + iOSVersion?: "16" | "17" | "18" | "26"; + /** @enum {string} */ + iOSDevice?: "iphone-14" | "iphone-15" | "iphone-16" | "iphone-16-plus" | "iphone-16-pro" | "iphone-16-pro-max" | "ipad-pro-6th-gen"; + platform?: string; + googlePlay?: boolean; + config: string; + name?: string; + /** @enum {string} */ + runnerType?: "m4" | "m1" | "default" | "gpu1" | "cpu1"; + metadata?: string; + workspaceConfig?: string; + flowMetadata?: string; + testFileOverrides?: string; + /** @description JSON array of explicit device configs forming the upload device matrix. Every flow that does not name its own device runs once per entry. Each entry names exactly one validated cell and must match the binary platform — there is no cross-product expansion. iOS: {"iOSDevice":"iphone-16","iOSVersion":"18"}. Android: {"androidDevice":"pixel-7","androidApiLevel":"34","googlePlay":true}. Omit for single-device (legacy) behaviour. */ + deviceMatrix?: string; + /** @description SHA-256 hash of the flow ZIP file */ + sha?: string; + /** @description JSON-encoded envelope { v, kek, wrapped_key } when the flow ZIP was client-side encrypted (#1151). Stored as uploads.metadata.enc; the flow zip carries its own per-upload DEK, distinct from the binary. */ + enc?: string; + /** @description Size of the flow ZIP file in bytes */ + bytes?: number; + /** + * Format: binary + * @description This file must be a zip file + */ + file: string; + }; + ISubmitFlowTestArgs: { + testFileNames?: string; + sequentialFlows?: string; + /** @enum {string} */ + androidApiLevel?: "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36"; + /** @enum {string} */ + androidDevice?: "pixel-6" | "pixel-6-pro" | "pixel-7" | "pixel-7-pro" | "generic-tablet"; + apiKey?: string; + apiUrl?: string; + appBinaryId: string; + appFile?: string; + env: string; + /** @enum {string} */ + iOSVersion?: "16" | "17" | "18" | "26"; + /** @enum {string} */ + iOSDevice?: "iphone-14" | "iphone-15" | "iphone-16" | "iphone-16-plus" | "iphone-16-pro" | "iphone-16-pro-max" | "ipad-pro-6th-gen"; + platform?: string; + googlePlay?: boolean; + config: string; + name?: string; + /** @enum {string} */ + runnerType?: "m4" | "m1" | "default" | "gpu1" | "cpu1"; + metadata?: string; + workspaceConfig?: string; + flowMetadata?: string; + testFileOverrides?: string; + /** @description JSON array of explicit device configs forming the upload device matrix. Every flow that does not name its own device runs once per entry. Each entry names exactly one validated cell and must match the binary platform — there is no cross-product expansion. iOS: {"iOSDevice":"iphone-16","iOSVersion":"18"}. Android: {"androidDevice":"pixel-7","androidApiLevel":"34","googlePlay":true}. Omit for single-device (legacy) behaviour. */ + deviceMatrix?: string; + /** @description SHA-256 hash of the flow ZIP file */ + sha?: string; + /** @description JSON-encoded envelope { v, kek, wrapped_key } when the flow ZIP was client-side encrypted (#1151). Stored as uploads.metadata.enc; the flow zip carries its own per-upload DEK, distinct from the binary. */ + enc?: string; + /** @description Size of the flow ZIP file in bytes */ + bytes?: number; + /** @description Flow upload identifier returned by getFlowUploadUrl */ + id: string; + /** @description Storage path where the flow zip was uploaded (tempPath for TUS, finalPath for legacy signed URL) */ + path: string; + /** + * @description Whether the Supabase upload was successful + * @default true + */ + supabaseSuccess: boolean; + /** + * @description Whether the Backblaze upload was successful + * @default false + */ + backblazeSuccess: boolean; + /** @description Whether client uses TUS resumable uploads (true for new clients, undefined/false for legacy) */ + useTus?: boolean; + }; + IFlowTestParams: { + testFileNames?: string; + sequentialFlows?: string; + /** @enum {string} */ + androidApiLevel?: "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36"; + /** @enum {string} */ + androidDevice?: "pixel-6" | "pixel-6-pro" | "pixel-7" | "pixel-7-pro" | "generic-tablet"; + apiKey?: string; + apiUrl?: string; + appBinaryId: string; + appFile?: string; + env: string; + /** @enum {string} */ + iOSVersion?: "16" | "17" | "18" | "26"; + /** @enum {string} */ + iOSDevice?: "iphone-14" | "iphone-15" | "iphone-16" | "iphone-16-plus" | "iphone-16-pro" | "iphone-16-pro-max" | "ipad-pro-6th-gen"; + platform?: string; + googlePlay?: boolean; + config: string; + name?: string; + /** @enum {string} */ + runnerType?: "m4" | "m1" | "default" | "gpu1" | "cpu1"; + metadata?: string; + workspaceConfig?: string; + flowMetadata?: string; + testFileOverrides?: string; + /** @description JSON array of explicit device configs forming the upload device matrix. Every flow that does not name its own device runs once per entry. Each entry names exactly one validated cell and must match the binary platform — there is no cross-product expansion. iOS: {"iOSDevice":"iphone-16","iOSVersion":"18"}. Android: {"androidDevice":"pixel-7","androidApiLevel":"34","googlePlay":true}. Omit for single-device (legacy) behaviour. */ + deviceMatrix?: string; + /** @description SHA-256 hash of the flow ZIP file */ + sha?: string; + /** @description JSON-encoded envelope { v, kek, wrapped_key } when the flow ZIP was client-side encrypted (#1151). Stored as uploads.metadata.enc; the flow zip carries its own per-upload DEK, distinct from the binary. */ + enc?: string; + /** @description Size of the flow ZIP file in bytes */ + bytes?: number; + }; + IRetryTestArgs: { + /** @description ID of a specific result to retry. Either resultId or uploadId must be provided, but not both. */ + resultId?: number; + /** @description ID of an upload to retry all failed tests for. Either resultId or uploadId must be provided, but not both. */ + uploadId?: string; + }; + ICancelTestArgs: { + /** @description ID of a specific result to cancel. Either resultId or uploadId must be provided, but not both. */ + resultId?: number; + /** @description ID of an upload to cancel all pending results for. Either resultId or uploadId must be provided, but not both. */ + uploadId?: string; + }; + UpdateOrgNameDto: { + /** + * @description Organization ID + * @example 123 + */ + orgId: number; + /** + * @description Organization name + * @example Acme Corporation + */ + name: string; + }; + InviteTeamMemberDto: { + /** + * @description Email address to invite + * @example teammate@example.com + */ + inviteEmail: string; + /** + * @description Invite acceptance link shown in the email + * @example https://app.devicecloud.dev/login?invite_email=... + */ + link: string; + /** + * @description Organization ID + * @example 1 + */ + orgId: string; + /** @description Organization name shown in the email */ + orgName: string; + }; + AcceptInviteDto: { + /** + * @description Organization ID + * @example 1 + */ + orgId: string; + /** + * @description User email address + * @example user@example.com + */ + email: string; + }; + RevokeInviteDto: { + /** + * @description Organization ID + * @example 1 + */ + orgId: string; + /** + * @description Email of the pending invite to revoke + * @example teammate@example.com + */ + email: string; + }; + ChangeRoleDto: { + /** + * @description Organization ID + * @example 1 + */ + orgId: string; + /** + * @description Email of the team member whose role is being changed + * @example teammate@example.com + */ + email: string; + /** + * @description New role to assign + * @example admin + * @enum {string} + */ + newRole: "admin" | "standard" | "owner"; + }; + RemoveMemberDto: { + /** + * @description Organization ID + * @example 1 + */ + orgId: string; + /** + * @description Email of the team member to remove + * @example teammate@example.com + */ + email: string; + }; + LeaveTeamDto: { + /** + * @description Organization ID to leave + * @example 1 + */ + orgId: string; + }; + DeleteTeamDto: { + /** + * @description Organization ID to delete + * @example 1 + */ + orgId: string; + }; + TResultResponse: { + id: number; + test_file_name: string; + status: string; + retry_of?: number; + fail_reason?: string; + duration_seconds?: number; + simulator_name?: string; + config?: Record; + }; + TFlowSummaryResponse: { + flow_name: string; + file_name: string; + last_run_at: string; + total_runs: number; + passed_runs: number; + failed_runs: number; + pass_rate: number; + avg_duration: number; + daily_data: Record; + tags: string[]; + }; + TFlowRunItem: { + id: number; + status: string; + createdAt: string; + durationSeconds: number | null; + failReason: string | null; + testUploadId: string; + uploadName: string; + }; + HandoffDto: { + /** @description Opaque state token minted by the CLI. */ + state: string; + /** @description base64url(sha256(code_verifier)) — the PKCE S256 challenge. */ + code_challenge: string; + /** @description The browser session's Supabase access token (JWT), used only to verify the user's identity. */ + access_token: string; + /** @description The browser session's refresh token. Sent only for SAML SSO sessions, which cannot be minted a dedicated CLI session server-side. */ + refresh_token?: string; + }; + ClaimDto: { + /** @description Opaque state token minted by the CLI. */ + state: string; + /** @description base64url(random bytes) — the PKCE verifier. */ + code_verifier: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + UploadsController_getBinaryUploadUrl: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IGetBinaryUploadUrlArgs"]; + }; + }; + responses: { + /** @description The url has been successfully created. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["IGetBinaryUploadUrlResponse"]; + }; + }; + }; + }; + UploadsController_checkForExistingUpload: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ICheckForExistingUploadArgs"]; + }; + }; + responses: { + /** @description The url has been successfully created. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ICheckForExistingUploadResponse"]; + }; + }; + }; + }; + UploadsController_finaliseUpload: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IFinaliseUploadArgs"]; + }; + }; + responses: { + /** @description The upload has been completed. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["IFinaliseUploadResponse"]; + }; + }; + }; + }; + UploadsController_finishLargeFile: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IFinishLargeFileArgs"]; + }; + }; + responses: { + /** @description The large file upload has been completed. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["IFinishLargeFileResponse"]; + }; + }; + }; + }; + UploadsController_getFlowUploadUrl: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IGetFlowUploadUrlArgs"]; + }; + }; + responses: { + /** @description The url has been successfully created. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["IGetBinaryUploadUrlResponse"]; + }; + }; + }; + }; + UploadsController_createTest: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "multipart/form-data": components["schemas"]["ICreateTestUploadArgs"]; + }; + }; + responses: { + /** @description The record has been successfully created. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message?: string; + results?: components["schemas"]["IDBResult"][]; + }; + }; + }; + }; + }; + UploadsController_submitFlowTest: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ISubmitFlowTestArgs"]; + }; + }; + responses: { + /** @description The record has been successfully created. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message?: string; + results?: components["schemas"]["IDBResult"][]; + }; + }; + }; + }; + }; + UploadsController_estimateMatrix: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IFlowTestParams"]; + }; + }; + responses: { + /** @description Estimated cell count and cost for a device-matrix submission. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + cellCount?: number; + totalCost?: number; + excludedFlows?: string[]; + columns?: { + deviceName?: string; + osVersion?: string; + googlePlay?: boolean; + flowCount?: number; + cost?: number; + }[]; + }; + }; + }; + }; + }; + UploadsController_retryTest: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IRetryTestArgs"]; + }; + }; + responses: { + /** @description Retry started. Provide resultId to retry a single test (returns the new result id), or uploadId to retry all failed tests in an upload (returns retriedCount). */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message?: string; + id?: number; + success?: boolean; + retriedCount?: number; + }; + }; + }; + }; + }; + UploadsController_cancelTest: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ICancelTestArgs"]; + }; + }; + responses: { + /** @description The record has been successfully cancelled. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message?: string; + success?: boolean; + cancelledCount?: number; + }; + }; + }; + }; + }; + UploadsController_getUploadStatus: { + parameters: { + query?: { + /** @description Upload ID to get status for */ + uploadId?: string; + /** @description Upload name to get status for */ + name?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Upload status */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "uploadId": "upload-123", + * "status": "PENDING", + * "tests": [ + * { + * "id": 1, + * "test_file_name": "test-flow.yaml", + * "status": "PENDING" + * } + * ] + * } + */ + "application/json": Record; + }; + }; + }; + }; + UploadsController_listUploads: { + parameters: { + query?: { + /** @description Filter by upload name (supports * wildcard) */ + name?: string; + /** @description Filter uploads created on or after this date (ISO 8601) */ + from?: string; + /** @description Filter uploads created on or before this date (ISO 8601) */ + to?: string; + /** @description Maximum number of uploads to return (default: 20) */ + limit?: number; + /** @description Number of uploads to skip (default: 0) */ + offset?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of flow uploads. Use GET /uploads/status for detailed test results. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "uploads": [ + * { + * "id": "upload-123", + * "name": "Test Upload", + * "created_at": "2024-01-01T00:00:00Z", + * "consoleUrl": "https://console.devicecloud.dev/results/upload-123" + * } + * ], + * "total": 1, + * "limit": 20, + * "offset": 0 + * } + */ + "application/json": { + uploads?: { + id?: string; + name?: string | null; + created_at?: string; + consoleUrl?: string; + }[]; + total?: number; + limit?: number; + offset?: number; + }; + }; + }; + }; + }; + UploadsController_deleteUpload: { + parameters: { + query?: never; + header?: never; + path: { + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description The upload has been successfully deleted. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + success?: boolean; + message?: string; + }; + }; + }; + }; + }; + OrgController_handlePaddleWebhook: { + parameters: { + query?: never; + header: { + "paddle-signature": string; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paddle webhook handler. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string; + }; + }; + }; + }; + OrgController_updateOrgName: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateOrgNameDto"]; + }; + }; + responses: { + /** @description Organization name updated successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_inviteTeamMember: { + parameters: { + query?: never; + header: { + authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["InviteTeamMemberDto"]; + }; + }; + responses: { + /** @description Team member invited successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_acceptInvite: { + parameters: { + query?: never; + header: { + authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AcceptInviteDto"]; + }; + }; + responses: { + /** @description Team invite accepted successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_revokeInvite: { + parameters: { + query?: never; + header: { + authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RevokeInviteDto"]; + }; + }; + responses: { + /** @description Team invite revoked successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_changeTeamMemberRole: { + parameters: { + query?: never; + header: { + authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ChangeRoleDto"]; + }; + }; + responses: { + /** @description Team member role updated successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_removeTeamMember: { + parameters: { + query?: never; + header: { + authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RemoveMemberDto"]; + }; + }; + responses: { + /** @description Team member removed successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_leaveTeam: { + parameters: { + query?: never; + header: { + authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["LeaveTeamDto"]; + }; + }; + responses: { + /** @description Left the team successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_deleteTeam: { + parameters: { + query?: never; + header: { + authorization: string; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["DeleteTeamDto"]; + }; + }; + responses: { + /** @description Team deleted successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": boolean; + }; + }; + }; + }; + OrgController_getAllSubscriptions: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + orgId: string; + }; + }; + }; + responses: { + /** @description All subscription data fetched successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + OrgController_updateOverageLimit: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + orgId: string; + overageLimit: number; + }; + }; + }; + responses: { + /** @description Overage limit updated successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + OrgController_getUsageHistory: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + orgId: string; + /** @enum {string} */ + format?: "json" | "csv"; + /** Format: date-time */ + startDate?: string; + /** Format: date-time */ + endDate?: string; + }; + }; + }; + responses: { + /** @description Usage history fetched successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": unknown[]; + }; + }; + }; + }; + OrgController_updateGpuRetries: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + orgId: number; + gpuRetries: boolean; + }; + }; + }; + responses: { + /** @description GPU retries setting updated successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + OrgController_updateBillingEmail: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + orgId: number; + billingEmail: string; + }; + }; + }; + responses: { + /** @description Billing email updated successfully. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + OrgController_getInvoices: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + orgId: number; + }; + }; + }; + responses: { + /** @description List of Paddle invoices for the organization. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + OrgController_getInvoiceUrl: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + orgId: number; + transactionId: string; + }; + }; + }; + responses: { + /** @description Hosted PDF URL for a single invoice. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + OrgController_billDailyOverages: { + parameters: { + query?: never; + header: { + "x-cron-secret": string; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Daily overage billing processed. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + ResultsController_getResults: { + parameters: { + query?: never; + header?: never; + path: { + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description The record has been successfully created. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + statusCode?: number; + results?: components["schemas"]["TResultResponse"][]; + }; + }; + }; + }; + }; + ResultsController_getTestRunArtifacts: { + parameters: { + query?: never; + header?: never; + path: { + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + ResultsController_downloadReport: { + parameters: { + query?: never; + header?: never; + path: { + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Download combined JUNIT test report (report.xml) for the upload */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string; + }; + }; + }; + }; + ResultsController_downloadHtmlReport: { + parameters: { + query?: never; + header?: never; + path: { + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Download combined HTML test report with assets (report.zip) for the upload */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string; + }; + }; + }; + }; + ResultsController_downloadSingleHtmlReport: { + parameters: { + query?: never; + header?: never; + path: { + resultId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Download HTML test report with assets (report.zip) for a single result */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": string; + }; + }; + }; + }; + ResultsController_getArtifactsBundleManifest: { + parameters: { + query: { + results: string; + }; + header?: never; + path: { + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + ResultsController_getReportBundleManifest: { + parameters: { + query?: never; + header?: never; + path: { + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + ResultsController_getSingleReportBundleManifest: { + parameters: { + query?: never; + header?: never; + path: { + resultId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + ResultsController_getCompatibilityData: { + parameters: { + query?: never; + header: { + "x-dcd-cli-version": string; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Device compatibility lookup data including Maestro versions */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "statusCode": 200, + * "data": { + * "ios": { + * "iphone-14": { + * "name": "iPhone 14", + * "versions": [ + * "16", + * "17", + * "18" + * ], + * "deprecated": false + * }, + * "iphone-15": { + * "name": "iPhone 15", + * "versions": [ + * "17" + * ], + * "deprecated": false + * }, + * "iphone-16": { + * "name": "iPhone 16", + * "versions": [ + * "18", + * "26" + * ], + * "deprecated": false + * }, + * "iphone-16-plus": { + * "name": "iPhone 16 Plus", + * "versions": [ + * "26" + * ], + * "deprecated": false + * }, + * "iphone-16-pro": { + * "name": "iPhone 16 Pro", + * "versions": [ + * "18", + * "26" + * ], + * "deprecated": false + * }, + * "iphone-16-pro-max": { + * "name": "iPhone 16 Pro Max", + * "versions": [ + * "18", + * "26" + * ], + * "deprecated": false + * }, + * "ipad-pro-6th-gen": { + * "name": "iPad Pro (6th gen)", + * "versions": [ + * "18", + * "26" + * ], + * "deprecated": false + * } + * }, + * "android": { + * "pixel-6": { + * "name": "Pixel 6", + * "apiLevels": [ + * "29", + * "30", + * "31", + * "32", + * "33", + * "34", + * "35", + * "36" + * ], + * "deprecated": false + * }, + * "pixel-6-pro": { + * "name": "Pixel 6 Pro", + * "apiLevels": [ + * "33", + * "34", + * "35", + * "36" + * ], + * "deprecated": false + * }, + * "pixel-7": { + * "name": "Pixel 7", + * "apiLevels": [ + * "33", + * "34", + * "35", + * "36" + * ], + * "deprecated": false + * }, + * "pixel-7-pro": { + * "name": "Pixel 7 Pro", + * "apiLevels": [ + * "33", + * "34", + * "35", + * "36" + * ], + * "deprecated": false + * }, + * "generic-tablet": { + * "name": "Generic Tablet", + * "apiLevels": [ + * "33", + * "34", + * "35", + * "36" + * ], + * "deprecated": false + * } + * }, + * "androidPlay": { + * "pixel-6": { + * "name": "Pixel 6 (Google Play)", + * "apiLevels": [ + * "34", + * "35", + * "36" + * ], + * "deprecated": false + * }, + * "pixel-7": { + * "name": "Pixel 7 (Google Play)", + * "apiLevels": [ + * "34", + * "35", + * "36" + * ], + * "deprecated": false + * } + * }, + * "maestro": { + * "supportedVersions": [ + * "2.0.4", + * "2.0.9", + * "2.1.0", + * "2.2.0", + * "2.5.0", + * "2.5.1", + * "2.6.0", + * "2.6.1", + * "2.7.0", + * "2.8.0" + * ], + * "defaultVersion": "2.2.0", + * "latestVersion": "2.8.0" + * } + * } + * } + */ + "application/json": { + statusCode?: number; + data?: { + ios?: Record; + android?: Record; + androidPlay?: Record; + maestro?: { + supportedVersions?: string[]; + defaultVersion?: string; + latestVersion?: string; + }; + }; + }; + }; + }; + }; + }; + AllureController_downloadAllureReport: { + parameters: { + query?: never; + header?: never; + path: { + /** @description The upload ID to generate Allure report for */ + uploadId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Allure report HTML file download */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/html": string; + }; + }; + /** @description Upload not found or no results available */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + WebhooksController_getWebhook: { + parameters: { + query?: { + /** @description Set to true to return full secret instead of masked version */ + show_secret?: boolean; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Current webhook configuration */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + webhook_url?: string; + /** @description Full secret (only when show_secret=true) */ + secret_key?: string; + /** @description Masked secret (default) */ + secret_key_masked?: string; + /** Format: date-time */ + created_at?: string; + /** Format: date-time */ + updated_at?: string; + }; + }; + }; + }; + }; + WebhooksController_setWebhook: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** + * Format: uri + * @example https://api.example.com/webhook + */ + url: string; + }; + }; + }; + responses: { + /** @description Webhook URL set successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + WebhooksController_deleteWebhook: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Webhook configuration deleted successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + WebhooksController_regenerateWebhookSecret: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Webhook secret regenerated successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + WebhooksController_testWebhook: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** Format: uri */ + url?: string; + }; + }; + }; + responses: { + /** @description Test webhook sent successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + }; + }; + SlackController_oauthStart: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - ICheckForExistingUploadResponse: { - appBinaryId: string; - exists: boolean; + requestBody?: never; + responses: { + /** @description Slack authorize URL to redirect the user to */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; - IFinaliseUploadArgs: { - /** @description Unique upload identifier */ - id: string; - /** @description Storage path for the uploaded file */ - path: string; - /** @description File metadata (bundle ID, package name, platform) - required for new clients */ - metadata?: Record; - /** @description SHA-256 hash of the file - required for new clients */ - sha?: string; - /** - * @description Whether the Supabase upload was successful - * @default true - */ - supabaseSuccess: boolean; - /** - * @description Whether the Backblaze upload was successful - * @default false - */ - backblazeSuccess: boolean; - /** @description Whether client uses TUS resumable uploads (true for new clients, undefined/false for legacy) */ - useTus?: boolean; - /** @description File size in bytes */ - bytes?: number; + }; + SlackController_getConnection: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - IFinaliseUploadResponse: Record; - IFinishLargeFileArgs: { - /** - * @description The Backblaze file ID from the large file upload - * @example abc123xyz - */ - fileId: string; - /** - * @description Array of SHA1 hashes for each uploaded part - * @example [ - * "sha1hash1", - * "sha1hash2" - * ] - */ - partSha1Array: string[]; + requestBody?: never; + responses: { + /** @description Current Slack connection for the org (or null) */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; - IFinishLargeFileResponse: { - success: boolean; - result: Record; + }; + SlackController_disconnect: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - ICreateTestUploadArgs: { - /** - * Format: binary - * @description This file must be a zip file - */ - file: string; - testFileNames?: string; - sequentialFlows?: string; - /** @enum {string} */ - androidApiLevel?: "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36"; - /** @enum {string} */ - androidDevice?: "pixel-6" | "pixel-6-pro" | "pixel-7" | "pixel-7-pro" | "generic-tablet"; - apiKey?: string; - apiUrl?: string; - appBinaryId: string; - appFile?: string; - env: string; - /** @enum {string} */ - iOSVersion?: "16" | "17" | "18" | "26"; - /** @enum {string} */ - iOSDevice?: "iphone-14" | "iphone-15" | "iphone-16" | "iphone-16-plus" | "iphone-16-pro" | "iphone-16-pro-max" | "ipad-pro-6th-gen"; - platform?: string; - googlePlay: boolean; - config: string; - name?: string; - /** @enum {string} */ - runnerType?: "m4" | "m1" | "default" | "gpu1" | "cpu1"; - metadata?: string; - workspaceConfig?: string; - flowMetadata?: string; - testFileOverrides?: string; - /** @description SHA-256 hash of the flow ZIP file */ - sha?: string; + requestBody?: never; + responses: { + /** @description Slack disconnected and connection removed */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; - IRetryTestArgs: { - resultId: number; + }; + SlackController_getChannels: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Channels the bot can see, for the picker */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + SlackController_setConfig: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Slack channel / preferences updated */ + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + SlackController_test: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Test message sent to the configured channel */ + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + GithubController_oauthStart: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description GitHub App install URL to redirect the user to */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + GithubController_getConnection: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Current GitHub App connection for the org (or null) */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + GithubController_disconnect: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description GitHub connection removed for the org */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + NoticesController_getNotices: { + parameters: { + query: { + surface: string; + platform: string; + }; + header: { + "x-dcd-cli-version": string; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Active notices for the calling client. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + statusCode?: number; + data?: { + id?: string; + slug?: string | null; + /** @enum {string} */ + level?: "deprecation" | "warn" | "info" | "marketing"; + title?: string; + body?: string; + learnMoreUrl?: string | null; + dismissible?: boolean; + match?: Record | null; + }[]; + }; + }; + }; + }; + }; + ApiKeysController_list: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List the org API keys (no secrets) */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; - ICancelTestArgs: { - /** @description ID of a specific result to cancel. Either resultId or uploadId must be provided, but not both. */ - resultId?: number; - /** @description ID of an upload to cancel all pending results for. Either resultId or uploadId must be provided, but not both. */ - uploadId?: string; + }; + ApiKeysController_create: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; }; - TResultResponse: { - id: number; - test_file_name: string; - status: string; - retry_of?: number; - fail_reason?: string; - duration_seconds?: number; + requestBody?: never; + responses: { + /** @description Issue a new key; returns the raw key once */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; }; - UpdateOrgNameDto: { - /** - * @description Organization ID - * @example 123 - */ - orgId: number; - /** - * @description Organization name - * @example Acme Corporation - */ - name: string; + }; + ApiKeysController_revoke: { + parameters: { + query?: never; + header?: never; + path: { + id: number; + }; + cookie?: never; }; - AcceptInviteDto: { - /** - * @description Organization ID - * @example 1 - */ - orgId: string; - /** - * @description User email address - * @example user@example.com - */ - email: string; + requestBody?: never; + responses: { + /** @description Revoke (soft-delete) a key */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; -} -export type $defs = Record; -export interface operations { - UploadsController_getBinaryUploadUrl: { + ApiKeysController_update: { parameters: { query?: never; - header: { - "x-app-api-key": string; + header?: never; + path: { + id: number; }; - path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["IGetBinaryUploadUrlArgs"]; + requestBody?: never; + responses: { + /** @description Update a key name/description/expiry */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + ApiKeysController_rotate: { + parameters: { + query?: never; + header?: never; + path: { + id: number; }; + cookie?: never; }; + requestBody?: never; responses: { - /** @description The url has been successfully created. */ + /** @description Rotate a key; returns the new raw key once */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["IGetBinaryUploadUrlResponse"]; + "application/json": Record; }; }; }; }; - UploadsController_checkForExistingUpload: { + NetworkController_getIpAddresses: { parameters: { query?: never; - header: { - "x-app-api-key": string; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Current DeviceCloud test-runner egress IP addresses. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "updatedAt": "2026-07-06", + * "ipAddresses": [ + * "46.17.215.144", + * "46.17.215.145", + * "83.217.174.249" + * ], + * "ranges": [ + * { + * "cidr": "46.17.215.144/32", + * "platforms": [ + * "android", + * "ios" + * ], + * "type": "egress", + * "description": "Test runner egress" + * } + * ] + * } + */ + "application/json": { + /** @example 2026-07-06 */ + updatedAt?: string; + /** + * @example [ + * "46.17.215.144", + * "46.17.215.145", + * "83.217.174.249" + * ] + */ + ipAddresses?: string[]; + ranges?: { + /** @example 46.17.215.144/32 */ + cidr?: string; + platforms?: ("android" | "ios")[]; + /** @enum {string} */ + type?: "egress"; + description?: string; + }[]; + }; + }; }; + }; + }; + FrontendController_checkDomainSaml: { + parameters: { + query?: never; + header?: never; path?: never; cookie?: never; }; + /** @description Domain to check for SAML configuration */ requestBody: { content: { - "application/json": components["schemas"]["ICheckForExistingUploadArgs"]; + "application/json": { + /** @example example.com */ + domain: string; + }; }; }; responses: { - /** @description The url has been successfully created. */ + /** @description SAML status for the domain */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + forceSaml?: boolean; + }; + }; + }; 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Bad request - invalid domain or API error */ + 400: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["ICheckForExistingUploadResponse"]; + "application/json": { + error?: string; + }; }; }; }; }; - UploadsController_finaliseUpload: { + FrontendController_validateEmail: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; + header?: never; path?: never; cookie?: never; }; + /** @description Email address to validate */ requestBody: { content: { - "application/json": components["schemas"]["IFinaliseUploadArgs"]; + "application/json": { + /** @example user@example.com */ + email: string; + }; }; }; responses: { - /** @description The upload has been completed. */ + /** @description Email validation result */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + valid?: boolean; + reason?: string; + }; + }; + }; 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Bad request - invalid email or API error */ + 400: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["IFinaliseUploadResponse"]; + "application/json": { + error?: string; + }; }; }; }; }; - UploadsController_finishLargeFile: { + FrontendController_getBinaryDownloadUrl: { parameters: { query?: never; header: { - "x-app-api-key": string; + authorization: string; }; path?: never; cookie?: never; }; + /** @description Get a signed download URL for a binary */ requestBody: { content: { - "application/json": components["schemas"]["IFinishLargeFileArgs"]; + "application/json": { + binaryId: string; + orgId: number; + }; }; }; responses: { - /** @description The large file upload has been completed. */ + /** @description Signed download URL for the binary; `dek` (base64) is present when the binary is encrypted */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + url?: string; + encrypted?: boolean; + dek?: string; + }; + }; + }; 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["IFinishLargeFileResponse"]; + "application/json": Record; + }; + }; + /** @description Binary not found or not accessible */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error?: string; + }; }; }; }; }; - UploadsController_createTest: { + FrontendController_downloadBinary: { parameters: { - query?: never; + query: { + orgId: number; + }; header: { - "x-app-api-key": string; + authorization: string; }; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "multipart/form-data": components["schemas"]["ICreateTestUploadArgs"]; + path: { + binaryId: string; }; + cookie?: never; }; + requestBody?: never; responses: { - /** @description The record has been successfully created. */ - 201: { + /** @description Binary bytes (decrypted if encrypted) */ + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Binary not found or not accessible */ + 400: { headers: { [name: string]: unknown; }; - content: { - "application/json": { - message?: string; - results?: components["schemas"]["IDBResult"][]; - }; - }; + content?: never; }; }; }; - UploadsController_retryTest: { + FrontendController_getArtifactDownloadUrl: { parameters: { query?: never; header: { - "x-app-api-key": string; + authorization: string; }; path?: never; cookie?: never; }; + /** @description Get a signed download URL for a single result artifact */ requestBody: { content: { - "application/json": components["schemas"]["IRetryTestArgs"]; + "application/json": { + resultId: number; + /** @description Supabase storage path; must be one of the result's recorded files */ + path: string; + /** @description Optional filename override for the saved file */ + download?: string; + }; }; }; responses: { - /** @description The record has been successfully created. */ - 201: { + /** @description Signed download URL for the artifact (CDN/B2 or Supabase) */ + 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - message?: string; - results?: components["schemas"]["IDBResult"][]; + url?: string; }; }; }; - }; - }; - UploadsController_cancelTest: { - parameters: { - query?: never; - header: { - "x-app-api-key": string; - }; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["ICancelTestArgs"]; - }; - }; - responses: { - /** @description The record has been successfully cancelled. */ 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Artifact not found or not accessible */ + 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - message?: string; - success?: boolean; - cancelledCount?: number; + error?: string; }; }; }; }; }; - UploadsController_getUploadStatus: { + FrontendController_getResultDetail: { parameters: { - query?: { - /** @description Upload ID to get status for */ - uploadId?: string; - /** @description Upload name to get status for */ - name?: string; - }; + query?: never; header: { - "x-app-api-key": string; + authorization: string; + }; + path: { + resultId: number; }; - path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Upload status */ + /** @description Bundled result detail: row + result_files + binary + signed media URLs + parsed log in a single round-trip */ 200: { headers: { [name: string]: unknown; }; - content: { - /** - * @example { - * "uploadId": "upload-123", - * "status": "PENDING", - * "tests": [ - * { - * "id": 1, - * "test_file_name": "test-flow.yaml", - * "status": "PENDING" - * } - * ] - * } - */ - "application/json": Record; + content?: never; + }; + /** @description Result not found or caller not authorized */ + 400: { + headers: { + [name: string]: unknown; }; + content?: never; }; }; }; - UploadsController_listUploads: { + FrontendController_ingestLogs: { parameters: { - query?: { - /** @description Filter by upload name (supports * wildcard) */ - name?: string; - /** @description Filter uploads created on or after this date (ISO 8601) */ - from?: string; - /** @description Filter uploads created on or before this date (ISO 8601) */ - to?: string; - /** @description Maximum number of uploads to return (default: 20) */ - limit?: number; - /** @description Number of uploads to skip (default: 0) */ - offset?: number; - }; + query?: never; header: { - "x-app-api-key": string; + authorization: string; + "x-dcd-org": string; }; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description List of flow uploads. Use GET /uploads/status for detailed test results. */ - 200: { + /** @description Batch accepted for forwarding to Axiom */ + 202: { headers: { [name: string]: unknown; }; content: { - /** - * @example { - * "uploads": [ - * { - * "id": "upload-123", - * "name": "Test Upload", - * "created_at": "2024-01-01T00:00:00Z", - * "consoleUrl": "https://console.devicecloud.dev/results/upload-123" - * } - * ], - * "total": 1, - * "limit": 20, - * "offset": 0 - * } - */ "application/json": { - uploads?: { - id?: string; - name?: string | null; - created_at?: string; - consoleUrl?: string; - }[]; - total?: number; - limit?: number; - offset?: number; + accepted?: number; }; }; }; + /** @description Malformed batch payload */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; - UploadsController_deleteUpload: { + FrontendController_ingestLogsAnonymous: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; - path: { - uploadId: string; - }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - 200: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description The upload has been successfully deleted. */ - 201: { + /** @description Batch accepted for forwarding to Axiom */ + 202: { headers: { [name: string]: unknown; }; content: { "application/json": { - success?: boolean; - message?: string; + accepted?: number; }; }; }; + /** @description Malformed batch payload */ + 400: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; }; }; - ResultsController_getResults: { + HealthController_health: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; - path: { - uploadId: string; - }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description The record has been successfully created. */ + /** @description Health check endpoint */ 200: { headers: { [name: string]: unknown; }; content: { + /** + * @example { + * "status": "ok" + * } + */ "application/json": { - statusCode?: number; - results?: components["schemas"]["TResultResponse"][]; + /** @example ok */ + status?: string; }; }; }; }; }; - ResultsController_getTestRunArtifacts: { + BillingController_createSubscription: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; - path: { - uploadId: string; - }; + header?: never; + path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + items: { + price_id?: string; + quantity?: number; + }[]; + customer_email?: string; + custom_data?: { + userId?: string; + }; + billing_details?: { + enable_checkout?: boolean; + }; + }; + }; + }; responses: { + /** @description Subscription created successfully. */ 201: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": Record; + }; }; }; }; - ResultsController_notifyTestRunComplete: { + BillingController_updateSubscription: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; - path: { - uploadId: string; - }; + header?: never; + path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + price_id: string; + }; + }; + }; responses: { - /** @description Send results summary email. */ + /** @description Subscription updated successfully. */ 201: { headers: { [name: string]: unknown; }; content: { - "application/json": string; + "application/json": Record; }; }; }; }; - ResultsController_downloadReport: { + StatsController_getMarketingStats: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; - path: { - uploadId: string; - }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Download combined JUNIT test report (report.xml) for the upload */ + /** @description Public marketing statistics */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": string; + "application/json": { + /** @example 150000 */ + total_count?: number; + }; }; }; }; }; - ResultsController_downloadHtmlReport: { + FlowsController_getFlows: { parameters: { - query?: never; - header: { - "x-app-api-key": string; + query?: { + platform?: "android" | "ios"; + appId?: string; + days?: number; + /** @description ISO 8601 date string (e.g. 2026-01-01). Overrides days when provided. */ + startDate?: string; + /** @description ISO 8601 date string (e.g. 2026-01-31). Defaults to now when startDate is set. */ + endDate?: string; + /** @description Comma-separated tag filter. Returns flows that have any of the given tags (e.g. smoke,critical). */ + tags?: string; }; - path: { - uploadId: string; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Aggregated flow statistics for the last N days. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + statusCode?: number; + flows?: components["schemas"]["TFlowSummaryResponse"][]; + }; + }; + }; + }; + }; + FlowsController_getFlowRuns: { + parameters: { + query: { + fileName: string; + platform?: "android" | "ios"; + appId?: string; + limit?: number; + /** @description ISO 8601 date string (e.g. 2026-01-01). */ + startDate?: string; + /** @description ISO 8601 date string (e.g. 2026-01-31). */ + endDate?: string; }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Download combined HTML test report with assets (report.zip) for the upload */ + /** @description Individual run history for a specific flow file. */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": string; + "application/json": { + statusCode?: number; + runs?: components["schemas"]["TFlowRunItem"][]; + }; }; }; }; }; - ResultsController_downloadSingleHtmlReport: { + LiveController_createSession: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; - path: { - resultId: string; - }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Download HTML test report with assets (report.zip) for a single result */ - 200: { + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": string; + "application/json": Record; }; }; }; }; - ResultsController_getCompatibilityData: { + LiveController_getSession: { parameters: { query?: never; - header: { - "x-app-api-key": string; + header?: never; + path: { + identifier: string; }; - path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Device compatibility lookup data including Maestro versions */ 200: { headers: { [name: string]: unknown; }; content: { - /** - * @example { - * "statusCode": 200, - * "data": { - * "ios": { - * "iphone-14": { - * "name": "iPhone 14", - * "versions": [ - * "16", - * "17", - * "18" - * ], - * "deprecated": false - * }, - * "iphone-15": { - * "name": "iPhone 15", - * "versions": [ - * "17" - * ], - * "deprecated": false - * }, - * "iphone-16": { - * "name": "iPhone 16", - * "versions": [ - * "18", - * "26" - * ], - * "deprecated": false - * }, - * "iphone-16-plus": { - * "name": "iPhone 16 Plus", - * "versions": [ - * "18", - * "26" - * ], - * "deprecated": false - * }, - * "iphone-16-pro": { - * "name": "iPhone 16 Pro", - * "versions": [ - * "18", - * "26" - * ], - * "deprecated": false - * }, - * "iphone-16-pro-max": { - * "name": "iPhone 16 Pro Max", - * "versions": [ - * "18", - * "26" - * ], - * "deprecated": false - * }, - * "ipad-pro-6th-gen": { - * "name": "iPad Pro (6th gen)", - * "versions": [ - * "18", - * "26" - * ], - * "deprecated": false - * } - * }, - * "android": { - * "pixel-6": { - * "name": "Pixel 6", - * "apiLevels": [ - * "29", - * "30", - * "31", - * "32", - * "33", - * "34", - * "35", - * "36" - * ], - * "deprecated": false - * }, - * "pixel-6-pro": { - * "name": "Pixel 6 Pro", - * "apiLevels": [ - * "33", - * "34", - * "35", - * "36" - * ], - * "deprecated": false - * }, - * "pixel-7": { - * "name": "Pixel 7", - * "apiLevels": [ - * "33", - * "34", - * "35", - * "36" - * ], - * "deprecated": false - * }, - * "pixel-7-pro": { - * "name": "Pixel 7 Pro", - * "apiLevels": [ - * "33", - * "34", - * "35", - * "36" - * ], - * "deprecated": false - * }, - * "generic-tablet": { - * "name": "Generic Tablet", - * "apiLevels": [ - * "33", - * "34", - * "35", - * "36" - * ], - * "deprecated": false - * } - * }, - * "androidPlay": { - * "pixel-6": { - * "name": "Pixel 6 (Google Play)", - * "apiLevels": [ - * "34", - * "35", - * "36" - * ], - * "deprecated": false - * }, - * "pixel-7": { - * "name": "Pixel 7 (Google Play)", - * "apiLevels": [ - * "34", - * "35", - * "36" - * ], - * "deprecated": false - * } - * }, - * "maestro": { - * "supportedVersions": [ - * "1.39.0", - * "1.39.2", - * "1.39.5", - * "1.39.7", - * "1.40.3", - * "1.41.0", - * "2.0.2", - * "2.0.3", - * "2.0.4", - * "2.0.9", - * "2.1.0" - * ], - * "defaultVersion": "1.41.0", - * "latestVersion": "2.1.0" - * } - * } - * } - */ - "application/json": { - statusCode?: number; - data?: { - ios?: Record; - android?: Record; - androidPlay?: Record; - maestro?: { - supportedVersions?: string[]; - defaultVersion?: string; - latestVersion?: string; - }; - }; - }; + "application/json": Record; }; }; }; }; - AllureController_downloadAllureReport: { + LiveController_stopSession: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; + header?: never; path: { - /** @description The upload ID to generate Allure report for */ - uploadId: string; + identifier: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Allure report HTML file download */ 200: { - headers: { - [name: string]: unknown; - }; - content: { - "text/html": string; - }; - }; - /** @description Upload not found or no results available */ - 404: { headers: { [name: string]: unknown; }; @@ -1426,64 +4188,40 @@ export interface operations { }; }; }; - WebhooksController_getWebhook: { + LiveController_execTest: { parameters: { - query?: { - /** @description Set to true to return full secret instead of masked version */ - show_secret?: boolean; - }; - header: { - "x-app-api-key": string; + query?: never; + header?: never; + path: { + identifier: string; }; - path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Current webhook configuration */ - 200: { + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": { - webhook_url?: string; - /** @description Full secret (only when show_secret=true) */ - secret_key?: string; - /** @description Masked secret (default) */ - secret_key_masked?: string; - /** Format: date-time */ - created_at?: string; - /** Format: date-time */ - updated_at?: string; - }; + "application/json": Record; }; }; }; }; - WebhooksController_setWebhook: { + LiveController_getCommandStatus: { parameters: { query?: never; - header: { - "x-app-api-key": string; + header?: never; + path: { + identifier: string; + commandId: string; }; - path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": { - /** - * Format: uri - * @example https://api.example.com/webhook - */ - url: string; - }; - }; - }; + requestBody?: never; responses: { - /** @description Webhook URL set successfully */ - 201: { + 200: { headers: { [name: string]: unknown; }; @@ -1493,160 +4231,123 @@ export interface operations { }; }; }; - WebhooksController_deleteWebhook: { + LiveController_keepalive: { parameters: { query?: never; - header: { - "x-app-api-key": string; + header?: never; + path: { + identifier: string; }; - path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Webhook configuration deleted successfully */ - 200: { + 201: { headers: { [name: string]: unknown; }; - content: { - "application/json": Record; - }; + content?: never; }; }; }; - WebhooksController_regenerateWebhookSecret: { + LiveController_installBinary: { parameters: { query?: never; - header: { - "x-app-api-key": string; + header?: never; + path: { + identifier: string; }; - path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Webhook secret regenerated successfully */ 201: { headers: { [name: string]: unknown; }; - content: { - "application/json": Record; - }; + content?: never; }; }; }; - WebhooksController_testWebhook: { + MeController_listOrgs: { parameters: { query?: never; header: { - "x-app-api-key": string; + authorization: string; }; path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": { - /** Format: uri */ - url?: string; - }; - }; - }; + requestBody?: never; responses: { - /** @description Test webhook sent successfully */ - 201: { + 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": Record; - }; + content?: never; }; }; }; - OrgController_handlePaddleWebhook: { + MeController_listSessions: { parameters: { query?: never; header: { - "paddle-signature": string; + authorization: string; }; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Paddle webhook handler. */ - 201: { + 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": string; - }; + content?: never; }; }; }; - OrgController_updateOrgName: { + MeController_revokeSession: { parameters: { query?: never; header: { - "x-app-api-key": string; + authorization: string; }; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["UpdateOrgNameDto"]; + path: { + id: string; }; + cookie?: never; }; + requestBody?: never; responses: { - /** @description Organization name updated successfully. */ - 201: { + 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": boolean; - }; + content?: never; }; }; }; - OrgController_inviteTeamMember: { + MeController_createPersonalTeam: { parameters: { query?: never; header: { - "x-app-api-key": string; + authorization: string; }; path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": { - inviteEmail: string; - requesterEmail: string; - link: string; - orgId: string; - orgName: string; - }; - }; - }; + requestBody?: never; responses: { - /** @description Team member invited successfully. */ - 201: { + 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": boolean; - }; + content?: never; }; }; }; - OrgController_acceptInvite: { + MeController_createTeam: { parameters: { query?: never; header: { @@ -1655,292 +4356,262 @@ export interface operations { path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["AcceptInviteDto"]; - }; - }; + requestBody?: never; responses: { - /** @description Team invite accepted successfully. */ - 201: { + 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": boolean; - }; + content?: never; }; }; }; - OrgController_getAllSubscriptions: { + MeController_deleteAccount: { parameters: { query?: never; header: { - "x-app-api-key": string; + authorization: string; }; path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": { - orgId: string; - }; - }; - }; + requestBody?: never; responses: { - /** @description All subscription data fetched successfully. */ - 201: { + 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": Record; - }; + content?: never; }; }; }; - OrgController_updateOverageLimit: { + CliLoginController_handoff: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; + header?: never; path?: never; cookie?: never; }; requestBody: { content: { - "application/json": { - orgId: string; - overageLimit: number; - }; + "application/json": components["schemas"]["HandoffDto"]; }; }; responses: { - /** @description Overage limit updated successfully. */ - 201: { + 204: { headers: { [name: string]: unknown; }; - content: { - "application/json": Record; - }; + content?: never; }; }; }; - OrgController_getUsageHistory: { + CliLoginController_claim: { parameters: { query?: never; - header: { - "x-app-api-key": string; - }; + header?: never; path?: never; cookie?: never; }; requestBody: { content: { - "application/json": { - orgId: string; - /** @enum {string} */ - format?: "json" | "csv"; - /** Format: date-time */ - startDate?: string; - /** Format: date-time */ - endDate?: string; - }; + "application/json": components["schemas"]["ClaimDto"]; }; }; responses: { - /** @description Usage history fetched successfully. */ - 201: { + /** @description Returns the Supabase session on successful claim. */ + 200: { headers: { [name: string]: unknown; }; - content: { - "application/json": unknown[]; - }; + content?: never; }; }; }; - FrontendController_checkDomainSaml: { + CliLogsController_ingestLogs: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** @description Domain to check for SAML configuration */ - requestBody: { - content: { - "application/json": { - /** @example example.com */ - domain: string; - }; - }; - }; + requestBody?: never; responses: { - /** @description SAML status for the domain */ + /** @description Batch accepted for forwarding to Axiom */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - forceSaml?: boolean; + accepted?: number; }; }; }; - 201: { + 202: { headers: { [name: string]: unknown; }; content?: never; }; - /** @description Bad request - invalid domain or API error */ + /** @description Malformed batch payload */ 400: { headers: { [name: string]: unknown; }; - content: { - "application/json": { - error?: string; - }; - }; + content?: never; }; }; }; - FrontendController_validateEmail: { + EmailChangeController_start: { parameters: { query?: never; - header?: never; + header: { + authorization: string; + }; path?: never; cookie?: never; }; - /** @description Email address to validate */ + /** @description New email address to change to */ requestBody: { content: { "application/json": { /** @example user@example.com */ - email: string; + newEmail: string; }; }; }; responses: { - /** @description Email validation result */ + /** @description Verification code sent to the current address */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - valid?: boolean; - reason?: string; + ok?: boolean; }; }; }; - 201: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - /** @description Bad request - invalid email or API error */ + /** @description Invalid or missing newEmail */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": { - error?: string; + message?: string; }; }; }; }; }; - HealthController_health: { + EmailChangeController_verifyCurrent: { parameters: { query?: never; - header?: never; + header: { + authorization: string; + }; path?: never; cookie?: never; }; - requestBody?: never; + /** @description Code emailed to the current address */ + requestBody: { + content: { + "application/json": { + /** @example 123456 */ + code: string; + }; + }; + }; responses: { - /** @description Health check endpoint */ + /** @description Current address verified; code sent to the new address */ 200: { headers: { [name: string]: unknown; }; content: { - /** - * @example { - * "status": "ok" - * } - */ "application/json": { - /** @example ok */ - status?: string; + ok?: boolean; + }; + }; + }; + /** @description Invalid or expired code */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message?: string; }; }; }; }; }; - BillingController_createSubscription: { + EmailChangeController_verifyNew: { parameters: { query?: never; - header?: never; + header: { + authorization: string; + }; path?: never; cookie?: never; }; + /** @description Code emailed to the new address */ requestBody: { content: { "application/json": { - items: { - price_id?: string; - quantity?: number; - }[]; - customer_email?: string; - custom_data?: { - orgId?: string; - userId?: string; - }; - billing_details?: { - enable_checkout?: boolean; - }; + /** @example 123456 */ + code: string; }; }; }; responses: { - /** @description Subscription created successfully. */ - 201: { + /** @description Email change applied */ + 200: { headers: { [name: string]: unknown; }; content: { - "application/json": Record; + "application/json": { + ok?: boolean; + email?: string; + }; + }; + }; + /** @description Invalid or expired code, or current email not verified */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + message?: string; + }; }; }; }; }; - StatsController_getMarketingStats: { + EmailChangeController_cancel: { parameters: { query?: never; - header?: never; + header: { + authorization: string; + }; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Public marketing statistics */ + /** @description In-progress email change cancelled (idempotent) */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - /** @example 150000 */ - total_count?: number; + ok?: boolean; }; }; };