Skip to content

chore(api): sync OpenAPI contract - #2

Draft
kong[bot] wants to merge 1 commit into
mainfrom
chore/sync-openapi
Draft

kong[bot] wants to merge 1 commit into
mainfrom
chore/sync-openapi

Conversation

@kong

@kong kong Bot commented Aug 28, 2026 •

Copy link
Copy Markdown

Summary

API change report

Public API

New Endpoints: 6


GET /capabilities
GET /projects/{id}/variable-environments
POST /projects/{id}/variable-environments
DELETE /projects/{id}/variable-environments/{environmentId}
GET /projects/{id}/variable-environments/{environmentId}
PATCH /projects/{id}/variable-environments/{environmentId}

Deleted Endpoints: None


Modified Endpoints: 18


POST /durable-approvals

  • Request body changed
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Properties changed
            • Modified property: details
              • Extensions changed
                • New extension: x-go-type
                • New extension: x-go-type-skip-optional-pointer
              • Description changed from 'Any JSON value to show the person deciding. The whole request is
                limited to 64 KiB.
                ' to 'Any JSON value to show the person deciding. A number's exponent must
                be between -324 and 324, and a number too large or too precise to
                store is refused with 400. Numbers are read back written out in
                full, so the exponents' absolute values may total at most 65,536.
                The whole request is limited to 64 KiB.
                '

GET /projects/{id}/auth/config

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • New property: created_at
              • New property: rate_limit_password_reset
              • New property: refresh_token_reuse_interval
              • New property: updated_at

PUT /projects/{id}/auth/config

  • Request body changed
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Properties changed
            • New property: cors_allowed_origins
            • New property: cors_enabled
            • New property: platform_token_ttl
            • New property: rate_limit_password_reset
            • New property: refresh_token_reuse_interval
  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • New property: created_at
              • New property: rate_limit_password_reset
              • New property: refresh_token_reuse_interval
              • New property: updated_at

POST /projects/{id}/auth/config/test-email

  • Description changed from 'Sends a diagnostic email to to_email using the project's
    persisted auth_config SMTP credentials. If html_body or
    text_body is supplied, the override path is taken: those
    values (plus optional subject) are rendered through
    html/text templates against the project's Data and
    used as the body — used by the template editor's "Send Test"
    affordance to preview an unsaved template. With both bodies
    omitted, a hardcoded diagnostic message is sent and any
    subject field is ignored. Sending subject alone (no
    bodies) is rejected with 400 to avoid a silently-dropped
    subject or a blank message. Also rejects with 400 if
    email_enabled=false or smtp_host is empty.
    ' to 'Sends a diagnostic email to to_email using the project's
    persisted auth_config SMTP credentials. If html_body or
    text_body is supplied, the override path is taken: those
    values (plus optional subject) are rendered through
    html/text templates against the project's Data and
    used as the body — used by the template editor's "Send Test"
    affordance to preview an unsaved template. With both bodies
    omitted, a hardcoded diagnostic message is sent and any
    subject field is ignored. Sending subject alone (no
    bodies) is rejected with 400 to avoid a silently-dropped
    subject or a blank message. Also rejects with 400 if
    email_enabled=false, smtp_host is empty, or the saved
    smtp_password can't be read and must be set again.
    '

GET /projects/{id}/config

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: sandboxes
                • Items changed
                  • Properties changed
                    • Deleted property: idle_timeout_seconds
                    • Modified property: ttl_seconds
                    • Description changed from 'Default absolute lifetime for new sessions when the caller omits it.' to 'Default absolute lifetime for new sessions when the caller omits it. Cloud templates accept 30–28800 seconds; inherited lifetimes are clamped to the session plan limit (3600 for HOBBY, 28800 for SUPERAGENT). Local accepts 0 for unlimited or a positive lifetime.'
                    • Min changed from 30 to 0
                    • Max changed from 28800 to 2.147483647e+09

