promote

Generated automatically from the published contract sources.

Build metadata: Registered in this build. Registration describes the default dispatcher in this build. It does not guarantee that a caller has the required credential or grant, that a tool is listed for that connection, or that the required service is configured.

A script calls this action over HTTPS at POST https://turnzero.ai/api/v1/actions/promote, with a bearer credential and the action's payload as the JSON body.

Contract description

Promote a version the history holds to production with production's own settings and credentials: the development environment's serving version, or the version named. On an application with one environment, whose deploy reaches production itself, it is refused `environment_not_created`, naming `create_environment`, and `roll_back` puts an earlier version back. It reuses the image built at deploy, so a version whose image the platform's retention deleted is refused version_image_pruned. With `wait_seconds`, up to 45, it holds its answer until the promote ends, leading with a one-line `summary`; an answer that did not settle names the `next` call. Without it, it answers at once and completes detached; read its end through `read_status` or `list_versions`, which name its `step` while it runs. A promote reads `deployed` once every router reaches the new version, typically 33 to 45 seconds, so one wait usually covers it; the health gate's own bound is 180 seconds.

An answer that is not this platform's own, such as a gateway's error page or a closed connection, says nothing about whether the promote was made. Read `read_status` with `wait_seconds` first: the promote started where `environments.production.deploy` names the kind `promote` with a `started_at` later than your call. Call `promote` again only where that read shows it did not start.

Access and action metadata

{
  "name": "promote",
  "resource": "environment",
  "tier": "reversible",
  "summary": "Promote a version the history holds to production with production's own settings and credentials: the development environment's serving version, or the version named. It reuses the image built at deploy, so a version whose image the platform's retention deleted is refused `version_image_pruned`; it answers at once with the state `deploying`, and completes detached, read to its end through `read_status` and `list_versions`. With `wait_seconds` up to 45 it holds its answer until the promote ends, leading with a `summary`; unsettled, it names the `next` call. On an application with one environment, whose deploy reaches production itself, it is refused `environment_not_created`, naming `create_environment` and `roll_back`.\n\nAn answer that is not this platform's own, such as a gateway's error page or a closed connection, says nothing about whether the promote was made. Read `read_status` with `wait_seconds` first: the promote started where `environments.production.deploy` names the kind `promote` with a `started_at` later than your call. Call `promote` again only where that read shows it did not start.",
  "annotations": {
    "readOnlyHint": false,
    "destructiveHint": true,
    "openWorldHint": true
  }
}

MCP catalog entry

{
  "name": "promote",
  "tier": "reversible",
  "scenario": "CHI-L0-07",
  "summary": "Promote a version the history holds to production with production's own settings and credentials: the development environment's serving version, or the version named. On an application with one environment, whose deploy reaches production itself, it is refused `environment_not_created`, naming `create_environment`, and `roll_back` puts an earlier version back. It reuses the image built at deploy, so a version whose image the platform's retention deleted is refused version_image_pruned. With `wait_seconds`, up to 45, it holds its answer until the promote ends, leading with a one-line `summary`; an answer that did not settle names the `next` call. Without it, it answers at once and completes detached; read its end through `read_status` or `list_versions`, which name its `step` while it runs. A promote reads `deployed` once every router reaches the new version, typically 33 to 45 seconds, so one wait usually covers it; the health gate's own bound is 180 seconds.\n\nAn answer that is not this platform's own, such as a gateway's error page or a closed connection, says nothing about whether the promote was made. Read `read_status` with `wait_seconds` first: the promote started where `environments.production.deploy` names the kind `promote` with a `started_at` later than your call. Call `promote` again only where that read shows it did not start.",
  "owners": [
    "PLD-L0-43",
    "PLD-L0-63",
    "DBS-L0-02",
    "SEC-L0-07",
    "MAPI-04"
  ]
}

request

JSON pointer Description and constraints
"" (root) Type: object
Required fields: ["application"]
/properties/application The application id, from `list_applications`.

Type: string
/properties/version Optional. The number of a deployed version-history row of the application, in either environment and not retired by its environment's deletion; absent, the development environment's serving version is promoted.

Type: integer
Minimum: 1
/properties/rotate_database_credential Optional; absent, false. Where true and the manifest declares the database kind, the promote also re-mints the production database role's password under the same window as the platform credential, the production database's rotation act; the value is never answered.

