Zaroz
Units your code controls

Unit contract v1: JSON Schemas

These are the schemas of contract v1, draft 2020-12, copied verbatim from the files the agent embeds and validates against. Each is also served as a file under /contract/units/v1/. The $id URLs are the canonical identifiers.

POST /accepting request body

A JSON boolean (the literal true or false). An empty body means true. The signals ready, idle, busy and shutdown take no body. The same text is the content of the file signals/accepting.

Raw file: accepting-request.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/accepting-request.schema.json", "title": "POST /accepting request body", "description": "A JSON boolean (the literal true or false). An empty body means true. The signals ready, idle, busy and shutdown take no body. The same text is the content of the file signals/accepting.", "type": "boolean" }

/zaroz/allocation.json

null while the unit is not allocated. When allocated, user-data.json already holds the allocation's user_data.

Raw file: allocation.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/allocation.schema.json", "title": "/zaroz/allocation.json", "description": "null while the unit is not allocated. When allocated, user-data.json already holds the allocation's user_data.", "oneOf": [ { "type": "null" }, { "type": "object", "required": [ "id", "allocated_at", "generation" ], "properties": { "id": { "type": "string", "minLength": 1, "maxLength": 128 }, "allocated_at": { "type": "string", "format": "date-time" }, "generation": { "type": "integer" } } } ] }

/zaroz/contract.json

Which contract the files in this directory follow. Read it first.

Raw file: contract.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/contract.schema.json", "title": "/zaroz/contract.json", "description": "Which contract the files in this directory follow. Read it first.", "type": "object", "required": [ "version", "agent_version" ], "properties": { "version": { "const": 1, "description": "Contract major version. Within a major, changes are additive only." }, "agent_version": { "type": "string", "minLength": 1 } } }

Error response of the signal socket

Raw file: error.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/error.schema.json", "title": "Error response of the signal socket", "type": "object", "required": [ "error" ], "properties": { "error": { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "string", "description": "Stable machine-readable code, for example unknown_signal, invalid_body, invalid_wait, not_ready, body_too_large." }, "message": { "type": "string" } } } } }

Unit event envelope

One event of the units event log, as returned by the events route and delivered to webhooks. Consumers must ignore unknown fields and unknown event types.

Raw file: event.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/event.schema.json", "title": "Unit event envelope", "description": "One event of the units event log, as returned by the events route and delivered to webhooks. Consumers must ignore unknown fields and unknown event types.", "type": "object", "required": [ "seq", "id", "type", "contract_version", "occurred_at", "service_instance_id", "unit", "data" ], "properties": { "seq": { "type": "integer", "minimum": 0, "description": "Gapless and strictly increasing per Workload, from 1. Only the delivery-only webhook.ping may carry 0 (the cursor of a webhook that has delivered nothing yet)." }, "id": { "type": "string", "pattern": "^evt_[0-9a-fA-F-]{32,36}$" }, "type": { "type": "string", "minLength": 1 }, "contract_version": { "const": 1 }, "occurred_at": { "type": "string", "format": "date-time" }, "service_instance_id": { "type": "string", "minLength": 1 }, "unit": { "oneOf": [ { "type": "null" }, { "type": "object", "required": [ "id", "key", "labels" ], "properties": { "id": { "type": "string", "minLength": 1 }, "key": { "type": "string", "minLength": 1, "maxLength": 40 }, "labels": { "type": "object", "additionalProperties": { "type": "string" } } } } ] }, "data": { "type": "object" } }, "allOf": [ { "if": { "properties": { "type": { "const": "webhook.ping" } }, "required": [ "type" ] }, "else": { "properties": { "seq": { "minimum": 1 } } } }, { "if": { "properties": { "type": { "const": "unit.exited" } }, "required": [ "type" ] }, "then": { "properties": { "data": { "type": "object", "required": [ "code", "restarted" ], "properties": { "code": { "type": "integer" }, "restarted": { "type": "boolean" } } } } } }, { "if": { "properties": { "type": { "enum": [ "unit.failed", "unit.destroyed" ] } }, "required": [ "type" ] }, "then": { "properties": { "data": { "type": "object", "required": [ "reason" ], "properties": { "reason": { "type": "string" } } } } } }, { "if": { "properties": { "type": { "const": "units.scaled" } }, "required": [ "type" ] }, "then": { "properties": { "unit": { "type": "null" }, "data": { "type": "object", "required": [ "from", "to", "reason" ], "properties": { "from": { "type": "integer", "minimum": 0 }, "to": { "type": "integer", "minimum": 0 }, "reason": { "type": "string" } } } } } }, { "if": { "properties": { "type": { "enum": [ "unit.ready", "unit.allocated" ] } }, "required": [ "type" ] }, "then": { "properties": { "unit": { "type": "object" }, "data": { "type": "object", "required": [ "private_name" ], "properties": { "private_name": { "type": "string" }, "public_endpoints": { "type": "array" } } } } } }, { "if": { "properties": { "type": { "enum": [ "unit.created", "unit.starting", "unit.accepting", "unit.not_accepting", "unit.allocation_delivered", "unit.allocation_undelivered", "unit.idle", "unit.busy", "unit.draining", "unit.stopped" ] } }, "required": [ "type" ] }, "then": { "properties": { "unit": { "type": "object" } } } } ] }