PUT /projects/{id}/config

  • Request body changed
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Properties changed
            • Modified property: sandboxes
              • Items changed
                • Properties changed
                  • Deleted property: idle_timeout_seconds
                  • Modified property: ttl_seconds
                    • Description changed from 'Default absolute lifetime for new sessions when the caller omits it.' to 'Default absolute lifetime for new sessions when the caller omits it. Cloud templates accept 30–28800 seconds; inherited lifetimes are clamped to the session plan limit (3600 for HOBBY, 28800 for SUPERAGENT). Local accepts 0 for unlimited or a positive lifetime.'
                    • Min changed from 30 to 0
                    • Max changed from 28800 to 2.147483647e+09

GET /projects/{id}/domains

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: data
                • Items changed
                  • Property 'AllOf' changed
                    • Modified schema: #/components/schemas/FrontendCustomDomainResponse
                    • Properties changed
                    • Modified property: verification_records
                    • Description changed from '' to 'DNS records to publish now. For a managed domain whose hostname the account already owns, the create response names the _acme-challenge CNAME that authorizes certificate issuance and renewal. Otherwise it names the _volcano TXT record that proves ownership of the hostname's registrable domain, and reads return the CNAME once Volcano sees that record. Usually empty for BYOC.'

GET /projects/{id}/frontends/{frontendId}/domain

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Property 'AllOf' changed
              • Modified schema: #/components/schemas/FrontendCustomDomainResponse
                • Properties changed
                  • Modified property: verification_records
                    • Description changed from '' to 'DNS records to publish now. For a managed domain whose hostname the account already owns, the create response names the _acme-challenge CNAME that authorizes certificate issuance and renewal. Otherwise it names the _volcano TXT record that proves ownership of the hostname's registrable domain, and reads return the CNAME once Volcano sees that record. Usually empty for BYOC.'

POST /projects/{id}/frontends/{frontendId}/domain

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: verification_records
                • Description changed from '' to 'DNS records to publish now. For a managed domain whose hostname the account already owns, the create response names the _acme-challenge CNAME that authorizes certificate issuance and renewal. Otherwise it names the _volcano TXT record that proves ownership of the hostname's registrable domain, and reads return the CNAME once Volcano sees that record. Usually empty for BYOC.'
    • Modified response: 201
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: verification_records
                • Description changed from '' to 'DNS records to publish now. For a managed domain whose hostname the account already owns, the create response names the _acme-challenge CNAME that authorizes certificate issuance and renewal. Otherwise it names the _volcano TXT record that proves ownership of the hostname's registrable domain, and reads return the CNAME once Volcano sees that record. Usually empty for BYOC.'

POST /projects/{id}/sandbox-executions

  • Request body changed
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Properties changed
            • New property: max_duration_seconds
            • Modified property: memory_mb
              • Description changed from '' to 'Baseline memory in MiB. Cloud HOBBY supports 1024; SUPERAGENT supports 1024 or 2048. Omission uses the preset or template default; a template requiring more than the plan permits is rejected. Local sessions are exempt from cloud plan limits.'
            • Modified property: timeout_seconds
              • Description changed from '' to 'Command execution time from process start. Cloud defaults to 60 seconds and accepts 1–28800; local defaults to 0 (unlimited) and accepts nonnegative values. VM expiry always takes precedence. Cloud synchronous requests must return within the public connection idle limit (1000 seconds); use a session with a background process and short polling requests for longer work.'
              • Default changed from 60 to null
              • Min changed from 1 to 0
              • Max changed from 60 to 2.147483647e+09
  • Responses changed
    • Modified response: default
      • Description changed from 'Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and temporarily unavailable (503). Code feature_unavailable with 404 means sandboxes are not available in this environment.' to 'Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and temporarily unavailable (503). Code feature_unavailable with 404 means sandboxes are not available in this environment. Code sandbox_plan_limit_exceeded (403) means the requested resources exceed the plan. Code sandbox_allowance_exhausted (429) means the remaining allowance or credits cannot admit the operation.'

GET /projects/{id}/sandbox-sessions

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: data
                • Items changed
                  • Properties changed
                    • Modified property: expires_at
                    • Description changed from '' to 'Absolute VM expiry. Null means unlimited in local mode.'
                    • Nullable changed from false to true
                    • Modified property: sandbox_id
                    • Description changed from '' to 'Explicit template used to create the session. Null when created directly from a preset.'
                    • Nullable changed from false to true

