Skip to content

Record where a deployment's pack service runs

View as Markdown
PUT
/v1/system/tenants/{tenantId}/deployments/{deploymentId}/endpoint
curl --request PUT \
--url https://example.com/v1/system/tenants/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/deployments/example/endpoint \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "url": "example", "auth": "google-id-token", "token": "example", "packEnvRevision": "example" }'

Records the endpoint, once every check passes: the URL is https://<host> (endpoint-url-invalid); its host is on the operator’s allowlist (endpoint-host-not-allowed); its host names the deployment’s own service, packServiceName(tenantId, deploymentId) then - or . (endpoint-name-mismatch); the image is in the tenant’s repository (image-not-allowed); the pack service answers /v1/info, with the kindgi-tenant-id header, as this deployment (endpoint-unreachable, endpoint-info-mismatch, with the names of the fields that differed). A refusal is also recorded as the endpoint’s problem, which the tenant sees as a code. The deployment’s endpoint is then ready. Refused for a closing or suspended tenant, project or pack, so a sweep can’t recreate a service another one retired. Takes system:deployments. The same body twice records it once.

tenantId
required
string format: uuid

The tenant’s id (a UUID).

deploymentId
required
string
>= 1 characters <= 128 characters

The deployment’s id, as GET /v1/system/deployments lists it.

Idempotency-Key
string
>= 1 characters

Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5). A request whose key store can’t be read before it runs is answered 503 idempotency-store-unavailable with Retry-After: nothing ran, so retry with the same key (from 0.3.0).

Media typeapplication/json
object
url
required

https://<host>: no user info, path, query or fragment. Its host must be on the operator’s allowlist (KINDGI_PACK_ENDPOINT_HOSTS) and begin with the deployment’s own service name (packServiceName), then - or ..

string
auth
required

How the server calls it: google-id-token adds an ID token for the URL (Cloud Run’s invoker check) to the pack token; token sends the pack token only.

string
Allowed values: google-id-token token
token
required

The pack service’s token (KINDGI_PACK_SERVICE_TOKEN), printable ASCII without spaces. Stored wrapped; never returned, logged or recorded.

string
>= 16 characters <= 512 characters
packEnvRevision

The revision from GET …/pack-env whose values the service was made with, when its pack declares an environment. Kept as the one it runs, so GET /v1/system/pack-env lists it once they change.

string
>= 1 characters <= 128 characters

Recorded: the deployment’s endpoint as its tenant sees it.

Media typeapplication/json

Its pack service’s status, when the server routes each pack call to the deployment that shipped the tool (KINDGI_PACK_ROUTING=per-deployment). Absent otherwise, and for a deployment that ships nothing a pack service serves (no tool, and no guardrail check but built-in ones: a pack of agents and flows only), which needs none. pending: no pack service yet, and calls to its tools fail (pack-endpoint-pending) rather than go to another deployment. ready: calls go to its own pack service. cleared: its pack service was taken down, and calls fail (pack-endpoint-cleared); it carries waiting or retired to say whether it comes back. Carries no URL and no token.

object
status
required
string
Allowed values: pending ready cleared
since
required

When the status last changed.

string format: date-time
problem

While the deployment waits for a pack service (pending, or cleared and waiting): the last reason recorded while it waited. A ready endpoint has none, nor a retired one. A fixed code, never free text.

object
code
required

One of a fixed list; a later runtime may add codes, so treat an unknown one as a reason not yet named. The server refused the endpoint it was given: endpoint-url-invalid (not https, or with user info or a path), endpoint-host-not-allowed (the host isn’t on the operator’s allowlist), endpoint-name-mismatch (the host doesn’t name this deployment’s service), endpoint-unreachable (the pack service didn’t answer), endpoint-info-mismatch (it answered as another pack or version), image-not-allowed (the image is outside the tenant’s repository). The pack service couldn’t be created: tenant-not-provisioned (the tenant has nowhere to run pack services yet), capacity-unavailable (no room for another pack service just now), service-start-failed (the image was deployed but didn’t start). It can’t be given its declared environment (GET /v1/deployments/{deploymentId}/pack-env names the names): pack-env-ambiguous, pack-env-secret-not-yet, pack-env-missing, pack-env-secret-unreadable (a name’s secret can’t be read for a reason the platform fixes, not the owner; it’s tried again). It can’t be given its secrets: pack-env-secrets-unaudited (the runtime has nowhere to audit a secret it gives out; the platform fixes it, and it’s tried again), pack-env-secret-too-large (a secret’s value is over 32768 bytes, the most a pack service can be given), pack-env-name-too-long (a name set as a secret is too long for the secret it’s kept in, which is named after the pack service; shorten it in the pack), pack-env-secret-capacity (a name is set only as a secret, and there’s no room just now for a pack service that can be given one, apart from other projects’; it’s tried again).

string
since
required

When it was recorded.

string format: date-time
waiting

cleared only: a pack service is wanted for it again, as once a suspension that took its service down is lifted, and it lists as needing one; problem says why it isn’t back yet. A cleared endpoint carries this or retired, never both. Absent from older servers, which send neither.

boolean
retired