Response of POST /<signal>

Raw file: signal-response.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/signal-response.schema.json", "title": "Response of POST /<signal>", "type": "object", "required": [ "ok", "signal", "changed" ], "properties": { "ok": { "const": true }, "signal": { "enum": [ "ready", "accepting", "idle", "busy", "shutdown" ] }, "changed": { "type": "boolean", "description": "false when the signal repeated the current state and was coalesced." } } }

/zaroz/state.json

Whether the unit is being drained. A draining unit has already left the load-balanced set; finish up and exit before the pod's termination grace ends.

Raw file: state.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/state.schema.json", "title": "/zaroz/state.json", "description": "Whether the unit is being drained. A draining unit has already left the load-balanced set; finish up and exit before the pod's termination grace ends.", "oneOf": [ { "type": "object", "required": [ "draining" ], "properties": { "draining": { "const": false } } }, { "type": "object", "required": [ "draining", "reason" ], "properties": { "draining": { "const": true }, "reason": { "enum": [ "stop", "destroy", "replace", "scale_down" ] } } } ] }

UnitSignal (units.zaroz.cloud/v1) spec

Written by the kernel, read by the agent. The agent ignores unknown fields and refuses a spec that fails validation, keeping the previous contract.

Raw file: unit-signal-spec.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/unit-signal-spec.schema.json", "title": "UnitSignal (units.zaroz.cloud/v1) spec", "description": "Written by the kernel, read by the agent. The agent ignores unknown fields and refuses a spec that fails validation, keeping the previous contract.", "type": "object", "required": [ "unitId", "key", "contractVersion", "generation" ], "properties": { "unitId": { "type": "string", "minLength": 1, "maxLength": 128 }, "key": { "type": "string", "minLength": 1, "maxLength": 40, "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$" }, "labels": { "type": "object", "maxProperties": 16, "propertyNames": { "minLength": 1, "maxLength": 32, "pattern": "^[a-z0-9]([a-z0-9_.-]*[a-z0-9])?$" }, "additionalProperties": { "type": "string", "maxLength": 64 } }, "userData": { "description": "Any JSON value, null for none." }, "allocation": { "oneOf": [ { "type": "null" }, { "type": "object", "required": [ "id", "generation" ], "properties": { "id": { "type": "string", "minLength": 1, "maxLength": 128 }, "generation": { "type": "integer" }, "allocatedAt": { "type": "string", "format": "date-time", "description": "Optional; the agent stamps the time it first saw the allocation when absent." } } } ] }, "draining": { "oneOf": [ { "const": false }, { "enum": [ "stop", "destroy", "replace", "scale_down" ] } ], "description": "false, or the reason." }, "contractVersion": { "const": 1 }, "generation": { "type": "integer", "minimum": 0, "description": "Bump on every change; the agent acknowledges it in status.observedGeneration after the files are written." }, "publicEndpoints": { "type": "array", "description": "Optional override of the pod's ZAROZ_PUBLIC_ENDPOINTS, for an address assigned after pod creation.", "items": { "type": "object", "required": [ "protocols", "internal_port", "address" ], "properties": { "protocols": { "type": "array", "items": { "type": "string" } }, "internal_port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "address": { "type": "string" } } } } } }