POST /projects/{id}/sandbox-sessions

  • Request body changed
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Properties changed
            • Deleted property: idle_timeout_seconds
            • Modified property: max_duration_seconds
              • Description changed from 'Inherits the template TTL when omitted (3600 seconds for a new template).' to 'Inherits the template TTL when omitted (cloud default 3600 seconds; local default 0, unlimited). Cloud HOBBY accepts 30–3600 seconds; SUPERAGENT accepts 30–28800 seconds. Inherited template defaults are clamped to the plan limit; explicit values above it are rejected. Local accepts 0 for unlimited or a positive lifetime.'
              • Min changed from 30 to 0
              • Max changed from 28800 to 2.147483647e+09
            • Modified property: memory_mb
              • Description changed from '' to 'Baseline memory in MiB. Cloud HOBBY supports 1024; SUPERAGENT supports 1024 or 2048. Omission uses the preset or template default; a template requiring more than the plan permits is rejected. Local sessions are exempt from cloud plan limits.'
  • Responses changed
    • Modified response: 201
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: expires_at
                • Description changed from '' to 'Absolute VM expiry. Null means unlimited in local mode.'
                • Nullable changed from false to true
              • Modified property: sandbox_id
                • Description changed from '' to 'Explicit template used to create the session. Null when created directly from a preset.'
                • Nullable changed from false to true
    • Modified response: default
      • Description changed from 'Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and temporarily unavailable (503). Code feature_unavailable with 404 means sandboxes are not available in this environment.' to 'Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and temporarily unavailable (503). Code feature_unavailable with 404 means sandboxes are not available in this environment. Code sandbox_plan_limit_exceeded (403) means the requested resources exceed the plan. Code sandbox_allowance_exhausted (429) means the remaining allowance or credits cannot admit the operation.'

GET /projects/{id}/usage

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: metrics
                • Items changed
                  • Properties changed
                    • Modified property: metric
                    • Description changed from 'Metric name (for example, "Function & Frontend Invocations", "Frontend Requests",
                      "Durable Executions", "Durable Operations", "Durable Compute (MB-Seconds)",
                      "Build Seconds",
                      "Bandwidth Ingress (Bytes)", "Bandwidth Egress (Bytes)",
                      "Bandwidth Total (Bytes)", or "Database Storage (Bytes)"). Byte-based metrics are
                      reported in bytes. "Bandwidth Total (Bytes)" is derived (ingress + egress) and
                      is not billed separately. The three durable metrics are
                      counted separately from "Function & Frontend Invocations", which covers standard
                      invocations only. Operations and compute are counted when an execution finishes,
                      so they appear in the window the execution completed in rather than the one it
                      started in. "Durable Compute (MB-Seconds)" reports the memory the execution ran
                      at times the time it spent running, in megabyte-seconds; the allowance for it is
                      published in gigabyte-seconds, which is 1024 of these.
                      "Sandbox Running (MiB-Seconds)", "Sandbox Suspended (Seconds)", and
                      "Sandbox Uncertain (MiB-Seconds)" are preview-only usage; they do not
                      debit credits. Running reports configured memory times observed runtime,
                      not measured CPU or elastic memory consumption. Uncertain includes
                      observation gaps and unconfirmed state transitions. Suspended reports
                      duration, not snapshot size. Local sessions do not contribute.
                      Totals are rounded down after aggregating millisecond measurements.
                      "Database Storage (Bytes)" is a current observed gauge,
                      not a cumulative counter. It is the sum of the latest samples exposed as
                      storage_bytes by the project's database list, so it includes what each
                      database's branches and backups hold, and it inherits that field's lag
                      behind a live measurement.
                      ' to 'Metric name (for example, "Function & Frontend Invocations", "Frontend Requests",
                      "Durable Executions", "Durable Operations", "Durable Compute (MB-Seconds)",
                      "Build Seconds",
                      "Bandwidth Ingress (Bytes)", "Bandwidth Egress (Bytes)",
                      "Bandwidth Total (Bytes)", or "Database Storage (Bytes)"). Byte-based metrics are
                      reported in bytes. "Bandwidth Total (Bytes)" is derived (ingress + egress) and
                      is not billed separately. The three durable metrics are
                      counted separately from "Function & Frontend Invocations", which covers standard
                      invocations only. Operations and compute are counted when an execution finishes,
                      so they appear in the window the execution completed in rather than the one it
                      started in. "Durable Compute (MB-Seconds)" reports the memory the execution ran
                      at times the time it spent running, in megabyte-seconds; the allowance for it is
                      published in gigabyte-seconds, which is 1024 of these.
                      "Sandbox Running (MiB-Seconds)", "Sandbox Suspended (Seconds)", and
                      "Sandbox Uncertain (MiB-Seconds)" report cloud Sandbox usage. Running
                      reports configured baseline memory times confirmed runtime, not measured
                      CPU or elastic memory consumption. For sessions admitted after the pricing
                      release, confirmed running time consumes the account's runtime allowance;
                      SUPERAGENT overage debits credits according to the account's pricing terms.
                      Suspended time and uncertain usage do not consume runtime allowance or
                      debit credits. Uncertain includes observation gaps and unconfirmed state
                      transitions. Suspended reports duration, not snapshot size; snapshot costs
                      are included in runtime pricing. Local and platform image-validation
                      sessions do not contribute. Existing preview sessions remain unbilled,
                      and preview history is never charged retroactively. Displayed totals are
                      rounded down after aggregating millisecond measurements; billing uses
                      unrounded measurements in the monthly account billing cycle.
                      "Database Storage (Bytes)" is a current observed gauge,
                      not a cumulative counter. It is the sum of the latest samples exposed as
                      storage_bytes by the project's database list, so it includes what each
                      database's branches and backups hold, and it inherits that field's lag
                      behind a live measurement.
                      '

