From 7572e49f034667f27bfd0416299a607e2b8051a6 Mon Sep 17 00:00:00 2001 From: "cloudquery-ci[bot]" <271027272+cloudquery-ci[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 07:39:19 +0000 Subject: [PATCH] fix: Generate CloudQuery Go API Client from `spec.json` --- client.gen.go | 358 ++++++++++++++++++++++++++++++++++++++++++++++++++ models.gen.go | 36 +++++ spec.json | 134 ++++++++++++++++++- 3 files changed, 527 insertions(+), 1 deletion(-) diff --git a/client.gen.go b/client.gen.go index 499972d..3337e5b 100644 --- a/client.gen.go +++ b/client.gen.go @@ -144,6 +144,16 @@ type ClientInterface interface { // GetOpenAPIJSON request GetOpenAPIJSON(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + // UpsertPlatformDestinationSecretWithBody request with any body + UpsertPlatformDestinationSecretWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + UpsertPlatformDestinationSecret(ctx context.Context, body UpsertPlatformDestinationSecretJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // CreatePlatformDestinationSessionWithBody request with any body + CreatePlatformDestinationSessionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CreatePlatformDestinationSession(ctx context.Context, body CreatePlatformDestinationSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // CreatePlatformSignupWithBody request with any body CreatePlatformSignupWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -764,6 +774,54 @@ func (c *Client) GetOpenAPIJSON(ctx context.Context, reqEditors ...RequestEditor return c.Client.Do(req) } +func (c *Client) UpsertPlatformDestinationSecretWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertPlatformDestinationSecretRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpsertPlatformDestinationSecret(ctx context.Context, body UpsertPlatformDestinationSecretJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertPlatformDestinationSecretRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreatePlatformDestinationSessionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreatePlatformDestinationSessionRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreatePlatformDestinationSession(ctx context.Context, body CreatePlatformDestinationSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreatePlatformDestinationSessionRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) CreatePlatformSignupWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewCreatePlatformSignupRequestWithBody(c.Server, contentType, body) if err != nil { @@ -3345,6 +3403,86 @@ func NewGetOpenAPIJSONRequest(server string) (*http.Request, error) { return req, nil } +// NewUpsertPlatformDestinationSecretRequest calls the generic UpsertPlatformDestinationSecret builder with application/json body +func NewUpsertPlatformDestinationSecretRequest(server string, body UpsertPlatformDestinationSecretJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewUpsertPlatformDestinationSecretRequestWithBody(server, "application/json", bodyReader) +} + +// NewUpsertPlatformDestinationSecretRequestWithBody generates requests for UpsertPlatformDestinationSecret with any type of body +func NewUpsertPlatformDestinationSecretRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/platform-destination/secret") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewCreatePlatformDestinationSessionRequest calls the generic CreatePlatformDestinationSession builder with application/json body +func NewCreatePlatformDestinationSessionRequest(server string, body CreatePlatformDestinationSessionJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCreatePlatformDestinationSessionRequestWithBody(server, "application/json", bodyReader) +} + +// NewCreatePlatformDestinationSessionRequestWithBody generates requests for CreatePlatformDestinationSession with any type of body +func NewCreatePlatformDestinationSessionRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/platform-destination/session") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewCreatePlatformSignupRequest calls the generic CreatePlatformSignup builder with application/json body func NewCreatePlatformSignupRequest(server string, body CreatePlatformSignupJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -9189,6 +9327,16 @@ type ClientWithResponsesInterface interface { // GetOpenAPIJSONWithResponse request GetOpenAPIJSONWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetOpenAPIJSONResponse, error) + // UpsertPlatformDestinationSecretWithBodyWithResponse request with any body + UpsertPlatformDestinationSecretWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertPlatformDestinationSecretResponse, error) + + UpsertPlatformDestinationSecretWithResponse(ctx context.Context, body UpsertPlatformDestinationSecretJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertPlatformDestinationSecretResponse, error) + + // CreatePlatformDestinationSessionWithBodyWithResponse request with any body + CreatePlatformDestinationSessionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreatePlatformDestinationSessionResponse, error) + + CreatePlatformDestinationSessionWithResponse(ctx context.Context, body CreatePlatformDestinationSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreatePlatformDestinationSessionResponse, error) + // CreatePlatformSignupWithBodyWithResponse request with any body CreatePlatformSignupWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreatePlatformSignupResponse, error) @@ -9945,6 +10093,60 @@ func (r GetOpenAPIJSONResponse) StatusCode() int { return 0 } +type UpsertPlatformDestinationSecretResponse struct { + Body []byte + HTTPResponse *http.Response + JSON400 *BadRequest + JSON401 *RequiresAuthentication + JSON404 *NotFound + JSON429 *TooManyRequests + JSON500 *InternalError +} + +// Status returns HTTPResponse.Status +func (r UpsertPlatformDestinationSecretResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UpsertPlatformDestinationSecretResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type CreatePlatformDestinationSessionResponse struct { + Body []byte + HTTPResponse *http.Response + JSON201 *CreatePlatformDestinationSession201Response + JSON400 *BadRequest + JSON401 *RequiresAuthentication + JSON404 *NotFound + JSON422 *UnprocessableEntity + JSON429 *TooManyRequests + JSON500 *InternalError +} + +// Status returns HTTPResponse.Status +func (r CreatePlatformDestinationSessionResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CreatePlatformDestinationSessionResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type CreatePlatformSignupResponse struct { Body []byte HTTPResponse *http.Response @@ -12861,6 +13063,40 @@ func (c *ClientWithResponses) GetOpenAPIJSONWithResponse(ctx context.Context, re return ParseGetOpenAPIJSONResponse(rsp) } +// UpsertPlatformDestinationSecretWithBodyWithResponse request with arbitrary body returning *UpsertPlatformDestinationSecretResponse +func (c *ClientWithResponses) UpsertPlatformDestinationSecretWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertPlatformDestinationSecretResponse, error) { + rsp, err := c.UpsertPlatformDestinationSecretWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpsertPlatformDestinationSecretResponse(rsp) +} + +func (c *ClientWithResponses) UpsertPlatformDestinationSecretWithResponse(ctx context.Context, body UpsertPlatformDestinationSecretJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertPlatformDestinationSecretResponse, error) { + rsp, err := c.UpsertPlatformDestinationSecret(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpsertPlatformDestinationSecretResponse(rsp) +} + +// CreatePlatformDestinationSessionWithBodyWithResponse request with arbitrary body returning *CreatePlatformDestinationSessionResponse +func (c *ClientWithResponses) CreatePlatformDestinationSessionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreatePlatformDestinationSessionResponse, error) { + rsp, err := c.CreatePlatformDestinationSessionWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreatePlatformDestinationSessionResponse(rsp) +} + +func (c *ClientWithResponses) CreatePlatformDestinationSessionWithResponse(ctx context.Context, body CreatePlatformDestinationSessionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreatePlatformDestinationSessionResponse, error) { + rsp, err := c.CreatePlatformDestinationSession(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreatePlatformDestinationSessionResponse(rsp) +} + // CreatePlatformSignupWithBodyWithResponse request with arbitrary body returning *CreatePlatformSignupResponse func (c *ClientWithResponses) CreatePlatformSignupWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreatePlatformSignupResponse, error) { rsp, err := c.CreatePlatformSignupWithBody(ctx, contentType, body, reqEditors...) @@ -14827,6 +15063,128 @@ func ParseGetOpenAPIJSONResponse(rsp *http.Response) (*GetOpenAPIJSONResponse, e return response, nil } +// ParseUpsertPlatformDestinationSecretResponse parses an HTTP response from a UpsertPlatformDestinationSecretWithResponse call +func ParseUpsertPlatformDestinationSecretResponse(rsp *http.Response) (*UpsertPlatformDestinationSecretResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UpsertPlatformDestinationSecretResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BadRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest RequiresAuthentication + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest NotFound + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + +// ParseCreatePlatformDestinationSessionResponse parses an HTTP response from a CreatePlatformDestinationSessionWithResponse call +func ParseCreatePlatformDestinationSessionResponse(rsp *http.Response) (*CreatePlatformDestinationSessionResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CreatePlatformDestinationSessionResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: + var dest CreatePlatformDestinationSession201Response + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON201 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest BadRequest + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest RequiresAuthentication + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest NotFound + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest UnprocessableEntity + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON422 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 429: + var dest TooManyRequests + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON429 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParseCreatePlatformSignupResponse parses an HTTP response from a CreatePlatformSignupWithResponse call func ParseCreatePlatformSignupResponse(rsp *http.Response) (*CreatePlatformSignupResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/models.gen.go b/models.gen.go index ac5697e..cca1d2a 100644 --- a/models.gen.go +++ b/models.gen.go @@ -659,6 +659,24 @@ type CreateAddonVersionRequest struct { PluginDeps *[]string `json:"plugin_deps,omitempty"` } +// CreatePlatformDestinationSession201Response defines model for CreatePlatformDestinationSession_201_response. +type CreatePlatformDestinationSession201Response struct { + // ApiUrl Base URL of the tenant's platform API (e.g. https://acme.us.platform.cloudquery.io). The CLI uses it to reach /external-syncs/* directly — no CQ_PLATFORM_API_URL configuration needed. + ApiUrl string `json:"api_url"` + + // ExpiresInSeconds Seconds until the token expires. + ExpiresInSeconds int `json:"expires_in_seconds"` + + // Token HMAC-signed, tenant-scoped token for /external-syncs/*. + Token string `json:"token"` +} + +// CreatePlatformDestinationSessionRequest defines model for CreatePlatformDestinationSession_request. +type CreatePlatformDestinationSessionRequest struct { + // TenantId The platform tenant (instance) to mint a token for. + TenantId openapi_types.UUID `json:"tenant_id"` +} + // CreatePlatformSignup201Response defines model for CreatePlatformSignup_201_response. type CreatePlatformSignup201Response struct { // MagicLoginEnabled Whether magic-link sign-in is available for this tenant. @@ -2064,6 +2082,18 @@ type UploadPluginUIAssetsRequest struct { Assets []PluginUIAssetUploadRequest `json:"assets"` } +// UpsertPlatformDestinationSecretRequest defines model for UpsertPlatformDestinationSecret_request. +type UpsertPlatformDestinationSecretRequest struct { + // Current The new current HMAC secret (cleartext; stored encrypted). + Current string `json:"current"` + + // Previous The just-demoted secret, kept verifiable through the rotation grace window. Omit for backfill. + Previous *string `json:"previous,omitempty"` + + // TenantId The platform tenant (instance) the secret belongs to. + TenantId openapi_types.UUID `json:"tenant_id"` +} + // UsageCurrent The usage of a plugin within the current calendar month. type UsageCurrent struct { // PluginKind The kind of plugin, ie. source or destination. @@ -2652,6 +2682,12 @@ type UpdateAddonVersionJSONRequestBody = AddonVersionUpdate // CreateAddonVersionJSONRequestBody defines body for CreateAddonVersion for application/json ContentType. type CreateAddonVersionJSONRequestBody = CreateAddonVersionRequest +// UpsertPlatformDestinationSecretJSONRequestBody defines body for UpsertPlatformDestinationSecret for application/json ContentType. +type UpsertPlatformDestinationSecretJSONRequestBody = UpsertPlatformDestinationSecretRequest + +// CreatePlatformDestinationSessionJSONRequestBody defines body for CreatePlatformDestinationSession for application/json ContentType. +type CreatePlatformDestinationSessionJSONRequestBody = CreatePlatformDestinationSessionRequest + // CreatePlatformSignupJSONRequestBody defines body for CreatePlatformSignup for application/json ContentType. type CreatePlatformSignupJSONRequestBody = CreatePlatformSignupRequest diff --git a/spec.json b/spec.json index 54c27d5..2fd805d 100644 --- a/spec.json +++ b/spec.json @@ -4164,6 +4164,92 @@ "x-internal" : true } }, + "/platform-destination/secret" : { + "post" : { + "description" : "Store/replace cloud's copy of a platform tenant's external-sync HMAC secret(s) — the propagate step of platform admin's two-phase secret rotation (and the backfill path for tenants provisioned before rotation support). Admin authenticates with the tenant's own cloud API key (stored at tenant creation) and upserts {current, previous} atomically, so cloud never verifies only the new secret while outstanding cqpd_ tokens are signed with the old one. previous is omitted for backfill, which clears any stale grace window. Requires a durable team API key — cqpd_ tokens are rejected (a leaked derived token must not be able to replace the secret it is verified against). The caller's team must own the tenant (404 otherwise, hiding existence).", + "operationId" : "UpsertPlatformDestinationSecret", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UpsertPlatformDestinationSecret_request" + } + } + }, + "required" : true + }, + "responses" : { + "204" : { + "description" : "Secret stored" + }, + "400" : { + "$ref" : "#/components/responses/BadRequest" + }, + "401" : { + "$ref" : "#/components/responses/RequiresAuthentication" + }, + "404" : { + "$ref" : "#/components/responses/NotFound" + }, + "429" : { + "$ref" : "#/components/responses/TooManyRequests" + }, + "500" : { + "$ref" : "#/components/responses/InternalError" + } + }, + "tags" : [ "platform" ], + "x-internal" : true + } + }, + "/platform-destination/session" : { + "post" : { + "description" : "Mint a short-lived (≈1 week), tenant-scoped token that authenticates the local CLI's platform-destination plugin to the platform's /external-syncs/* endpoints. It is a derived credential — the CLI re-mints it here from the durable root (cloud login, or a team API key in CI) as it nears expiry. The caller selects one of their platform tenants by tenant_id; cloud verifies the caller is a member of the owning team, then delegates the mint to platform admin (the single minting authority) and relays the returned token. Cloud holds its own copy of the per-tenant secret only to verify cqpd_ tokens offline, not to sign. The token carries only tenant id + email + expiry; no cloud credential crosses to the platform.\n", + "operationId" : "CreatePlatformDestinationSession", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreatePlatformDestinationSession_request" + } + } + }, + "required" : true + }, + "responses" : { + "201" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreatePlatformDestinationSession_201_response" + } + } + }, + "description" : "Token minted" + }, + "400" : { + "$ref" : "#/components/responses/BadRequest" + }, + "401" : { + "$ref" : "#/components/responses/RequiresAuthentication" + }, + "404" : { + "$ref" : "#/components/responses/NotFound" + }, + "422" : { + "$ref" : "#/components/responses/UnprocessableEntity" + }, + "429" : { + "$ref" : "#/components/responses/TooManyRequests" + }, + "500" : { + "$ref" : "#/components/responses/InternalError" + } + }, + "tags" : [ "platform" ], + "x-internal" : true + } + }, "/platform-signup" : { "post" : { "description" : "Self-serve entry point for a new Platform trial. The wizard collects `name`, `job_title`, `company` and, optionally, an existing `team_name` the caller wants to attach the new tenant to. Server side: re-runs UserCheck on the caller's email (personal / disposable / blocklisted / non-deliverable addresses are rejected with 400), auto-generates a subdomain, creates the owning Cloud team (or uses the supplied one), generates a per-tenant API key + password, and inserts the `platform_tenants` row in `pending` status.\nLifetime gate: a caller may successfully sign up at most once — match is on `platform_tenants.email == user.Email`. Subsequent calls return 422. Admin override is operational only (support deletes the blocking row in the DB).\nThe Firebase `email_verified` claim may be `false` — this is the only operation in the API surface that intentionally accepts unverified callers, because the wizard captures form data before the user clicks the Mandrill verification link. The wizard's \"continuing\" screen follows up with `POST /teams/{team_name}/platform/tenant/{tenant_id}/finalize` (which DOES require a verified email) once the user verifies. The returned `team_name` and `tenant_id` are the values the wizard passes back into `/finalize`.\n", @@ -4360,7 +4446,7 @@ }, "/user/platform/tenants" : { "get" : { - "description" : "List Platform tenants the authenticated user can access via Cloud team membership. Used by the signup wizard to decide whether to show the tenant-creation form (empty list) or route the user to an existing tenant. Returns tenants in any status (pending/created/active).\n", + "description" : "List Platform tenants the caller can access. Interactive sessions see the tenants of every Cloud team they are a member of (used by the signup wizard to decide whether to show the tenant-creation form or route to an existing tenant). Team API keys see their one team's tenants — the CLI's tenant-discovery path before POST /platform-destination/session, so headless runs need no CQ_PLATFORM_TENANT_ID configuration. cqpd_ tokens are rejected (a derived credential must not enumerate tenants). Returns tenants in any status (pending/created/active).\n", "operationId" : "ListUserPlatformTenants", "responses" : { "200" : { @@ -8597,6 +8683,52 @@ }, "required" : [ "has_cloud_account" ] }, + "UpsertPlatformDestinationSecret_request" : { + "properties" : { + "tenant_id" : { + "description" : "The platform tenant (instance) the secret belongs to.", + "format" : "uuid", + "type" : "string" + }, + "current" : { + "description" : "The new current HMAC secret (cleartext; stored encrypted).", + "minLength" : 1, + "type" : "string" + }, + "previous" : { + "description" : "The just-demoted secret, kept verifiable through the rotation grace window. Omit for backfill.", + "type" : "string" + } + }, + "required" : [ "current", "tenant_id" ] + }, + "CreatePlatformDestinationSession_request" : { + "properties" : { + "tenant_id" : { + "description" : "The platform tenant (instance) to mint a token for.", + "format" : "uuid", + "type" : "string" + } + }, + "required" : [ "tenant_id" ] + }, + "CreatePlatformDestinationSession_201_response" : { + "properties" : { + "token" : { + "description" : "HMAC-signed, tenant-scoped token for /external-syncs/*.", + "type" : "string" + }, + "expires_in_seconds" : { + "description" : "Seconds until the token expires.", + "type" : "integer" + }, + "api_url" : { + "description" : "Base URL of the tenant's platform API (e.g. https://acme.us.platform.cloudquery.io). The CLI uses it to reach /external-syncs/* directly — no CQ_PLATFORM_API_URL configuration needed.", + "type" : "string" + } + }, + "required" : [ "api_url", "expires_in_seconds", "token" ] + }, "CreatePlatformSignup_request" : { "additionalProperties" : { }, "properties" : {