UnitSignal (units.zaroz.cloud/v1) status

Written by the agent through the status subresource only, coalesced to at most 5 patches per second. Every field is always present (null, not absent) because the agent patches with a JSON merge patch.

Raw file: unit-signal-status.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/unit-signal-status.schema.json", "title": "UnitSignal (units.zaroz.cloud/v1) status", "description": "Written by the agent through the status subresource only, coalesced to at most 5 patches per second. Every field is always present (null, not absent) because the agent patches with a JSON merge patch.", "type": "object", "required": [ "observedGeneration", "agentVersion", "signalledReady", "accepting", "activity", "activitySince", "shutdownRequestedAt", "allocationAck", "seq" ], "properties": { "observedGeneration": { "type": "integer" }, "agentVersion": { "type": "string" }, "signalledReady": { "oneOf": [ { "type": "null" }, { "type": "string", "format": "date-time" } ] }, "accepting": { "type": "boolean" }, "activity": { "oneOf": [ { "type": "null" }, { "enum": [ "idle", "busy" ] } ] }, "activitySince": { "oneOf": [ { "type": "null" }, { "type": "string", "format": "date-time" } ] }, "shutdownRequestedAt": { "oneOf": [ { "type": "null" }, { "type": "string", "format": "date-time" } ] }, "allocationAck": { "oneOf": [ { "type": "null" }, { "type": "string" } ], "description": "Id of the allocation whose files are written, null when none." }, "seq": { "type": "integer", "minimum": 0, "description": "Monotonic per agent start." } } }

/zaroz/unit.json

Who this unit is. Labels update live; every other field is fixed for the life of the pod. Ignore fields you do not know.

Raw file: unit.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/unit.schema.json", "title": "/zaroz/unit.json", "description": "Who this unit is. Labels update live; every other field is fixed for the life of the pod. Ignore fields you do not know.", "type": "object", "required": [ "contract_version", "unit_id", "key", "labels", "origin", "workload", "project_id", "region", "private_name", "public_endpoints", "incarnation", "started_at" ], "properties": { "contract_version": { "const": 1 }, "unit_id": { "type": "string", "minLength": 1, "maxLength": 128 }, "key": { "type": "string", "minLength": 1, "maxLength": 40, "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$" }, "labels": { "type": "object", "maxProperties": 16, "propertyNames": { "minLength": 1, "maxLength": 32, "pattern": "^[a-z0-9]([a-z0-9_.-]*[a-z0-9])?$" }, "additionalProperties": { "type": "string", "maxLength": 64 } }, "origin": { "type": "string", "minLength": 1, "description": "How the unit came to exist (for example policy, code, warm)." }, "workload": { "type": "object", "required": [ "id", "slug" ], "properties": { "id": { "type": "string", "minLength": 1 }, "slug": { "type": "string", "minLength": 1 } } }, "project_id": { "type": "string", "minLength": 1 }, "region": { "type": "string", "minLength": 1 }, "private_name": { "type": "string", "minLength": 1, "description": "<key>.<workload>, resolvable from the project's other units." }, "public_endpoints": { "type": "array", "items": { "type": "object", "required": [ "protocols", "internal_port", "address" ], "properties": { "protocols": { "type": "array", "items": { "type": "string" } }, "internal_port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "address": { "type": "string" } } } }, "incarnation": { "type": "integer", "minimum": 0 }, "started_at": { "type": "string", "format": "date-time" } } }

/zaroz/user-data.json

The customer's JSON value for this unit, or null. At most 64 KiB serialized compactly and nested at most 32 deep (enforced before it is delivered); any JSON value otherwise.

Raw file: user-data.schema.json

JSONCode
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://zaroz.cloud/contract/units/v1/user-data.schema.json", "title": "/zaroz/user-data.json", "description": "The customer's JSON value for this unit, or null. At most 64 KiB serialized compactly and nested at most 32 deep (enforced before it is delivered); any JSON value otherwise." }
Last modified on