DELETE /sandbox-sessions/{sessionId}

  • Responses changed
    • Modified response: 202
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: expires_at
                • Description changed from '' to 'Absolute VM expiry. Null means unlimited in local mode.'
                • Nullable changed from false to true
              • Modified property: sandbox_id
                • Description changed from '' to 'Explicit template used to create the session. Null when created directly from a preset.'
                • Nullable changed from false to true

GET /sandbox-sessions/{sessionId}

  • Responses changed
    • Modified response: 200
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: expires_at
                • Description changed from '' to 'Absolute VM expiry. Null means unlimited in local mode.'
                • Nullable changed from false to true
              • Modified property: sandbox_id
                • Description changed from '' to 'Explicit template used to create the session. Null when created directly from a preset.'
                • Nullable changed from false to true

POST /sandbox-sessions/{sessionId}/exec

  • Request body changed
    • Content changed
      • Modified media type: application/json
        • Schema changed
          • Properties changed
            • Modified property: timeout_seconds
              • Description changed from '' to 'Command execution time from process start. Cloud defaults to 60 seconds and accepts 1–28800; local defaults to 0 (unlimited) and accepts nonnegative values. VM expiry always takes precedence. Cloud synchronous requests must return within the public connection idle limit (1000 seconds); use a session with a background process and short polling requests for longer work.'
              • Default changed from 60 to null
              • Min changed from 1 to 0
              • Max changed from 3600 to 2.147483647e+09

POST /sandbox-sessions/{sessionId}/resume

  • Responses changed
    • Modified response: 202
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: expires_at
                • Description changed from '' to 'Absolute VM expiry. Null means unlimited in local mode.'
                • Nullable changed from false to true
              • Modified property: sandbox_id
                • Description changed from '' to 'Explicit template used to create the session. Null when created directly from a preset.'
                • Nullable changed from false to true
    • Modified response: default
      • Description changed from 'Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and temporarily unavailable (503). Code feature_unavailable with 404 means sandboxes are not available in this environment.' to 'Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and temporarily unavailable (503). Code feature_unavailable with 404 means sandboxes are not available in this environment. Code sandbox_plan_limit_exceeded (403) means the requested resources exceed the plan. Code sandbox_allowance_exhausted (429) means the remaining allowance or credits cannot admit the operation.'