cleared only: why no pack service is wanted for it now. superseded: nothing a call can still ask for needs it: for each tool version, pack check, agent and flow version it serves, a newer deployment into its project serves it too, or it’s unregistered and not held (a check: no registered guardrail runs it in its project); and each tool it deployed without a version, a newer deployment into its project deploys without one too (from Kindgi 0.4.0; before, it meant newer deployments into its project shipped every tool version and check it does and deployed each tool it deployed without a version the same way, and was for good). One whose endpoint an earlier runtime made or last set is superseded as well, for good, once newer deployments into its project ship every tool version and check it does and deploy each tool it deployed without a version the same way. Otherwise it’s needed again once something it serves that no newer deployment into its project serves is wanted again: a tool, agent or flow version registered or held again, or a check a newly registered guardrail runs in its project. A tool call a step made on it still goes back to it when the step runs again, and fails closed (pack-endpoint-cleared). tenant-closing, tenant-suspended, project-suspended and pack-suspended last until the tenant, project or pack is restored. A later runtime may add reasons, so treat an unknown one as a reason not yet named. A cleared endpoint carries this or waiting, never both. Absent from older servers, which send neither.

string
packEnvProblem

ready only: the pack service runs on the values it was last given, because the newest can’t be given to it (a required one was removed, say, or a secret can’t be given), or didn’t start (pack-env-update-failed). Gone once they can, or do. For a name that can’t be given, GET /v1/deployments/{deploymentId}/pack-env names it. Absent from older servers.

object
code
required

Why a ready pack service runs on the values it was last given: a PackEnvProblemCode, so the newest can’t be given to it; pack-env-update-failed: they were given, and its new revision with them didn’t start, so the last ready one serves. That revision is tried again for an hour after it’s first recorded; setting the values again is a new revision, tried again too. The orchestrator couldn’t give it its secrets: pack-env-secrets-unaudited (the runtime has nowhere to audit a secret it gives out, so it gives none; the platform fixes it), pack-env-secret-too-large (a secret’s value is over 32768 bytes, the most a pack service can be given), pack-env-name-too-long (a name set as a secret is too long for the secret it’s kept in, which is named after the pack service; shorten it in the pack), pack-env-secret-redeploy (a name is now set only as a secret, and this pack service was made where no secret can be given to it; a new deployment’s can be, from a new build of the pack), pack-env-cloud-secret-unsupported (a name is set to a cloud secret, and this pack service’s host mounts none; removing it, or setting a value instead, moves the revision). A service held as pack-env-secret-unreadable or pack-env-secrets-unaudited is listed by GET /v1/system/pack-env every time, with its held, as the revision doesn’t move when the platform fixes it. A later runtime may add codes, so treat an unknown one as a reason not yet named.

string
Allowed values: pack-env-ambiguous pack-env-secret-not-yet pack-env-missing pack-env-secret-unreadable pack-env-update-failed pack-env-secrets-unaudited pack-env-secret-too-large pack-env-name-too-long pack-env-cloud-secret-unsupported pack-env-secret-redeploy
since
required

When it was recorded.

string format: date-time
keptFor

What keeps this build’s pack service, whatever its status, in kind, id, then version order. [] when nothing does: it’s retired (superseded), or retired next. A suspended build has retired and still lists what keeps it, since its service comes back when the suspension lifts. On a list page, the first 20 entries, with keptForTotal; a get of one deployment gives them all. Absent when builds aren’t counted (one service serves every build), and from a runtime before Kindgi 0.4.0.

Array<object>

One thing a build’s pack service is kept for. To let the build go, unregister it: kindgi tools|agents|flows unregister <id> <version>, kindgi guardrails unregister <id>.

object
kind
required

tool: a tool version this build is the newest into its project to route, still registered or held; a tool deployed without a version has no version and neither flag, and is kept until a newer deployment into the project ships the tool. agent, flow: a version this build is the newest into its project to ship or carry, still registered or held. guardrail: a registered guardrail that runs a pack check this build is the newest into its project to route; it has no version. A later runtime may add kinds, so treat an unknown one as a kind not yet named.

string
id
required

The tool, agent, flow or guardrail id.

string
version

The version kept for. Absent for a guardrail, or a tool deployed without one.

string
registered

The version (or guardrail) is registered.

boolean
held

A pin or a run that hasn’t finished uses the version. Unregistering it then lets the build go only once the pin’s own version is unregistered or the run finishes. Sent beside registered when both are true.

boolean
keptForTotal

On a list page, with keptFor: how many entries there are, of which keptFor holds the first 20. A get of one deployment doesn’t send it.

integer
Example
{
"status": "pending",
"waiting": true,
"packEnvProblem": {
"code": "pack-env-ambiguous"
},
"keptFor": [
{
"registered": true,
"held": true
}
]
}

A malformed body (bad-input), or a URL that isn’t https://<host> (endpoint-url-invalid).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Missing / malformed / expired / revoked bearer token.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

A tenant’s key or session (system-principal-required), or a system key without system:deployments (system-scope-missing).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

No such tenant (tenant-not-found), or no such deployment in it (deployment-not-found).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The tenant is closing or suspended (tenant-closing, tenant-suspended), or the project or pack is (project-suspended, pack-suspended); the image is outside the tenant’s repository (image-not-allowed).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The request body is over the API’s limit (request-too-large; details.maxBytes says how much).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The host isn’t allowed (endpoint-host-not-allowed) or doesn’t name the deployment’s service (endpoint-name-mismatch, with details.expected); the pack service didn’t answer (endpoint-unreachable) or answered as another pack or version (endpoint-info-mismatch, with details.differs).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Server error (unmapped domain code or framework crash).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The operator’s access record can’t be written, so nothing was done (access-record-unavailable), or the Idempotency-Key store couldn’t be read before the request ran (idempotency-store-unavailable, with Retry-After).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

See also