Type: boolean
/properties/wait_seconds Optional. The seconds, 1 to 45, the answer is held until the version-history row this call starts ends, counted from the call's arrival. Absent, the call answers 202 at once with the state `deploying`. The wait takes the application's one held place, so a concurrent held `read_status` answers at once, from its own read. A value outside that range is refused `invalid_request`, its detail naming 45 as the bound.

Type: integer
Minimum: 1
Maximum: 45

response

JSON pointer Description and constraints
"" (root) Answered 202 at once where the request carries no `wait_seconds`: the promote's history row is inserted and the work continues detached; its end is read through `read_status` and `list_versions`, never through the action record (PLD-L0-63; MAPI-04). With `wait_seconds`, the answer is held until the row ends: settled, it is 200 with the state `deployed` or `failed` and the row's `outcome`; unsettled, it is 202 with `next` (MAPI-04; PLD-L0-63). On an application with one environment, whose deploy reaches production itself, `promote` is refused `environment_not_created` before any other check, its detail naming `roll_back` and `create_environment` (PLD-L0-43; PLD-L0-96).

Type: object
Required fields: ["contract_version","application","environment","version","state","hostname"]
/properties/contract_version Required value: 1
/properties/reference The short reference the platform recorded this call under, ten lowercase hexadecimal characters, the value the call’s record row carries; quote it when reporting the call.

Type: string
Pattern: ^[0-9a-f]{10}$
/properties/summary The answer's first member: one sentence naming the environment's state and serving version and, for the row this call started, its version, kind, step, and seconds since it started, or how it ended (PLD-L0-63).

Type: string
/properties/application Type: string
/properties/environment Always `production`: a promote targets production alone (PLD-L0-43).

Type: string
Pattern: ^production$
/properties/version The promoted number, an existing number of the application's history and never a fresh one (PLD-L0-43).

Type: integer
/properties/state `deploying` on the 202 answer, which precedes the row's end. The state is `deployed` or `failed` on the 200 answer, where the request's `wait_seconds` saw the row end.

Type: string
Pattern: ^(deploying|deployed|failed)$
/properties/hostname Type: string
/properties/health_path The recorded manifest's health path, which the health gate that follows this act will probe, cut at 256 characters as the gate's record keeps it. It is absent only where the recorded manifest holds no health path, which the manifest's schema admits nowhere (PLD-L0-63).

Type: string
/properties/settled Present where the request carried `wait_seconds`. True where the one read after the wait found the row this call started ended, whatever ended the wait. False means that read found the row still deploying, or could not read it, and not that it failed: `next` names the call that waits on it (MAPI-04; PLD-L0-63).

Type: boolean
/properties/waited_ms Present where the request carried `wait_seconds`: the milliseconds the answer was held after the row started.

Type: integer
Minimum: 0
/properties/outcome Present where the wait settled: the row's `outcome` as `list_versions` answers it. Its `result` is `succeeded` on a deployed row and `failed`, `interrupted`, or `superseded` on a failed one (PLD-L0-63).

Type: object
/properties/next Present where the wait did not settle: the exact call that reads the row to its end, `read_status` naming `production`, with `wait_seconds` 45.

Type: object
Required fields: ["action","arguments"]
Additional properties: false
/properties/next/properties/action Required value: read_status
/properties/next/properties/arguments Type: object
Required fields: ["application","environment","wait_seconds"]
Additional properties: false
/properties/next/properties/arguments/properties/application Type: string
/properties/next/properties/arguments/properties/environment Required value: production
/properties/next/properties/arguments/properties/wait_seconds Required value: 45
/properties/detail With the state `deploying`, names how the promote's step and end are read: the `next` call, `read_status` with `wait_seconds` 45, or a read every ten seconds (MAPI-04). With `deployed` or `failed`, names how the row ended; with `deployed`, it also says the health check requested the health path alone, and to request the other routes and read `read_logs` for errors.

Type: string

Complete payload contract

{
  "request": {
    "type": "object",
    "required": [
      "application"
    ],
    "properties": {
      "application": {
        "type": "string",
        "description": "The application id, from `list_applications`."
      },
      "version": {
        "type": "integer",
        "minimum": 1,
        "description": "Optional. The number of a deployed version-history row of the application, in either environment and not retired by its environment's deletion; absent, the development environment's serving version is promoted."
      },
      "rotate_database_credential": {
        "type": "boolean",
        "description": "Optional; absent, false. Where true and the manifest declares the database kind, the promote also re-mints the production database role's password under the same window as the platform credential, the production database's rotation act; the value is never answered."
      },
      "wait_seconds": {
        "type": "integer",
        "minimum": 1,
        "maximum": 45,
        "description": "Optional. The seconds, 1 to 45, the answer is held until the version-history row this call starts ends, counted from the call's arrival. Absent, the call answers 202 at once with the state `deploying`. The wait takes the application's one held place, so a concurrent held `read_status` answers at once, from its own read. A value outside that range is refused `invalid_request`, its detail naming 45 as the bound."
      }
    }
  },
  "response": {
    "type": "object",
    "required": [
      "contract_version",
      "application",
      "environment",
      "version",
      "state",
      "hostname"
    ],
    "properties": {
      "contract_version": {
        "const": 1
      },
      "reference": {
        "type": "string",
        "pattern": "^[0-9a-f]{10}$",
        "description": "The short reference the platform recorded this call under, ten lowercase hexadecimal characters, the value the call’s record row carries; quote it when reporting the call."
      },
      "summary": {
        "type": "string",
        "description": "The answer's first member: one sentence naming the environment's state and serving version and, for the row this call started, its version, kind, step, and seconds since it started, or how it ended (PLD-L0-63)."
      },
      "application": {
        "type": "string"
      },
      "environment": {
        "type": "string",
        "pattern": "^production$",
        "description": "Always `production`: a promote targets production alone (PLD-L0-43)."
      },
      "version": {
        "type": "integer",
        "description": "The promoted number, an existing number of the application's history and never a fresh one (PLD-L0-43)."
      },
      "state": {
        "type": "string",
        "pattern": "^(deploying|deployed|failed)$",
        "description": "`deploying` on the 202 answer, which precedes the row's end. The state is `deployed` or `failed` on the 200 answer, where the request's `wait_seconds` saw the row end."
      },
      "hostname": {
        "type": "string"
      },
      "health_path": {
        "type": "string",
        "description": "The recorded manifest's health path, which the health gate that follows this act will probe, cut at 256 characters as the gate's record keeps it. It is absent only where the recorded manifest holds no health path, which the manifest's schema admits nowhere (PLD-L0-63)."
      },
      "settled": {
        "type": "boolean",
        "description": "Present where the request carried `wait_seconds`. True where the one read after the wait found the row this call started ended, whatever ended the wait. False means that read found the row still deploying, or could not read it, and not that it failed: `next` names the call that waits on it (MAPI-04; PLD-L0-63)."
      },
      "waited_ms": {
        "type": "integer",
        "minimum": 0,
        "description": "Present where the request carried `wait_seconds`: the milliseconds the answer was held after the row started."
      },
      "outcome": {
        "type": "object",
        "description": "Present where the wait settled: the row's `outcome` as `list_versions` answers it. Its `result` is `succeeded` on a deployed row and `failed`, `interrupted`, or `superseded` on a failed one (PLD-L0-63)."
      },
      "next": {
        "type": "object",
        "required": [
          "action",
          "arguments"
        ],
        "properties": {
          "action": {
            "const": "read_status"
          },
          "arguments": {
            "type": "object",
            "required": [
              "application",
              "environment",
              "wait_seconds"
            ],
            "properties": {
              "application": {
                "type": "string"
              },
              "environment": {
                "const": "production"
              },
              "wait_seconds": {
                "const": 45
              }
            },
            "additionalProperties": false
          }
        },
        "additionalProperties": false,
        "description": "Present where the wait did not settle: the exact call that reads the row to its end, `read_status` naming `production`, with `wait_seconds` 45."
      },
      "detail": {
        "type": "string",
        "description": "With the state `deploying`, names how the promote's step and end are read: the `next` call, `read_status` with `wait_seconds` 45, or a read every ten seconds (MAPI-04). With `deployed` or `failed`, names how the row ended; with `deployed`, it also says the health check requested the health path alone, and to request the other routes and read `read_logs` for errors."
      }
    },
    "description": "Answered 202 at once where the request carries no `wait_seconds`: the promote's history row is inserted and the work continues detached; its end is read through `read_status` and `list_versions`, never through the action record (PLD-L0-63; MAPI-04). With `wait_seconds`, the answer is held until the row ends: settled, it is 200 with the state `deployed` or `failed` and the row's `outcome`; unsettled, it is 202 with `next` (MAPI-04; PLD-L0-63). On an application with one environment, whose deploy reaches production itself, `promote` is refused `environment_not_created` before any other check, its detail naming `roll_back` and `create_environment` (PLD-L0-43; PLD-L0-96)."
  }
}

Shared contracts