POST /sandbox-sessions/{sessionId}/suspend

  • Responses changed
    • Modified response: 202
      • Content changed
        • Modified media type: application/json
          • Schema changed
            • Properties changed
              • Modified property: expires_at
                • Description changed from '' to 'Absolute VM expiry. Null means unlimited in local mode.'
                • Nullable changed from false to true
              • Modified property: sandbox_id
                • Description changed from '' to 'Explicit template used to create the session. Null when created directly from a preset.'
                • Nullable changed from false to true

Validation

@kong
kong Bot force-pushed the chore/sync-openapi branch from 7cd039d to b69cdc1 Compare August 28, 2026 13:58
@kong
kong Bot force-pushed the chore/sync-openapi branch 4 times, most recently from ebe76ec to 5660716 Compare August 30, 2026 12:25
@kong
kong Bot force-pushed the chore/sync-openapi branch from 5660716 to 697020d Compare September 10, 2026 22:00
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@kong
kong Bot force-pushed the chore/sync-openapi branch 13 times, most recently from ebaec87 to 2891cbb Compare September 17, 2026 18:04
@kong
kong Bot force-pushed the chore/sync-openapi branch 8 times, most recently from 2768536 to 0d69f5d Compare September 19, 2026 06:17
@kong
kong Bot force-pushed the chore/sync-openapi branch from 0d69f5d to b463e46 Compare October 5, 2026 22:54
@kong
kong Bot force-pushed the chore/sync-openapi branch 18 times, most recently from 35606b8 to 8fce68b Compare October 10, 2026 04:36

@marckong marckong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: comment (don't merge as-is). The sync itself is correct and consistent with hosting 614aed52, and it keeps the durable-approvals operations intact. The generated contract change does expose two places where the hand-written SDK code no longer matches it (inline). Checked by reading the diff and the SDK source at this head; I did not run generation or tests locally. CI note: Quality Gate and Mutation Gate failed once on _durable_engine mutation and passed on rerun, which looks like a flake. Not checked: SDK-side validation of the widened timeout_seconds ranges.

Comment thread openapi/openapi.yaml
minimum: 30
maximum: 28800
description: Inherits the template TTL when omitted (3600 seconds for a new template).
idle_timeout_seconds:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] The SDK still sends idle_timeout_seconds, which the contract removes here.

CreateSandboxSessionRequest has additionalProperties: false upstream, and hosting #1743 removed the idle-timeout fields from the API and SDK bindings. Sandboxes.create in src/volcano_sdk/sandboxes.py:68 still loops over ("max_duration_seconds", "idle_timeout_seconds"), and SandboxCreateOptions still declares the field (sandbox_models.py:31).

Callers who pass it will have the request rejected by schema validation (exact status not confirmed). The bot's "Deleted Endpoints: None" report doesn't surface removed properties. Remove the option and the loop entry, and add a test, in a companion change landed with or before this PR.

memory_mb: int
created_at: datetime.datetime
expires_at: datetime.datetime
expires_at: datetime.datetime | None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] expires_at is now nullable, but session decoding rejects null.

SandboxSession in sandbox_session.py:89 and _update at :166 apply timestamp() from _sandbox.py to expires_at. timestamp() is built to require an aware timestamp, so I expect it to raise on None. I only read its start, so this is inferred. The public property is typed datetime (:113).

Local mode with unlimited lifetime returns null, so creating, getting or refreshing such a session would fail. Cloud always returns an expiry, so it isn't affected. sandbox_id is also nullable now, but the SDK doesn't read it.

Hosting #1743 notes that published-client decoding wasn't validated. Make expires_at datetime | None and add a test.

@kong
kong Bot force-pushed the chore/sync-openapi branch 2 times, most recently from 2066a06 to d1fc741 Compare October 11, 2026 01:25
@kong
kong Bot force-pushed the chore/sync-openapi branch from d1fc741 to 0123ed9 Compare October 11, 2026 21:07

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants