Schemas
AddDomainRequest
domainThe hostname the organization is proving it controls, for example
shop.acme.com. Normalized (lowercased, trailing root dot stripped)
and validated server-side; see the domain's own normalize_domain.
AddEndpointRequest
internal_portThe port the service listens on inside the container, 1 to 65535.
domainshttps only: the customer's own domains to serve on this endpoint. Each must be a
domain the organization has verified, or a subdomain of one, exactly as for a Web App;
certificates are issued automatically. All or nothing: one refused domain opens
nothing. More can be added later.
kindport (the default, so a request written before kinds existed means what it always
did), unit (a raw port per unit, see Add Service Endpoint) or https.
labelhttps only: the label of the free host (<label>.zone.<zone>.zaroz.cloud), one DNS
label. Omitted, the host is named after the endpoint's id.
For port and unit: tcp, udp, or tcp_udp for one public number on both; required. For
https: omit it (always TCP, TLS ends at the platform and the app serves plain HTTP);
tcp is accepted.
AddOrganizationMemberRequest
user_idThe user to add to this organization.
Defaults to member, the least-privileged role: an omitted role must
never widen access further than the caller asked for.
AddTicketMessageRequest
bodyFiles uploaded against this ticket that this message carries. Empty unless the caller uploaded something first; an attachment that is uploaded and never sent stays unreferenced and is not rendered anywhere.
AllocateUnitRequest
fail (default) answers 409 no_warm_unit when no warm unit is ready;
create cold-starts a new one already allocated to you (202).
Replaces the allocated unit's labels whole when given.
user_dataReplaces the allocated unit's user_data whole when given: the match's
roster, map, mode.
AllocateWait
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string |
AllocatedUnitResponse
createdtrue when if_none: create cold-started the unit: it is still starting.
replayedtrue when this Idempotency-Key had already allocated the unit.
The unit, with its user_data and allocation (delivered_at is null until
its agent has the files).
AllocationProtectionStateResponse
allocation_idprotection_statenormal, pressure, or attack. Never unknown: an allocation whose
state was not reported is absent from the list instead, so a caller
can tell "not reported" from "reported as normal".
AlterSharedDatabaseTableRequest
AlterTableOperationRequest
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, column | |
| type = object · requires: kind, name | |
| type = object · requires: kind, from, to | |
| type = object · requires: kind, name, column | |
| type = object · requires: kind, to |
kindafter_columnAnswerSetupStepResponse
One step's answers as a RESPONSE (GET .../setup/steps,
PUT .../setup/steps/{step}'s own echo). Same tag shape as
[SetupStepAnswersDto] for the three Minecraft steps, whose answers hold
nothing secret and so render identically either direction; NEVER the
same shape for [Self::ServerPasswords], which reports only which ids
are set, never a value or a ciphertext -- see
[ServerPasswordsResponseDto].
What landing this answer cost the running service. live when the
submitted answers matched what was already stored.
awaiting_configurationWhether provisioning is still waiting on at least one declared step after this write.
pendingTrue when this answer completed the product's declared steps and (re)provisioning was started, but the attempt itself failed. The answer is still saved; a later read or retry can still succeed.
The closed vocabulary of setup steps kernel knows how to ask, validate and
render. Adding a member is a reviewed code change here, in the dashboard's
step registry, and in whichever product template starts reading its
variables -- the same "closed set, matched code change" discipline
[crate::domain::product_definitions::capabilities::CapabilityId] uses,
for the same reason: a step nothing implements is a claim the platform
cannot back.
Ord is derived so this can key a BTreeMap
([StepAnswersDocument::steps]): declaration order becomes iteration
order there, which is incidental (the document is always looked up by
key, never walked in order) but harmless.
ApiTokenAuthorization
ApiTokenCapability
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
ApiTokenGrant
Closed, policy-owned action catalog. Capabilities are exact: there is
deliberately no prefix or glob matching, and unknown wire values are
rejected during deserialization.
PartialOrd/Ord exist so a capability set can be a BTreeSet, which is
what [crate::domain::auth::application_token::ApplicationToken] stores.
The ordering is the declaration order and is not a wire contract: nothing
serializes it, and as_str remains the only stable representation.
Scope of one grant. Global means the capability is allowed regardless of
resource. ResourceType is every resource in one namespace, while
Resource names exactly one object.
ApiTokenGrantScope
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind | |
| type = object · requires: kind, resource_type | |
| type = object · requires: kind, resource_type, resource_id | |
| type = object · requires: kind, resource_type, root_resource_id |
kindAppAdminDto
usernameemail"" when this product's params never asked for an email.
site_title"" when this product's params never asked for a site title.
AppAdminParamsDto
applyMirrors [AppAdminApply] by hand.
emailWhether this product asks for an admin email at all.
Mirrors [UsernameRule] by hand.
None when this product does not ask for a site title at all.
AppRuntimeParamsDto
start_command_max_lengthAppRuntimeRequestDto
runtimestart_commandvariantAppRuntimeResponseDto
imageinstall_commandruntimestart_commandvariantApplicationConsentPreviewResponse
application_idapplication_namePresentable name, the same one MyApplicationDelegationResponse carries.
ApplicationUserProfile
idnameThe user's display name, as shown to other users.
avatar_asset_idThe profile picture, addressed through /api/v2/assets/{id}. None
when they never set one.
deleted_atSet when the account was deleted. The profile is still answered so a listing can render "deleted user" rather than "unknown user".
ApplicationUsersLookupRequest
idsAt most [MAX_LOOKUP_IDS]; duplicates are fine.
ApplicationUsersLookupResponse
ApplyMode
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
AttachCustomDomainRequest
hostnameThe fully-qualified hostname, for example shop.acme.com.
Validated as a hostname before anything is persisted: trimmed,
lowercased and stripped of a trailing dot, then refused if it is
empty, longer than 253 characters, an IP address literal, a single
label with no dot in it, or carries a label that is empty, longer than
63 characters, hyphen-terminated, or holds anything outside
[a-z0-9-].
AttachEndpointDomainRequest
domainA domain the organization has verified, or a subdomain of one.
AttackSummaryReasonResponse
byteskeypacketsAttackSummaryResponse
attacker_estimateattacksblocked_bytesblocked_packetsdateThe UTC day, YYYY-MM-DD.
mitigated_secondspeak_bits_per_secondservices_stayed_onlineAbsent when continuity cannot be stated honestly from our own measurements.
AttackSummaryServiceResponse
blocked_bytesnameservice_instance_idAttackSummaryTimelineEntryResponse
blocked_bytesduration_secondsstarted_atended_atAbsent while the episode is still open.
service_nameAuditEntryResponse
actioncreated_atidmetadataArbitrary JSON.
principal_kindUser, Application, or System.
api_token_idapi_token_nameprincipal_idprincipal_nameproject_idservice_instance_idWhich of the caller's services this entry is about (ZC-1277).
AdminAuditEntryResponse has always carried it, and its doc comment
explains the omission here as these fields being "the scope of ITS
request, not data about the entry". That is true of
organization_id and was never true of this one: a customer read is
scoped to an organization, and could narrow only as far as a project,
so the service was never the scope of the request -- it was the one
thing the customer could not learn.
sponsor_application_idsponsor_application_nameAuthUserResponse
idis_onboardednameemailResolved through UserEmailService (checks oauth_accounts first,
then password_credentials). None when neither source has an
address for this user -- User itself carries no email field.
BackupResponse
created_atidnameThe label the customer gave it, or kernel's own timestamped default.
statuscreating, ready, failed or restoring.
completed_atPresent once the snapshot has finished or failed.
restore_phaseThe step of an in-progress restore, or null when this backup is not
currently being restored. One of stopping_workloads,
detaching_pre, maint_attaching, reverting, detaching_post,
csi_retaining_pv, csi_recreating_pvc, restarting_workloads.
restore_started_atWhen the current restore began, so a client can render "restoring for
N minutes" without polling a second endpoint. null outside a
restore.
size_bytesPresent once the snapshot has finished (status: "ready" or later).
BackupsResponse
max_backupsThe ceiling POST .../backups is refused against, published here so
a panel never holds it as a literal.
BannedPlayerResponse
namebanned_atreasonsourceBucketKeyView
access_key_idcreated_atidnamescoperead_only or read_write.
last_used_atBucketKeysResponse
BucketResponse
BucketUsageResponse
BucketUsageSampleView
egress_bytesingress_bytesstored_byteswindow_startBucketUsageView
egress_bytesBytes sent out of the bucket in the window (billed).
fromgap_hoursHours with no measurement, filled with the nearest earlier one.
Hourly measurements, oldest first.
storage_gib_monthsAverage stored GiB over the whole window, as a decimal string.
toBucketView
accessWhat the data plane allows right now: open, read_only (over the
cap), suspended (unpaid or moderated) or deleted. Suspended
buckets keep their data and can still be browsed through the console.
addressing_styleAlways path: use path-style addressing
({endpoint}/{bucket_name}/{key}); virtual-hosted style is not served.
bucket_nameThe bucket name to use with that endpoint.
cap_bytescreated_atendpointThe S3 URL to point a client at.
idlabelpublic_readregion_ids3_regionThe region name S3 clients sign with. Not a place: the bucket lives in
region_id.
subscription_idupdated_atpublic_urlWhere anonymous readers fetch objects ({url}{key}); absent unless
public_read is on.
purge_atWhen the bucket's data will be purged, once deleted.
stored_bytesLatest measured stored bytes; absent before the first measurement (measured hourly).
ByOauthAccountResponse
display_namelanguage_tagThe user's language, for example en-US.
user_idCancelWithWalletCreditRequest
quote_idThe quote_id of a quote issued for this subscription.
CancelWithWalletCreditResponse
cancels_atWhen the subscription stops: the instant of this request.
credit_note_idsOne credit note per credited invoice.
statuspending_termination: the subscription now ends and the reaper tears
the service down on its next tick.
subscription_idtotal_credited_centsThe amount credited to the wallet, in minor units.
Capability
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability, root_path | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability, mount_path, resource_id | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability, verbs | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability, id, url +1 more | |
| type = object · requires: capability, url, resource_id +1 more | |
| type = object · requires: capability, secrets_allowed | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability | |
| type = object · requires: capability |
capabilityChangePasswordRequest
current_passwordnew_passwordcurrent_session_idThe caller's own session, spared when the change signs every other session out. Omit to be signed out everywhere, including here.
CheckoutRequest
nameThe customer's name for the service being bought.
The subscription is a purchase of a product and carries no name; this
names the ServiceInstance the initial payment creates -- the VPS or
container the customer actually refers to.
plan_idproduct_idslugThe URL segment addressing that service, unique within its project. Supplied rather than derived here: the console suggests one from the name as the customer types and lets them edit it.
cadence_monthsThe billing term to buy, in months: 1, 3, 6 or 12 (V-0717).
Omitting it buys the monthly term, which is what every client
written before term choice sends. The plan's offered terms, with each
one's price and saving, are its terms on the product plan listing.
A term the plan is not sold at is refused (400), never sold monthly
instead; the subscription renews at the same term and Price.
discount_codeAn optional discount code, exactly as the customer typed it.
A code that cannot be used is refused, not ignored: a customer who entered one and was charged full price anyway has been overcharged as far as they are concerned.
Public ports to open on the service once it runs. Omitting this (or sending none) buys exactly what every earlier request bought.
The customer names only the container port and the protocol(s); Zaroz
assigns the public address and port. Each port is billed by the hour it
is held, monthly in arrears: it is never part of the invoice this
request creates, and the quote lists each one as a line of amount zero
with the estimate in metered_estimate. A port that cannot be opened
right after payment never fails the purchase: it is listed on the
service as pending with the reason, and opened as soon as it can be.
Refused for a product that offers none, past the plan's included ports
when more are not priced, and above 10 per request.
hardware_profile_idThe hardware tier inside region_id to run on, as
RegionHardwareResponse.id from GET /api/v2/catalog/regions
(decision-0347: a customer chooses between a region's tiers, each with
its own Price). Omit it to let kernel place the service on the
cheapest tier that fits. A tier that is not listed under region_id,
or that the listing marks unavailable, is refused exactly as an
unbuyable region is.
operating_system_idThe operating system to install, for a VPS purchase
(ProductFamily::VirtualMachine). Required for that family, and
refused if sent for any other -- nothing else on /v2 installs an
operating system. GET /api/v2/catalog/products/{id}/operating-systems
lists what can be named here.
organization_idWhich organization is buying, and therefore which one the subscription and its invoice bill to.
Optional, and omitting it means "my personal organization" -- the only
thing /v2 checkout could bill before shared organizations became
purchasable. Existing clients that send no organization_id keep the
exact behaviour they had.
Sending one requires the caller to be entitled to spend that organization's money: an Owner or Admin membership, or its personal owner. A Member or Billing role is refused (403), never silently redirected to the caller's own organization. An organization the caller has no relationship to answers 404, the same as an unknown id, so ids cannot be enumerated by their refusal.
project_idWhich project the purchased service belongs to (§34.1's
Organization -> Project -> Subscription -> Resource).
Optional, and omitting it means the buying organization's default
project -- created on first use if it does not exist yet, the same
resolution /v1 order creation has always applied for an organization
with no project concept of its own. This is what makes checkout
reachable without first showing the caller an organization: §11's
invisibility on organization_id is worthless if project_id still
forces one into view.
When supplied, it must name a project the buying organization owns; one belonging to another organization is refused rather than ignored, because a subscription filed under someone else's project misattributes that spend in every read that joins through it.
region_idWhere the service should run. Must be one of the regions
GET /api/v2/console/catalog/regions returns for this
product_id/plan_id: that read applies the same access and capacity
rules checkout does, so anything it lists is buyable and anything it
omits would be refused here.
Required for every purchasable product except a licence
(ProductFamily::License), which is placed nowhere at all and is
refused if this is sent. Omit it entirely for a licence purchase.
The size to buy, when the customer sized it themselves.
Omitting this buys the plan exactly as authored, which is what
every existing client does and what every existing request means. This
is an override, not a replacement: plan_id is still required and
still decides which hardware profile runs the workload and which Price
rates it, because those are placement and money rather than size.
A plan is one convenient point inside the range
products.minimum_*/maximum_* describes, and a customer sizing their
own instance is choosing a different point in the same range. Anything
outside it is refused by Product::admits rather than clamped to fit:
silently resizing somebody's order and then charging them for the
result is the worse of the two answers.
This is also what makes persistent storage opt-in. A product whose
minimum_storage_gb is zero admits a shape with no disk, that shape
prices at zero against the storage rate, and the provisioner builds no
volume for it.
CheckoutResourcesRequest
cpumemory_gbMemory in GiB, fractional (0.5 = 512 MiB)
storage_gbStorage in GiB. Zero buys no volume at all, where the product allows it.
CheckoutResponse
available_centsThe establishing invoice, in the same shape GET /billing/invoices/{id}
already returns (InvoiceResponse) -- a client that just checked out
pays this invoice through the existing invoice-id-keyed payment
endpoints (POST /api/v1/invoices/{id}/checkout/mollie or
.../paypal, both of which already resolve by InvoiceId alone).
required_centsZC-1324 org trust S5 (§8.4). See [QuoteResponse::required_cents]'s
own doc comment -- identical meaning, read AFTER this checkout's own
effects (its reservation, if it wrote one) rather than before.
V-0449.04: postpaid disclosure, present only for the OWNER of an
organization with a credit limit. See crate::contracts::standing::PostpaidDisclosureResponse.
CheckoutSubscriptionResponse
idorganization_idstatusClaimTrialRequest
nameThe customer's name for the service they will receive.
slugThe URL segment addressing it, unique within its project. Same rules as checkout's: 3-63 characters of lowercase letters, numbers and single hyphens.
trial_price_idThe id from GET /api/v2/me/trials.
project_idWhich project to file it under. Omit for the personal organization's
default project, created on first use. Must be omitted on
POST /api/v2/me/trials/gaming, which always files into the games
project.
region_idWhere to run it.
Ignored when the trial reports region_is_fixed, and omitting it
otherwise means "anywhere that fits, cheapest first" -- resolved
server-side, never by the client.
ClaimTrialResponse
The zero-amount establishing invoice, in the same shape
GET /billing/invoices/{id} returns. Already paid; it is returned so
the customer's invoice list and this response cannot describe the same
row differently.
ClaimableTrialResponse
claimableduration_hoursHow long the free period lasts, in hours, as declared.
idThe trial Price's id (decision-0353: a trial is a Price), to send
back as trial_price_id to POST /api/v2/me/trials.
plan_idThe plan this trial grants.
product_idproduct_nameThe product's display name, resolved server-side so a list needs no second request per row.
region_is_fixedWhether this trial pins its own hardware or region. When true, any
region_id sent to the claim is ignored, so a client must not offer a
region picker for this row.
Why not, when claimable is false. A stable machine value plus a
sentence; clients switch on code and never on message.
region_idThe region the trial runs in when it fixes one.
ClaimableTrialsResponse
ClaimedTrialSubscriptionResponse
auto_renewAlways false on a fresh claim, and stated on the wire rather than
assumed: this is the field that makes the trial free, and turning it
on through PUT /api/v2/subscriptions/{id}/renewal is the whole of what
converting a trial means. A client that hides it leaves the customer no
way to keep their service.
idorganization_idproject_idstatusactive for a claim that provisioned, pending for the narrow window
where the zero invoice settled but the row had not been re-read. Carried
as the real status rather than a one-variant enum like
CheckoutSubscriptionStatusResponse, because a claim -- unlike a
checkout -- activates inside the same request.
trial_ends_atWhen the free period stops. After this the subscription either starts billing (if the customer turned renewal on) or is suspended.
ColumnDefinitionRequest
namenullableprimary_keyCommandConsoleSessionTicketResponse
expires_atWhen the gateway stops accepting this ticket.
This is a redemption deadline, not a session deadline. cluster-agent
checks exp once, when the socket is upgraded
(gateway/edge_token.rs:41, called from gateway/terminal.rs:35); an
attached session then runs until one side disconnects. So a client
redeems the ticket immediately and never re-mints to stay connected: it
mints again only to attach again.
urlThe gateway URL to open a WebSocket against, carrying the signed ticket in its query string.
Binary frames both ways, and no subprotocol: cluster-agent's /terminal
upgrade negotiates none (cluster-agent/src/gateway/mod.rs:88), unlike
its /vnc and /ssh upgrades. Anything that is not a binary frame is
dropped by the gateway rather than refused (gateway/terminal.rs:107),
so there is no control channel to speak into.
CompleteOAuthLoginRequest
keyConditionFallbackResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
ConfigureHttpDomainRequest
domainContainerStatusResponse
namereadyrestart_countstatelast_exit_codelast_terminated_atlast_terminated_reasonmessageDetail for the container's current state: the waiting reason's
message while waiting, the terminated message while terminated,
absent while running.
ControlledUnitResponse
createdtrue only when this call made the unit.
The unit, with its user_data.
CrashLoopInfoResponse
restart_countlast_exit_code1 is an application error, 137 a SIGKILL and usually the OOM killer, 143 an ordinary SIGTERM.
last_terminated_atlast_terminated_reasonmessagenext_retry_atBest-effort estimate of the next restart attempt. Kubernetes does not publish the kubelet's schedule, so this is reconstructed from the last termination plus the standard backoff.
CreateBackupRequest
nameOptional label. Kernel fills in a timestamped default
("Backup 2026-09-10 14:35") when this is absent, null, or blank.
CreateBucketKeyRequest
scoperead_only or read_write.
nameDisplay name. Blank or absent becomes "Key".
CreateBucketRequest
cap_bytesStorage cap in bytes, 1 GiB to 100 TiB. Absent takes 100 GiB. Above the cap the keys turn read-only until usage falls or the cap is raised.
labelDisplay name. Blank or absent becomes "Bucket".
region_idWhere the bucket lives. Defaults to the region of the subscription's price; when the price names a region this must match it.
CreateCredentialRequest
name1 to 64 characters, so the credential can be told apart when revoking it.
expires_in_days1 to 365; 90 when omitted.
CreateDirectoryRequest
pathCreateFirewallRuleRequest
actiondirectionpriorityLower runs first. Ties are broken by the datapath, not here, so two rules sharing a priority have no defined order between them.
protocoldescriptioncidrThe source range this rule matches, IPv4 only and no broader than /8.
Absent, null, or empty all mean "any source".
enabledDefaults to true: a rule created disabled is almost always a mistake
in the client rather than an intention, and /v1 defaults the same way.
port_fromRequired for tcp and udp, refused for icmp and any. The domain
enforces that (FirewallRule::create), so an omitted port on a TCP rule
is a validation refusal rather than a rule that matches every port.
port_toCreateMyApiTokenRequest
The grants the token holds. Every capability must be one the caller
may grant themselves (GET /me/api-token-capabilities).
name1-64 characters after trimming.
admin_authorizedMust be true exactly when the authorization contains an admin-only capability, and then requires an elevated session.
expires_atOmit for a token that never expires on its own. Must be in the future.
CreateMyApplicationDelegationRequest
application_idNon-empty: a consent event that grants nothing is refused.
CreateMyReferralLinkRequest
slug1-64 characters of letters, numbers, hyphens, or underscores.
Lowercased and trimmed before it is checked for uniqueness -- see
kernel_organizations::referral_link_service::normalize_slug.
CreateMyWalletTopUpRequest
amount_centsInteger euro cents, and one of the fixed presets: 2500, 5000, 10000,
25000 or 100000. Any other amount is refused with
invalid-field-value; top-ups are always EUR.
providerA provider a top-up can be started with. Mollie is deliberately absent: a Mollie top-up has no checkout and no settlement path in the kernel.
CreateOrganizationApiTokenRequest
nameWhat the token may do, scoped to this organization. An empty list mints a token that authorizes nothing: for an organization credential, absence denies rather than permits.
expires_atOmit for a token that never expires on its own. Must be in the future.
Omitting this yields membership_tied, the safer shape: the token is revoked when the creator's membership of this organization ends. Pass organization_owned only when the credential is meant to outlive whoever set it up.
CreateOrganizationInvitationRequest
emailroleDistinct from OrganizationRoleResponse because request and response
enums are separate types on /v2 (design doc §43.4), even where they
currently carry the same variants.
CreateOrganizationRequest
nameslugURL-safe identifier, unique platform-wide (lowercase ascii letters, digits, and single internal hyphens).
CreateProjectRequest
nameslugURL-safe identifier, unique within the owning organization (lowercase ascii letters, digits, and single internal hyphens).
descriptionCreateRegistryCredentialRequest
scopepull, push (pull and push) or admin (pull, push and delete).
nameDisplay name. Blank or absent becomes "Credential".
CreateRegistryRequest
cap_bytesSpend cap in bytes of stored images, 1 GiB to 100 TiB. Absent takes 100 GiB. Above it pushes are refused until usage falls or the cap is raised; pulls and deletes keep working.
labelDisplay name. Blank or absent becomes "Registry".
region_idWhere the registry lives. Defaults to the region of the subscription's price; when the price names a region this must match it.
CreateScheduleRequest
What each fire does (V-0702). Required: run_job for a cron-job
service, tasks for any other.
cron_expressionFive space-separated fields. Syntax only is checked here and in the domain; computing the next fire time is the scheduler's job, out of scope for this slice.
nameThe three concurrency policies a schedule may declare. Mirrors
[OverlapPolicy] one for one; see this module's header for why it is not
reused directly.
timeout_secondstimezoneAn IANA zone name, e.g. Europe/Helsinki. Checked syntactically only:
this platform does not carry a timezone database yet, and adding one
is a dependency decision for the owner, not this slice.
pausedCreateServiceShareRequest
emailThe person's email address. An address an account has verified is shared with that account at once, any other waits until an account verifies it and opens "Shared with me".
What the person may do, besides seeing the service: any of console, files,
power, settings. Empty is allowed and means "may see it is up".
CreateSessionApplicationDelegationRequest
Non-empty: a delegation that grants nothing is refused.
session_tokenCreateSharedDatabaseTableRequest
nameCreateSubscriptionSharedDatabaseRequest
enginemariadb or postgres; see GET .../shared-databases/engines for
which are available right now.
display_nameThe customer's own label. Blank or absent becomes "Database N".
region_idPlace it in this region. Strict when given: a region with no enabled
host for engine is refused rather than silently placed elsewhere.
Absent places it on the least-loaded host for engine.
CreateTicketRequest
bodysubjectCreateTicketResponse
One message in TicketDetailResponse::messages.
Soft-deleted messages never appear here at all -- this endpoint reads
SupportMessageRepository::find_by_ticket_id_visible, which already
excludes them, rather than /v1's find_by_ticket_id (every message,
with the body blanked for a deleted one at render time). A /v2 read
surface has no reason to reconstruct a "[deleted]" placeholder in the
thread; see this crate's report.
A staff author's identity is never exposed: author_is_staff is true
and author_name reads "Support Team". A non-staff message's author_name is that
message's own author's display name, resolved per message by the caller of
from_message -- not necessarily the caller of the request. A ticket's whole thread is
now visible to every member of its organization (design doc §44.2), so a non-staff
message may have been authored by the ticket's owner, another organization member, or
the current caller; there is no single name that is correct for all of them.
One ticket visible to the caller, in the detail view (paired with its messages in
TicketDetailResponse) -- any ticket belonging to any organization the caller may see
(design doc §44.2), not only ones the caller personally opened. Same no-staff-identity
rule as TicketSummaryResponse.
CreateUnitRequest
key1 to 40 lowercase letters, digits or hyphens, starting and ending with a letter
or digit. Never changes. u followed by digits, keys starting w- or zaroz,
and the words the units routes use (allocate, events, policy, ...) are
reserved.
At most 16 pairs; replaced whole. Absent means none for a new unit.
What the unit does when its process exits. Defaults to the policy's
default_on_exit.
startfalse creates the unit stopped: it holds no slot and costs nothing until it
starts. Defaults to true.
user_dataAny JSON value up to 64 KiB, at most 32 levels deep. Not a secret store.
CreateUnitWebhookRequest
urlhttps:// and a public host; at most 2048 characters, no user name or
password.
event_typesEvent types to deliver (for example unit.ready); empty or absent for
every type.
CreatedApplicationDelegationResponse
iduser_idCreatedCredentialResponse
An external credential, without its secret.
tokenzaroz_sp_.... Shown once: it is stored only as a digest and cannot be
read back. Send it as Authorization: Bearer <token>.
CreatedMyApiTokenResponse
secretThe full credential, shown exactly once. Only a digest of its secret half is stored.
One of the caller's own personal API tokens (ZC-0512).
Never carries the secret, or even its digest. Only a digest of the
secret half is stored on token_hash, and this response omits that field
entirely: the full credential is returned exactly once, at creation
(POST /me/api-tokens), and no later read -- this one included -- can
reproduce it.
Unlike [crate::contracts::organization_api_tokens::OrganizationApiTokenResponse],
capabilities here is not filtered to resource-scoped grants: a personal
token may hold a global or resource-type-scoped grant as well as a
resource-scoped one, so every capability the token's authorization names
is reported, regardless of scope shape. A token created before restricted
authorization existed carries no authorization at all (a legacy
unrestricted token); it reports an empty list rather than "every
capability there is", since there is no finite list of everything an
unrestricted token can do to render here.
CreatedOrganizationApiTokenResponse
secretThe full credential, shown exactly once. Only a digest of its secret half is stored, so no later request can return this value again.
One organization API token. Never carries the secret. The secret exists
in exactly one response, [CreatedOrganizationApiTokenResponse], and only
its digest is stored, so nothing can put it back here later.
CredentialResponse
created_atexpires_atidnamecreated_byThe person who made the credential. null once that account is deleted.
created_by_nameTheir display name, null when created_by is or the account cannot be read.
last_used_atCurrentSessionResponse
Minimal caller identity carried on a session payload.
Deliberately not the full /console/me shape
(kernel_http_v2_identity::contracts::me::MeResponse): /v2 feature
crates do not depend on one another (see crates/http/CLAUDE.md), so
this is a small, independent projection sized for what a session
response needs, not a shared type.
CursorExpiredResponse
descriptioncodeoldest_retained_seqThe oldest seq still kept.
resume_afterSend this as after to read from the oldest kept event. Events before it
were swept: re-read the unit list to resynchronise.
CustomDomainAvailabilityResponse
statusavailable, taken, invalid, platform_zone or not_verified.
A string on the wire, like status above, so a new state does not
break a generated client.
CustomDomainResponse
hostnameNormalized: lowercase, no trailing dot.
idThe id DELETE /service-instances/{id}/custom-domains/{route_id}
names. It is the ingress resource's own id, so detaching addresses the
exact row that was created rather than the hostname string, which a
customer could otherwise re-send in a different case or with a
trailing dot and miss.
statuspending, active or failed.
pending is not a synonym for broken. It is the ordinary state
between accepting the name and cert-manager completing an HTTP-01
challenge, and that challenge cannot complete until the customer's own
DNS points here -- so a client should render it as "waiting on your
DNS", never as an error.
urlhttps://{hostname}, assembled here so every client renders the same
link rather than each concatenating its own.
CustomDomainsResponse
limitHow many hostnames this service may hold at once, so a panel can disable its own add control instead of discovering the ceiling at a refusal.
platform_hostThe free platform hostname this service always answers on, or null
when it publishes no HTTP ingress at all.
Also null when the instance's cluster could not be resolved, which
is a different cause with the same rendering on purpose: the listing
of attached domains is correct either way, and failing the whole read
because a placement lookup faulted would blind a customer to the names
they have already attached.
platform_urlhttps://{platform_host}, present exactly when platform_host is.
The shared wildcard certificate covers every platform host, so
unlike a CustomDomainResponse.url this one is never waiting on a
certificate to issue -- a client can render it as a ready link (copy
and open-in-new-tab) the moment platform_host is non-null.
DatabaseNameDto
nameDatabaseNameParamsDto
engine[DatabaseEngine] on the wire.
max_lengthdefaultDatabaseSqlResultResponse
databaseDatabaseTableResponse
databaseDatabaseTableRowsResponse
databaseDatabaseTablesResponse
databaseThe database's own name on its server, which is the root a browser draws the tree under.
truncatedDatabaseUsageResponse
How full a database is.
databaseDatabaseUsageView
data_lengthindex_lengthused_bytesData plus index bytes, as the engine reports them. Cached for up to a minute and refreshed by any write through this API.
over_quota_sinceSet while the quota enforcement task has the database locked read-only for being over its quota.
quota_bytesThe storage quota in bytes, or null for a database that has none (a dedicated database is sized by its own volume).
DatabaseWriteResultResponse
databaseDedicatedIpNetworkProtectionModeResponse
assignment_idnetwork_protection_modeDeploymentActor
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, user_id | |
| type = object · requires: kind | |
| type = object · requires: kind |
kinduser_idDeploymentCapabilitiesResponse
container_registryCustomer container registries. Registry products are not listed when false.
domain_connectDomain Connect one-click DNS setup.
mailTransactional email. Without it no mail is ever sent (verification, password reset and notifications included).
mollieMollie card checkout for invoices.
nowpaymentsNOWPayments crypto checkout.
object_storage_bucketsCustomer object-storage buckets. Bucket products are not listed when false.
paypalPayPal checkout (wallet top-ups and invoice payment).
unit_log_storeStored unit log history. Live tail is unaffected.
unit_metrics_storeStored unit metrics history.
wardenThe Warden edge protection listener.
web_pushWeb Push notifications.
DeploymentFailureReason
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
DeploymentOutcome
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
DeploymentResponse
Who started it, masked. A customer is named by their user id; an operator and the platform are deliberately anonymous.
idnumberThe number a customer cites in a support ticket.
Unique within this service and never reused, because the lease rows
it comes from are never deleted. Not contiguous: it is drawn from
the same per-instance sequence every operation on the service uses, so
a service's deployments are #3, #7, #12. A panel renders it as an
identifier, never as a count.
started_atHow the operation ended. Not whether it worked: see this module's header.
Why it ran. A closed union with two arms: manual, somebody pressed
Deploy, and config_change, a setting was written and the workload was
re-rendered because of it. The three the fixture also carries (push,
tag_moved, rollback) each need a subsystem kernel does not have,
and are absent rather than declared and unreachable.
config_change carries a summary: kernel's own sentence about
what changed, for a client to print verbatim (R2). Do not parse it
and do not compose your own -- only kernel knows which key was
written -- and note that its wording is prose rather than a
compatibility surface.
duration_secondsWhole seconds, null whenever finishedAt is. Computed by kernel
(R2) from the two fields beside it, so it can never disagree with
them.
Why the rollout failed, when outcome is failed. Kernel's own
closed vocabulary -- never the raw cluster or template message, which
is logged rather than returned (ZC-1084).
null here is not the same statement null on outcome is. It is
null for every deployment that is not a recorded failure, for a
ConfigChange-kind deployment (not yet classified), and for a lease
released before this field existed. None of those is the unknown
word, which is a positive statement that kernel tried to classify and
could not. See
DeploymentFailureReason's
own doc for the full vocabulary and why each word is there.
finished_atnull while it is still running, and also for one that was abandoned:
the row records when the lease would have lapsed, not when the holder
stopped, and reporting the expiry would invent a duration.
image_digestThe immutable digest that was pulled, when the reference pinned one.
Almost always null, and that is honest rather than missing.
Nothing in kernel resolves a tag to a digest against a third-party
registry: both manifest clients authenticate HTTP basic only, while
ghcr.io, Docker Hub and Quay all require a Bearer-token exchange. It
is non-null only where the customer pinned a digest themselves. A
client must not derive one from imageReference.
image_referenceThe image this deployment shipped, as ${service.image} resolved when
the deployment started.
A fact about the past, not about now. It is captured when the
deployment begins, because that is the only moment it exists: the value
lives on the instance's configuration and the customer overwrites it on
their next tag change. A client comparing this with the Source
capability's current reference is comparing "what is running" with
"what is saved", which is the question 00-program.md §8 is about.
null for a deployment from before the provenance migration and for a
product whose image the customer does not choose. It is not
reconstructable, so null here means the answer is gone rather than
that it is available from another route.
Whether the rollout applied: succeeded, failed, or null.
null is "not recorded", never a failure. It is every deployment
from before the provenance migration, every one still running, and
every holder that died or was forced open before it could say. Nothing
is backfilled and nothing can be, so a panel renders null as an
absence rather than as a red badge.
Separate from status on purpose: a failed deployment is ended and
failed at once, because the handler releases its lease on its error
path too.
DeploymentStatus
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
DeploymentTrigger
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind | |
| type = object · requires: kind, summary |
kindDesiredUnitsPointResponse
atThe bucket's start.
unitsnull when the service's history does not say.
DirectoryListingResponse
Unordered. Sorting is the panel's, per FilesTransport.
pathThe normalized path that was listed, not the one that was typed, so
a breadcrumb reflects what kernel actually read. A customer pasting an
SFTP-shaped path (/server/config) gets back the mount-relative one
(/config).
truncatedTrue when the directory holds more entries than one response carries.
A flag rather than a cursor: there is no stable ordering to page over
(the sidecar returns whatever read_dir yields), so a cursor would
promise a consistency the backend cannot keep.
DiscoverDomainConnectRequest
domainThe customer's registrable domain, e.g. example.com.
hostThe subdomain label (e.g. play), or empty to point the apex at the
server.
DnsInstructionResponse
nameThe domain the record is created on.
record_typeCNAME for a subdomain; ALIAS for a bare domain (example.com), which cannot hold a
CNAME: use the provider's ALIAS, ANAME or CNAME-flattening record to the same target.
targetWhat the record points at: the endpoint's free host.
DomainConnectLinkResponse
created_atdomainThe customer's registrable domain, e.g. example.com.
hostThe subdomain label, or empty for the apex.
hostnameWhat players connect to: {host}.{domain}, or {domain} for the apex.
idstatuspending, active or failed. pending is the ordinary state until
the customer approves the change at their DNS provider and the records
propagate; render it as waiting, not as an error.
apply_urlThe browser URL that applies the template at the customer's DNS
provider, or null when Domain Connect is not configured on this
platform.
dns_provider_display_nameThe detected DNS provider's display name, when it publishes one.
last_errorlast_verified_attemplate_confirmedWhether the DNS provider recognizes our template: true, false, or
null when the provider did not answer consistently.
DomainConnectResponse
supportedWhether this service's product offers Domain Connect. A client hides the
section when false.
DomainVerificationResponse
domainrecord_namerecord_typeAlways TXT. Present so a client never has to hardcode the record
type it renders next to record_name/record_value.
record_valuestatuspending, verified, lost, or failed.
first_verified_atThe first time this row was ever proven, set once and never moved
again even through a later Lost/Verified cycle. What a "Verified on
1 March" message (design doc state 4/5) reads from; distinct from
verified_at, which keeps advancing on every successful recheck.
grandfathered_untilA dated exemption for one of the handful of production domains that
were serving before this feature existed (design doc, "The four live
production domains"). Some only for those rows, and only until the
date itself: after it, an unproven domain in this state stops being
served. Absent for every row created through the ordinary start flow.
last_checked_atlast_errorKernel's own sentence for the most recent refusal, verbatim, per the design doc's "what kernel returns" (kernel writes the sentence, console renders it as-is).
lost_sinceWhen a Verified row's proof was most recently found gone or
replaced. Some only while status is lost. Combined with the
domain's fourteen-day grace period, this is what lets a client compute
the exact date state 6 names ("will stop being served on
lost_since + 14 days").
verified_atDownloadFormatParam
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
DownloadUrlRequest
pathDownloadUrlResponse
base_urlexpires_attokenEditTicketMessageRequest
bodyEffectiveRoutingResponse
hostpath_limitThe most path routes one domain may carry.
In the order they are evaluated; the last is always the default.
Every service that answers some part of the domain, with the paths it serves.
Present when the request carried ?path=.
ElevationMethod
Which admin-elevation module a credential belongs to, or a verification
attempt is checked against. AdminElevationModule gives each method
(PIN, WebAuthn, TOTP) a home behind this same enum without touching every
caller that only cares about routing by name. Serializable so callers of
/auth/sudo/* can pick a method by name instead of the HTTP layer
assuming PIN.
EndpointDomainResponse
domainidThe id to DELETE .../endpoints/{endpoint_id}/domains/{id}.
Verification state of what is served on it: the domain itself was verified for the organization before it could be attached (a domain that loses verification stops being served and disappears from here); this is the route and certificate.
urlhttps:// plus domain.
The DNS record the customer creates so the domain reaches this endpoint. Present on reads of an endpoint once its free host is known; absent on the response to attaching a domain (read the endpoint again).
Why the domain is failed: a stable code and a sentence. Present only while status is
failed. certificate_failed (usually DNS not pointing at the platform yet) or
route_failed.
EndpointKind
What an endpoint is (decision-0308). A Container offers two, and a customer chooses by what they run: a website or API, or anything else.
port: a raw TCP/UDP public port through Warden. Priced, metered, backed by a port allocation.https: one container port behind Traefik, on a free platform host plus the customer's verified domains, with automatic TLS. Free, never metered, holds no allocation. Carries TCP only (WebSockets included); TLS ends at Traefik.unit: a raw port likeport, but one per unit slot, reaching exactly that unit's pod (Units phase 1, S13). One allocation per slot, held while the slot exists, so the address survives pod restarts and is released on scale-down. Priced and metered per port exactly asportis.
EndpointOriginResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
EndpointProtocols
The protocols one endpoint carries. TcpUdp is one endpoint, one price,
over one allocation carrying both labels ([PortProtocol::Both]).
EndpointRequestBody
internal_portThe port the service listens on inside the container, 1 to 65535.
domainshttps only: the customer's own domains to serve on this endpoint once the service
runs. Each must be one the organization has verified or a subdomain of one, exactly as
POST .../endpoints requires; refused here with invalid_domain, platform_domain
or domain_not_verified. At most 10 across the whole purchase (domain_limit).
kindport (the default, so a request written before kinds existed means what it
always did) is a raw TCP/UDP public port: a shared address and an assigned public
port, billed by the hour held. https is a website or API behind Traefik: a free
platform host, the customer's own verified domains (added once the service runs),
and automatic TLS, free and never metered; the app serves plain HTTP.
labelhttps only: the label of the free host (<label>.zone.<zone>.zaroz.cloud), one DNS
label; refused with invalid_host_label otherwise. Omitted, the host is named after
the endpoint's id. Same rule as POST .../endpoints.
For port: tcp, udp, or tcp_udp for one public number on both; required.
For https: omit it (it is always TCP); tcp is accepted.
EndpointResponse
created_atWhen the port was opened, or, while pending, when it was asked for.
idThe id to DELETE. For a pending request this is the request's id.
internal_portThe port the service listens on inside the container.
kindport (raw TCP/UDP, billed), unit (a raw port that reaches one unit, billed like a
port) or https (a host and domains, free).
protocolThe protocols one endpoint carries. TcpUdp is one endpoint, one price,
over one allocation carrying both labels ([PortProtocol::Both]).
The host and domains of an https endpoint. Absent for a port, which has the
public_* fields instead.
last_public_ipThe public address the port had, once it is closed, so a month's bill can be read against it. Absent while the port is open, while it is pending, and for a port closed before the address was kept.
last_public_portThe public port the closed port had. Present exactly when last_public_ip is.
Why the port is not open yet. Present only while state is pending.
public_ipThe public address, while the port is open.
public_portThe public port Zaroz assigned, while the port is open.
released_atWhen the port was closed.
unit_ordinalThe unit slot a unit endpoint reaches. Absent for the other kinds.
EndpointStateResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
EnvironmentApplies
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
EnvironmentResponse
secrets_allowedWhether this product's customers may store secrets at all. A panel that inferred this from a product slug would be computing a verdict.
Ordered by key, so two reads of an unchanged service agree.
Whether the running container is still on older values, and which act
would pick them up. null when nothing is outstanding.
On the envelope rather than left to the client's local state, because a page reload must not make the banner disappear while the container is still running the old values.
EnvironmentVariableResponse
When changing this reaches the running container. Kernel's verdict.
idStable for as long as the key is.
Derived from the key rather than stored, so renaming a variable changes its id. Good enough to key a table row and an open dialog on; not durable, and nothing should persist it.
keysecretWhether the running container is still on an older value after the
request that produced this row, and which act would pick the new one
up. null means nothing is outstanding.
Only a write answers this. In a list read every row carries null and
[EnvironmentResponse::pending] on the envelope is the verdict for
the set, because staleness is compared against the whole rendered
workload rather than row by row. A write has no envelope to put it on
and does know the answer for its own change: saving succeeded but the
re-render did not, which is the case a panel must not report as done.
valuenull when secret is true, always.
Not "[redacted]": that is a string a customer can also type, so a
client could not tell a masked value from a real one, and null is
the only unambiguous answer.
ExecPtySessionTicketResponse
containerThe container the shell will open in.
expires_atWhen the gateway stops accepting this ticket. A redemption deadline: the ticket is single use and the open session is bounded by the gateway's own idle and maximum-length timeouts, not by this.
shellsThe shells the gateway tries, in order, until one starts.
urlThe gateway URL to open a WebSocket against, carrying the signed ticket
in its query string. Negotiate the zaroz-pty-v1 subprotocol and append
columns and rows.
ExternalAccessLiveResponse
degradedExternalAccessResponse
extra_slotsExtra slots staff granted this service instance on top of
free_slots (0 without a grant). free_slots + extra_slots is the
ceiling a new port request on a shared pool is refused at.
free_slotshttp_ingress_ipsis_dedicated_ipTrue when this instance's ports are served from an exclusive (dedicated) IP, where the requested port becomes the public port. On a shared pool the external port is drawn at random and cannot be chosen.
usedFileContentResponse
contentUTF-8 text. A file that is not valid UTF-8 is refused rather than
lossily converted, because the transport's write takes a string and a
lossy read followed by a save would rewrite the customer's binary as
replacement characters.
pathsize_bytesBytes of content, which is what was actually read rather than what the
directory entry claimed a moment earlier.
FileEntryResponse
kindWhat an entry is. Two values, closed: a filesystem entry the browser can
draw is a file or a directory, and the sidecar refuses to describe anything
else (entry_for_path answers invalid_argument for a socket or a device).
namepathAbsolute within the mount, always starting with /. This is the value
to hand back to any other route on this capability: it is the sidecar's
own answer about where the entry lives rather than a path the client
rebuilt from name, so following it addresses the file kernel listed.
modified_atnull when the backend reported none. Rendered, never parsed for
meaning.
size_bytesnull for a directory. The sidecar reports zero for one, and a rendered
zero reads as "this folder is empty", which is a claim kernel never
made.
FileKindResponse
What an entry is. Two values, closed: a filesystem entry the browser can
draw is a file or a directory, and the sidecar refuses to describe anything
else (entry_for_path answers invalid_argument for a socket or a device).
FilesSessionTicketResponse
base_urlexpires_attokenFirewallRuleResponse
actioncreated_atdirectionenabledidpriorityprotocolresource_idThe machine this rule filters traffic to. /v1 calls this
provision_id; see this module's header.
updated_atdescriptioncidrRendered back as it is stored, canonicalised by ipnetwork, so a
caller who wrote 10.0.0.5/8 reads 10.0.0.0/8 and can see what the
rule will actually match.
port_fromport_toFirewallRulesResponse
max_rules_per_directionHow many rules one direction may hold. Kernel's own constant, published rather than duplicated as a frontend literal.
FivemArtifactChannelDto
Mirrors [FiveMArtifactChannel] by hand, on this module's own discipline
(the domain type carries no JsonSchema).
FivemLiveResponse
Empty unless status is ok.
Present only when status is ok.
FivemLiveStatus
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
FivemPlayerResponse
idnamepingMilliseconds; 0 means the server did not report one.
FivemServerDto
artifact_channelMirrors [FiveMArtifactChannel] by hand, on this module's own discipline
(the domain type carries no JsonSchema).
default_chat_enabledcustom_artifact_versionExact {build}-{40 hex} id; required for custom, dropped otherwise.
FivemServerInfoResponse
clientsPlayers connected now.
gametypehostnamemapnamemax_clientsThe server's slot count, when it publishes one.
FivemServerParamsDto
artifact_channelWhether this product offers a channel / custom build choice. false
for FiveM Enhanced, whose build is pinned in the image.
ForgotPasswordRequest
emailoriginThe origin the emailed reset link should point back at (ZC-1425).
Same shape and validation as [PasswordSignupRequest::origin], including the
optional app mount path (https://zaroz.cloud/gaming).
Unlike the address above, a disallowed origin here is NOT hidden
behind the identical-response refusal: it is not account-existence
information, so forgot_handler refuses it with a real 4xx.
FramebufferHoldRequest
session_idThe session_id the ticket response minted. A session that no longer
holds the screen gets held: false rather than an error.
FramebufferHoldResponse
heldexpires_atWhen this hold lapses unless refreshed again. Absent when the hold was lost, because there is nothing left to refresh.
holder_nameWho holds it instead, when the hold was lost. Absent when it was kept, and absent when nothing holds it at all.
FramebufferReleaseResponse
releasedFalse when the session named no longer held the screen, which is the ordinary outcome of unmounting after being taken over. Not an error: a page being torn down is not a place to report one.
FramebufferSessionConflictResponse
descriptioncodeMatches the shape of the shared error envelope so a generic client error handler still reads it.
holder_nameRendered as given. zaroz-ui puts this straight on screen and does not
word a sentence around it.
holder_user_idupdated_atWhen the holder last refreshed. A client can use it to say how stale the hold is before offering to take over.
FramebufferSessionTicketResponse
expires_atWhen the gateway stops accepting this ticket.
A redemption deadline and not a session deadline: cluster-agent verifies
exp once at upgrade (gateway/vnc.rs:12) and never again, so an
attached screen outlives its ticket.
hold_expires_atWhen the exclusive hold lapses unless refreshed.
protocolsSubprotocols the socket must request. See [FRAMEBUFFER_SUBPROTOCOL].
session_idThe handle for this exclusive session.
Minted here rather than supplied by the client, unlike /v1's
sessionId query parameter. The client cannot then name somebody else's
session, and taking a screen over is spelled force rather than
spelled "guess the holder's identifier and refresh it".
Pass it to the hold and release routes. It is not a credential: holding this screen still requires passing the same authorization the mint did.
urlThe gateway URL to open a WebSocket against, carrying the signed ticket in its query string.
GameServerDto
descriptioncrossplaydisable_anti_cheatexpansionfps_limitmapmax_playersmodepublicseedserver_nameupdate_mods_on_startupdate_on_restartworld_nameworld_sizeGameServerParamsDto
GameSubdomainAvailabilityResponse
statusSet when status is invalid.
GameSubdomainRequest
parent_domain_idsubdomain3-32 characters: a-z, 0-9 and inner hyphens. Normalized to lowercase.
GameSubdomainResponse
created_athas_srv_recordWhether an SRV record carries the port, so players can connect with the hostname
alone. false means they must add :record_port.
hostname<subdomain>.<parent_domain_name>, what players connect to.
idChanges on a rename: a rename replaces the subdomain.
parent_domain_idparent_domain_nameWhere a game subdomain's DNS records are.
subdomainlast_synced_atrecord_ipThe address the records point at, once they were pushed.
record_portThe port players need when there is no SRV record carrying it.
GameSubdomainStatusResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
GameSubdomainZoneResponse
idnameGameSubdomainsResponse
limitHow many subdomains one service may hold (1), so a client can hide its add control.
The zones a new subdomain may be taken under. Empty when none is enabled.
GrantCapabilityDto
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
GrantDto
What a grant lets the principal do to its target service. Mirrors the domain's closed vocabulary; deliberately not an API token capability.
target_service_instance_idGrantableOrganizationApiTokenCapabilityResponse
Closed, policy-owned action catalog. Capabilities are exact: there is
deliberately no prefix or glob matching, and unknown wire values are
rejected during deserialization.
PartialOrd/Ord exist so a capability set can be a BTreeSet, which is
what [crate::domain::auth::application_token::ApplicationToken] stores.
The ordering is the declaration order and is not a wire contract: nothing
serializes it, and as_str remains the only stable representation.
GrantableServiceResponse
nameThe service's name, as the project lists it.
service_instance_idGuestReadinessResponse
kindreadystatusThe ticket's own state machine, as a string. Diagnostic rather than
something to branch on: ready is the decision.
completed_atHostStatusResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
HttpsDetailsResponse
The customer's own domains on this endpoint, each with its certificate state.
How far a host or a domain is.
hostThe free platform host, <label>.zone.<zone>.zaroz.cloud, covered by the platform's
wildcard certificate. Absent once the endpoint is released.
urlhttps:// plus host.
IdleAction
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
IfNone
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
ImportSharedDatabaseTransferRequest
source_operation_idInFlightOperationResponse
kindThe operation's stable snake_case spelling (deploy, restart,
reprovision, ...its ServiceOperationKind::to_string()). Plain text
rather than a dedicated wire enum, matching v2-admin's
ServiceOperationLockResponse::operation for the same lease, so an
operator comparing the two never reads two different vocabularies for
one fact. observe never appears here: it takes no lease.
started_atWhen kernel acquired the lease. Not an estimate of when it will finish -- nothing here knows how long an operation of this kind usually takes -- but enough for a consumer to render an elapsed timer ("deploying, 40s") instead of a bare "deploying".
InvoiceCardCheckoutResponse
checkout_urlThe provider-hosted page the customer completes the payment on. Open it in the browser; the invoice is paid when the provider settles, not when this URL is issued.
InvoiceKindResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
InvoiceLineKindResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
InvoiceLineResponse
descriptionamount_centscurrencyidMirrors InvoiceLineItemKind 1:1, as its own /v2 response type so the
wire format cannot drift silently if a variant is ever renamed on the
domain enum without a matching, deliberate wire change here (same
convention as kernel_http_v2_catalog::contracts::products::ProductKindResponse).
service_ends_atservice_starts_attax_amount_centsproject_idThe project this line was billed for, resolved server-side through
the line's subscription (subscriptions.project_id is NOT NULL).
Joined once for the whole invoice rather than left to the client:
a client holding only subscription_id would need a call per line to
recover it, turning one invoice read into N.
null -- together with project_name -- for a line with no
subscription_id, and for the (schema-permitted, expected-impossible)
case of a line whose subscription belongs to another organization,
which the join refuses to resolve rather than naming a project the
caller may not see. Both are absences, not errors: the line still
carries its description, amount, tax and service period.
project_nameThe project's current name, read live at response time rather than
snapshotted onto the line. Renaming a project moves every one of its
invoice lines with it -- this is navigation, not the frozen invoice
content bill_to_* is (Program G §2.2).
Always null exactly when project_id is.
resource_idsubscription_idInvoicePaymentResponse
entry_idInvoiceResponse
amount_centscreated_atcurrencyidis_syntheticstatusAn invoice's status on the /v2 wire.
Deserialize as well as Serialize, because this is also the closed
vocabulary of listOrganizationInvoices's status filter. Deliberately
one type rather than a separate *Filter enum: the filter's accepted
values and the values a row can come back carrying must be the same set,
and a second enum is a second place for them to disagree. A generated
client sees one schema for both.
tax_amount_centstotal_amount_centsbill_to_addressbill_to_countrybill_to_namebill_to_tax_iddue_atWhen an unpaid invoice must be paid by. Identical in meaning and
derivation to InvoiceSummaryResponse::due_at -- see that field,
including its postpaid settlement exception.
failed_atinvoice_numberpaid_atrefunded_attax_labeltax_rateThe tax rate applied at issue, e.g. 0.21 for 21%. None when no
tax rate was resolved for this invoice. Exactly the stored rate
(numeric(6,4)), never a blurred one: a rate the JSON number cannot
carry exactly fails the response instead (V-0699).
InvoiceSeriesResponse
Program G §1: the two invoice series, SIMP (simplified, structurally
carries no personal data) and FULL (identity-bearing). See
InvoiceResponse::bill_to_name and friends for the snapshot this series
gates.
InvoiceStatusResponse
An invoice's status on the /v2 wire.
Deserialize as well as Serialize, because this is also the closed
vocabulary of listOrganizationInvoices's status filter. Deliberately
one type rather than a separate *Filter enum: the filter's accepted
values and the values a row can come back carrying must be the same set,
and a second enum is a second place for them to disagree. A generated
client sees one schema for both.
InvoiceSummaryResponse
amount_centsMoney is integer cents on every /v2 DTO, never a float or a
formatted string -- /v1's InvoiceView renders format!("{:.2}", amount) decimal strings instead, which this deliberately does not
carry forward (see this crate's report).
created_atcurrencyidis_syntheticorganization_idThe organization this invoice belongs to.
Carried even when the caller filtered to a single organization, because
a row that cannot say who it belongs to forces the client to infer it
from the request it happened to send. A client rendering an unfiltered
listing has no other way to group or label rows at all, which is the
gap that made /{org}/billing/invoices show every organization's
invoices under one organization's heading.
statusAn invoice's status on the /v2 wire.
Deserialize as well as Serialize, because this is also the closed
vocabulary of listOrganizationInvoices's status filter. Deliberately
one type rather than a separate *Filter enum: the filter's accepted
values and the values a row can come back carrying must be the same set,
and a second enum is a second place for them to disagree. A generated
client sees one schema for both.
tax_amount_centstotal_amount_centsdue_atWhen an unpaid invoice must be paid by.
Derived, not stored: the invoice's created_at plus the grace period
of the subscription it bills (subscriptions.grace_period_hours).
That is the same deadline the invoice_due email quotes as its
suspension date and the same one the billing task suspends on, so it
is not a new promise -- it is the existing one, said on the wire.
null when the invoice bills no subscription at all (an admin or
synthetic invoice), because nothing about such an invoice says when it
is due and a default would be an invention. An invoice billing several
subscriptions takes the earliest of their deadlines.
A postpaid settlement invoice (kind == "postpaid_settlement") is
the exception: its due_at is the payment-terms date fixed when it was
issued (issued + postpaid_payment_terms_days, V-0484), stored and never
re-derived, so a later change of the terms does not move it. It is also
the instant the debt ladder starts counting the invoice from.
With this present, status == "pending" and due_at in the past
is readable as overdue. status == "pending" alone still is not.
failed_atinvoice_numberProgram G §1: the display-ready number (e.g. FULL-2026-000001).
None for every invoice issued before that programme -- never
backfilled, see Invoice::invoice_number's own doc comment.
paid_atrefunded_attax_labelThe tax's name as printed on the invoice (e.g. VAT); None when none was resolved.
tax_rateThe tax rate applied at issue, e.g. 0.21 for 21%; None when none was resolved.
Same meaning and exactness as InvoiceResponse::tax_rate (V-0699).
IssueSshSessionRequest
columnscorrelation_idrowsIssuedBucketKeyResponse
secret_access_keyIssuedRegistryCredentialResponse
secretThe password to log in with.
JavaRuntimeDto
use_optimization_flagsnull means "derive it from the Minecraft version" -- see
[kernel_core::domain::setup_steps::StepAnswersDocument::template_answers].
jvm_optionsjvm_xx_optionsJavaVersionDto
[JavaMajor], spelled the way minecraft.rs's java_major_export writes
it ("8"|"11"|"16"|"17"|"21"|"25") -- the template-export vocabulary, not
JavaMajor's own undecorated Serialize output ("J21").
LadderStopReasonResponse
own_debt: the service's own organization has an unpaid balance.
restricted: the service is frozen because of a debt elsewhere; the
reader should contact the organization's owner.
LadderStopResponse
reasonown_debt: the service's own organization has an unpaid balance.
restricted: the service is frozen because of a debt elsewhere; the
reader should contact the organization's owner.
sinceWhen the ladder stopped it.
LifecycleVerb
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
LimitLevel
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
LimitUsageResponse
currentWhat the organization uses now.
ok, near (80 percent of the limit or more) or at_limit (growth is refused).
limitWhat staff allow it.
ListAuditResponse
Pagination metadata included in paginated responses
ListCredentialsResponse
ListDeploymentsResponse
Newest first.
Pagination metadata included in paginated responses
The instance's workloads and their current state. Empty for a service that has never been provisioned, which is an ordinary state for one that has been paid for and not yet deployed.
active_deployment_idThe deployment happening right now, or null when nothing is.
Kernel's verdict, not a scan of data (R2,
13-deployments.md §6). It is read from the leases live on the
instance rather than from the page above, so it is the same answer on
page one and on page nine; a client that recomputed it by looking for
a running row would report "nothing deploying" for any customer who
paged back through their history.
It may name a deployment that is not in data at all, and that is
correct rather than a gap: the running one is always the newest, so it
is on page one, and a client on a later page should still show the
banner.
ListEndpointsResponse
domain_countCustomer domains attached now.
domain_limitThe most customer domains one service may hold, across all its https endpoints
(domain_limit when exceeded).
https_countHttps endpoints open now (pending purchase requests are not counted).
https_limitThe most https endpoints one service may hold open. An add button disables itself when
https_count reaches it; the add is refused with https_limit past it.
https_host_suffixWhat follows the label in a free host, zone.<zone>.zaroz.cloud: preview the address as
<label>. plus this. Present exactly when https_zone is. Before an endpoint exists the
label is optional and the endpoint's id names the host.
https_zoneThe zone the free address of a new https endpoint lands in, e.g. hel1. Absent when the
service has no placement to read yet.
ListGrantableOrganizationApiTokenCapabilitiesResponse
max_lifetime_daysLongest lifetime kernel accepts for an organization token, in days.
null means kernel enforces no maximum: only that expires_at is in
the future, and omitting it means the token never expires.
ListGrantableServicesResponse
ListInvoicesResponse
Pagination metadata included in paginated responses
ListMyApiTokenCapabilitiesResponse
ListMyApiTokensResponse
ListMyApplicationDelegationsResponse
ListMyNotificationsResponse
Pagination metadata included in paginated responses
unread_countThe caller's TOTAL unread count, across every page -- not merely how
many of the notifications in data are unread. The bell icon's badge
needs the whole number regardless of which page happens to be open.
ListMyReferralLinksResponse
ListMyServiceInstancesResponse
Pagination metadata included in paginated responses
ListMySessionsResponse
ListMyTicketsResponse
Pagination metadata included in paginated responses
ListOrganizationApiTokensResponse
ListOrganizationWalletEntriesResponse
Pagination metadata included in paginated responses
ListProductPlansResponse
ListProductsResponse
Pagination metadata included in paginated responses
ListPublicProductPlansResponse
ListPublicProductsResponse
Pagination metadata included in paginated responses
ListRegionsResponse
ListRunsResponse
Pagination metadata included in paginated responses
ListScalingDecisionsResponse
Pagination metadata included in paginated responses
ListScannerSubscriptionsResponse
Pagination metadata included in paginated responses
ListSchedulesResponse
Pagination metadata included in paginated responses
ListServiceInstanceActivityResponse
Pagination metadata included in paginated responses
ListServiceInstanceResourcesResponse
primary_role_is_inconsistenttrue when two live resources both satisfied the primary rule (a data fault); then no
resource is marked is_declared_primary.
ListServiceSharesResponse
limitHow many live shares one service may carry.
ListSharedServiceInstancesResponse
ListSubscriptionResourcesResponse
primary_role_is_inconsistenttrue when two live resources both satisfy the primary rule, which
A2-S9b made a hard error because it is never a legitimate state
(design doc §9.1).
When set, every is_declared_primary in data is false -- the
resolver refuses to guess between them -- and a consumer should say so
rather than render "no main resource", which is indistinguishable from
a subscription that legitimately has none.
It is a field rather than an error because this is a read-only
display surface and failing the whole response helps nobody. It is a
field rather than a log line because a silent degrade would make the
screen most likely to reveal the corruption the screen that hides it
(design doc §50).
The running service these resources belong to, carrying the name and slug the customer refers to it by. Included here rather than fetched separately because this read already resolves the instance to find the resources at all.
ListSubscriptionsResponse
Pagination metadata included in paginated responses
ListUnitEventsResponse
Oldest first; newest first for a read with before or newest.
has_earlierBackwards reads only: whether events matching the filters exist before
this page. Always false for a forward read.
next_afterPass this as after next: the last returned seq, or the one you sent
when nothing was new. After a backwards read it is the highest seq
returned, so the view follows live from the page it opened on.
oldest_retained_seqThe oldest seq still kept (events are kept 30 days).
next_beforeBackwards reads only: pass this as before to load earlier events (the
lowest seq returned); null for a forward read or an empty page.
ListUnitPodsResponse
next_cursorPass as cursor for the next page; absent on the last.
ListUnitTerminationsResponse
next_cursorPass as cursor for the next page; absent on the last.
ListUnitWebhookDeliveriesResponse
ListUnitWebhooksResponse
ListUnitsResponse
desired_stateWhat the service as a whole is meant to be doing: stopped when it has live units and
none is meant to run, else running.
included_unitsHow many units the plan's price covers; units above it are billed as extras.
max_unitsThe most units this service may run: the product's maximum capped by the organization's limit.
multi_unit_in_useThe service runs more than one unit now, or its policy is autoscaled.
restarts_24hContainer terminations across every unit of the service in the last 24 hours, gone units included. Computed by the kernel; clients do not sum the units.
scalableThe product allows more than one unit.
volume_lockedA shared volume holds the service to exactly one unit, whatever the product allows.
The organization's units and pod starts against its limits, which the console's near-limit notice reads. Absent for a service that does not run as units.
ListVpsOperatingSystemsResponse
LogCoverageNoteResponse
codetextLogDirectionParam
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
LogLineResponse
atWhen the container emitted the line, as Kubernetes recorded it.
idStable across overlapping reads of the same output: the line's instant plus its position within the run of lines sharing that instant. A client resuming from a cursor can dedupe on this without comparing text.
messageLogMarkerKindResponse
LogStreamTicketResponse
containerThe container the ticket is minted for. The gateway refuses any other, so a client switching containers mints a new ticket.
expires_atWhen the ticket stops being accepted. A client re-mints on expiry; the short life is what makes a leaked URL harmless.
urlThe gateway URL to open a WebSocket against. Carries the signed ticket in its query string and is single-purpose: it grants a read of exactly one container's output and nothing else.
LogicalColumnTypeRequest
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, size | |
| type = object · requires: kind, precision, scale | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind |
kindsizeunsignedLogicalDefaultValueRequest
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind | |
| type = object · requires: kind, value | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind |
kindLoginResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: status, challenge_id |
challenge_idstatusMapSettingDto
defaultlabelMirrors [MapLabel] by hand.
MarkDiscoverySeenRequest
keysMaskedInvitationEmailResponse
emailAlready masked by the caller (e.g. j***@example.com) before this type is built; masking is not this DTO's job. This is deliberately the only field on this response.
MeResponse
created_atdiscord_notifications_enabledWhether kernel-generated notifications are relayed to this user as
Discord DMs, on top of the in-app center they always get. Read back
so the toggle PATCH /me writes has somewhere to read its own
current state from.
idis_onboardedlanguageThe caller's own display language, as an unvalidated BCP-47-ish tag
(LanguageCode is a newtype over String and validates nothing).
Published because the onboarding screen and the account page both
need to render the value the account already holds as their default.
console/app/onboarding/page.tsx records the gap this closes: it had
to start the language and billing-country selects empty because
nothing on /v2 reported either field, which meant re-answering
onboarding silently guessed instead of showing what was already
stored.
namesystem_permissionsThe caller's own platform permissions, as
[kernel_core::domain::permissions::SystemPermission]'s wire strings
(view_all_orders, manage_users, ...). Empty for an ordinary
customer, which is nearly every caller.
Holding one of these IS being staff. The kernel has no separate staff flag, so a non-empty list is the whole of "this caller may open the admin app", and each value decides one gated section inside it.
Field-for-field the same answer /v1's
CurrentUserView::system_permissions gave (deleted with /v1 in
88cb24c1; it rendered User::permissions through the same Display).
Nothing on /v2 published it, so admin recovered it by intersecting
GET /api/v2/admin/users/{id}'s roles with GET /api/v2/admin/ permissions' granted_by_roles: two extra round trips per render,
growing with the role count, and both of those routes sit under
/admin/ and so behind require_elevated_session -- meaning an
un-elevated staff session could not learn what it held at all
(ZC-0410, and ZC-0411 which this closes with it). /api/v2/me has no
admin path segment, so it is not elevation-gated and does not
reintroduce that trap.
Empty for a restricted API token, never the owning user's list.
A restricted token's authority is its grants, which
domain::policies::api_token_intersect intersects with these
permissions once per operation; there is no mapping from a
SystemPermission back to the ApiTokenCapability a token would also
have to carry, so the owner's list is not an answer to "what may this
token do", and publishing it would tell a leaked token only that its
owner is staff. /v1 never had to decide this: its current-user
route refused a token caller outright.
avatar_asset_idThe caller's own avatar (ZC-1306), addressed through
/api/v2/assets/{id}. None when the account has never set one
(no OAuth provider avatar and nothing uploaded). An asset id, not a
URL -- see OrganizationResponse::icon_asset_id's own doc comment
for the /v2 convention this follows: the id itself changes on
every replace, uploaded or provider-synced alike, so a consumer
never has to append a cache-busting query parameter.
billing_country_codeThe ISO 3166-1 alpha-2 country the account is billed from, None
until onboarding answers it.
Write-once in practice: UserManagementService::update_user_profile
refuses to change it once is_onboarded is true and a value is
already set, so a client rendering an edit control for it after
onboarding is rendering a control that cannot succeed.
emailResolved through UserEmailService (checks oauth_accounts first,
then password_credentials). None when neither source has an
address for this user -- User itself carries no email field, so
this cannot be filled in by a pure User conversion; see
get_me_handler.
MemoryPressureResponse
last_high_atlevelhigh while pressure is sustained right now, recent for an episode
that has passed but is still inside the retention window.
peak_psi_some_avg60Worst percentage of wall time spent stalled on memory reclaim.
peak_working_set_ratioWorst working set during the episode, as a fraction (0-1) of the limit.
MeteredEstimateResponse
basisHow this is billed, in kernel's words.
included_portsPorts the plan includes at no charge.
monthly_centsEvery priced port held for a whole month. Zero when the plan includes them all.
per_port_monthly_centsWhat one priced port costs held a whole month, in cents. monthly_cents is this
times priced_ports; a client shows it rather than dividing.
priced_portsPorts billed per month held.
MetricLineResponse
[bucket start in epoch milliseconds, value], 120 of them.
limitThe ceiling this line is measured against, or null when it is unmetered or the unit
has no limit set.
Latest, mean and max of the buckets with a value; absent when there is none.
MetricSeriesResponse
idStable identifier: cpu, memory, net_in, net_out. A consumer
keys its unit formatter off this, never off label.
labelRendered as written. Naming a series is kernel's job; converting its
unit for display (bytes to MiB) is the client's, which is the same line
R2 already draws for prices.
unitThe unit points, limit and summary are all expressed in: cores,
bytes, or bytes_per_second. Every number on this series shares it,
so a client never has to know which field carries which scale.
limitThe ceiling this series is measured against, or null when the series
is unmetered and a line would invent a bound that does not exist
(15-metrics.md §4).
Attached to the series rather than to the instance for two reasons: it is per series (network has none), and a ceiling that arrives with the points cannot disagree with them.
Absent when the window holds no samples. The panel then shows no figures rather than inventing them.
MetricSummaryResponse
latestThe newest sample in the window. The whole summary is absent when the window holds no samples at all, so this is never a stand-in for one.
maxmeanMinecraftGameplayDto
difficultyonline_modeMinecraftInventoryItemResponse
file_nameThe bare file name, split off path so a panel need not parse it.
pathAbsolute within the mount, the same spelling the Files capability uses -- follow it there to open the jar in the file browser.
sizeWhat kernel currently knows about one jar's identity.
reasonPresent exactly when state is unresolved.
Present exactly when state is resolved.
MinecraftInventoryKindResponse
Which inventory this is. Mirrors [InventoryKind]'s own two values; a
third, "none", never reaches the wire because the route answers 404
instead (see the controller).
MinecraftInventoryResponse
Unordered, matching DirectoryListingResponse::entries's own
contract: sorting is the panel's.
kindWhich inventory this is. Mirrors [InventoryKind]'s own two values; a
third, "none", never reaches the wire because the route answers 404
instead (see the controller).
MinecraftJarStateResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
MinecraftLoaderDto
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: type, version | |
| type = object · requires: type, version | |
| type = object · requires: type, version, loader_version | |
| type = object · requires: type, version, loader_version | |
| type = object · requires: type, version | |
| type = object · requires: type, version | |
| type = object · requires: type, project_id | |
| type = object · requires: type, pack_id | |
| type = object · requires: type, path | |
| type = object · requires: type, url |
typeversionMinecraftPlayersResponse
Empty unless status is ok.
banned_unavailableSame meaning as ops_unavailable, for banned-players.json.
Empty unless status is ok.
Empty unless status is ok.
ops_unavailableTrue when ops.json could not be read or parsed. ops is then
empty, but that does not mean nobody is an operator -- it means this
answer cannot say.
partial_list_formatTrue when /list's reply did not match the vanilla format and had to
be parsed permissively (parser::parse_list's tier 2). The roster is
still usable; this is a hint that the counts may be approximate on a
heavily modded server.
Every outcome a read or a write can answer with, folded into one status
so a client renders a match rather than branching on HTTP status codes
that are all 200. Ok is the only variant the roster fields or the
action actually succeeding are meaningful under.
max_playersMinecraftPlayersStatus
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
MinecraftSoftwareDto
Which Minecraft server software runs, and where it comes from. The ten
spellings below are exactly minecraft.rs's own
minecraft_software.loader export vocabulary
(vanilla|paper|forge|neoforge|fabric|quilt|modrinth|feed_the_beast| custom_file|custom_url), not [MinecraftLoader]'s own serde tag.
ModeLabelDto
Mirrors [ModeLabel] by hand.
ModeSettingDto
defaultlabelMirrors [ModeLabel] by hand.
MyApiTokenCapabilityResponse
admin_onlyMinting it needs admin_authorized and an elevated session.
Closed, policy-owned action catalog. Capabilities are exact: there is
deliberately no prefix or glob matching, and unknown wire values are
rejected during deserialization.
PartialOrd/Ord exist so a capability set can be a BTreeSet, which is
what [crate::domain::auth::application_token::ApplicationToken] stores.
The ordering is the declaration order and is not a wire contract: nothing
serializes it, and as_str remains the only stable representation.
MyApiTokenResponse
created_atidnameexpires_atlast_used_atMyApplicationDelegationResponse
application_idapplication_namePresentable name, resolved by the kernel so this reads "the Discord
bot" rather than a bare id -- the same reason the consent page and the
management page must read from one source (grants spec §3.1/§4.1).
What the caller approved this application to do.
created_atidoriginsession_delegation or explicit_consent.
last_used_atrevoked_atMyDiscoveryResponse
MyInvitationStatusFilter
Only pending and declined are listable this way, matching the design's route table:
accepted, revoked and expired invitations do not belong in a recipient's actionable inbox.
MyReferralLinkResponse
conversion_countcreated_atidslugupdated_atuse_countMyServiceInstanceResourcesResponse
cpumemory_gbMemory in GiB, fractional (0.5 = 512 MiB)
storage_gbStorage in GiB.
MyServiceInstanceSummaryResponse
availabilitycluster_unavailable means the platform cannot currently resolve a cluster for this service's hardware profile -- the same profile-to-cluster resolution the status service itself uses to decide whether to attempt a live read. It does NOT mean a live reachability probe against the cluster failed; no such probe is made for a list of many rows. A row never fails the whole list: an unresolvable cluster for one row answers cluster_unavailable on that row alone.
created_athas_pending_invoiceWhether the owning subscription has at least one unpaid, pending invoice right now.
idnameproduct_idproject_idThe purchased sizing, in the same units ResizeResourcesRequest uses --
see that type's own doc comment. memory_gb is fractional (sub-GiB
workloads are real since the 2026-09-04 migration --
kernel_http_foundation::contracts::memory_units's own doc comment);
storage_gb is whole GiB, because storage never went sub-GiB.
slugsubscription_idsubscription_statuscancels_atThe owning subscription's scheduled end, or null if none is
scheduled. Mirrors SubscriptionResponse::cancels_at.
Set only while the debt ladder holds this service stopped (V-0482): own_debt when its organization has an unpaid balance, restricted when it is frozen because of a debt elsewhere (contact the organization's owner). null otherwise, and always null on routes other than GET ./service-instances and GET ./service-instances/{id}. Never identifies the debtor.
parent_subscription_idZC-0984: the bundle this instance's subscription is a member of, or
null for an ordinary, standalone subscription.
The service's aggregate run state, folded from its own resources' recorded statuses -- the same fold the live status route (GET .../service-instances/{id}/status/stream) uses, read here from the database rather than a live cluster call so listing many services costs one query, not one Kubernetes call per row. null only if the instance's resources could not be read at all; in practice every row answers not_provisioned at worst, never null.
The authored storefront shelf of this row's product, resolved through its display profile -- the same value ProductResponse.storefront_category publishes, repeated here so a client listing many services does not have to read a product per row to learn what kind of thing each one is (ZC-1270). null when nobody has categorised the display profile yet, which is a real state and not an error. This exists because the route returns EVERYTHING the caller owns, and a frontend that sells only part of the catalogue had no authored fact to filter on -- the gaming app was listing the business app's products. It is deliberately the authored shelf rather than a derived category: ProductResponse.category's own documentation warns that its fallthrough files databases, object storage and static sites all as game servers.
MySessionResponse
created_atWhen this session's current credential was issued -- the most recent rotation, not necessarily the original sign-in. See the type's own doc comment.
expires_atidlast_used_atSame caveat as created_at: refreshed on rotation, so it tracks "last
time this session's access token was renewed" rather than every
individual API call.
ip_addressCaptured from the request that most recently refreshed this session.
None when no client address was resolved.
user_agentCaptured from the request that most recently refreshed this session.
None when the client sent no User-Agent header.
MyWalletPreferencesResponse
autopay_enabledWhether invoices are collected from the wallet automatically when they fall due.
preferred_currencyISO 4217. Read-only: wallets are EUR-only, so there is nothing to choose.
MyWalletTopUpResponse
amount_centsInteger cents of currency.
created_atcurrencyISO 4217. Always EUR today.
expires_atAfter this the checkout lapses and the top-up becomes expired.
idproviderpaypal or nowpayments. Older rows may say mollie.
Where a top-up is. Only credited means money reached the wallet.
checkout_urlThe provider's hosted page to send the customer to. Present once the
checkout exists; absent while creating and on a failed start.
NetworkProtectionModesResponse
default_modeThe mode a new allocation starts in.
gameModes accepted for a game port allocation.
vpsModes accepted for a VPS's dedicated IP.
NotificationCreatedEventResponse
titlebodycreated_atThe moment this frame was assembled, not a persisted column -- see this type's own doc comment.
idkindThe wire spelling of NotificationKind, converted explicitly at the
transport boundary rather than deriving JsonSchema on the domain type
directly (domain crates do not take a schemars dependency -- see
crates/http/CLAUDE.md's "Transport boundary").
Subscription stays spelled order on the wire. See
NotificationKind::Subscription's own doc comment: it was renamed from
Order in the domain (ZC-0261 phase 9f), but notifications.kind is a
text column written since /v1 and dashboard's notification feed
(lib/notifications.ts) already reads the literal string "order" --
changing the wire value would be a breaking, silent rename of every
existing row's meaning.
hrefNotificationKindResponse
The wire spelling of NotificationKind, converted explicitly at the
transport boundary rather than deriving JsonSchema on the domain type
directly (domain crates do not take a schemars dependency -- see
crates/http/CLAUDE.md's "Transport boundary").
Subscription stays spelled order on the wire. See
NotificationKind::Subscription's own doc comment: it was renamed from
Order in the domain (ZC-0261 phase 9f), but notifications.kind is a
text column written since /v1 and dashboard's notification feed
(lib/notifications.ts) already reads the literal string "order" --
changing the wire value would be a breaking, silent rename of every
existing row's meaning.
NotificationResponse
titlebodycreated_atidkindThe wire spelling of NotificationKind, converted explicitly at the
transport boundary rather than deriving JsonSchema on the domain type
directly (domain crates do not take a schemars dependency -- see
crates/http/CLAUDE.md's "Transport boundary").
Subscription stays spelled order on the wire. See
NotificationKind::Subscription's own doc comment: it was renamed from
Order in the domain (ZC-0261 phase 9f), but notifications.kind is a
text column written since /v1 and dashboard's notification feed
(lib/notifications.ts) already reads the literal string "order" --
changing the wire value would be a breaking, silent rename of every
existing row's meaning.
readhreforganization_idOAuthAccountResponse
has_avatarWhether this provider has a stored avatar that could be activated.
The URL itself is not published: it is a provider-side resource the
kernel imports through AvatarImportService, not something a client
should be fetching directly.
provider_idemailThe address the provider reports for this account, when it reports one. Only ever the caller's own.
last_used_atOAuthProviderResponse
iddisplay_nameA reseller-chosen label. None means the client should render the
provider's own conventional name from the id.
OnExit
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
OnlinePlayerResponse
is_opnamegamemodesurvival, creative, adventure or spectator. Present only when
include=gamemode was asked for and the server answered for this
player.
Present only when include=position was asked for and the server
answered for this player.
OpenInvoicesSummaryResponse
countInvoices issued and not yet paid, including a postpaid invoice before
its due date. 0 means nothing is owed.
overdue_countHow many of count are past their due_at.
currencyISO 4217 code of total_cents; null exactly when total_cents is.
total_centsSum of the open invoices' tax-inclusive totals, in cents. null when
nothing is open, and also when the open invoices span more than one
currency (an amount that adds two currencies is withheld, not guessed).
OperationStatusResponse
Mirrors kernel_domain::domain::operations::OperationStatus 1:1, kept as
its own /v2 response type for the reason every other mirrored enum in
this file is: a rename on the domain enum must not silently change a wire
value.
OperatorPlayerResponse
levelnameonlineOrganizationApiTokenLifetimeResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
OrganizationApiTokenResponse
created_atidThe lifetime shape of an organization API token, on the wire.
MembershipTied is the default. A create request that omits
lifetime gets it, and that is the safer of the two: the token dies when
the person who minted it stops being a member. OrganizationOwned is the
one that keeps working afterwards, and asking for it is always explicit.
namecreated_by_user_idThe member who minted this token. Null when that account has since been deleted; an organization-owned token deliberately survives that.
expires_atlast_used_atOrganizationInvitationResponse
created_atemailexpires_atidinvited_by_nameorganization_idorganization_nameDenormalized onto every row (also present, redundantly, on an organization-scoped listing) so GET /me/invitations does not need a second round trip per organization to render a usable list.
rolestatusThe invitation's effective status: a stale pending or declined row past its own expiry reads as expired here even before any sweep has rewritten the stored column. See OrganizationInvitation::effective_status.
invited_by_avatar_asset_idorganization_icon_asset_idresponded_atOrganizationInvitationReviewResponse
created_atexpires_atidinviter_nameorganization_idWhere Accept navigates once it succeeds.
organization_namerolestatusThe invitation's effective status, not necessarily the raw stored column.
inviter_avatar_asset_idorganization_icon_asset_idOrganizationInvitationStatusResponse
Mirrors [OrganizationInvitationStatus] on the wire. A separate type rather than reusing the
domain enum's own Serialize impl, matching every other /v2 status/role pair in this crate
(see OrganizationRoleResponse next to OrganizationRole in contracts::organizations):
the wire representation and the domain representation are allowed to diverge without a
compile error forcing them apart later.
OrganizationLimitsResponse
nearingAny figure is near or at its limit: the console shows its notice and points to support.
The month's metered spend against the organization-wide spend cap.
One figure of the organization against its limit.
One figure of the organization against its limit.
OrganizationMemberResponse
created_atnameThe member's display name.
organization_idroleuser_idavatar_asset_idThe member's profile picture, addressed through /api/v2/assets/{id}. None when they never set one.
emailNone when the account has no reachable address.
OrganizationResponse
created_atidnameslugURL-safe identifier, unique platform-wide. Console routes are /{slug}/...
billing_country_codeTwo-letter country the organization is taxed under. Null until set; a purchase in a shared organization needs it (PUT /organizations/{id}/billing-country).
icon_asset_idThe organization's uploaded icon (ZC-1305), addressed through
/api/v2/assets/{id}. None when no icon has been uploaded. An
asset id, not a URL -- the /v2 convention every other asset-backed
field on this surface already follows (see
OrganizationMemberResponse::avatar_asset_id's own doc comment): the
id itself changes on every replace, so a consumer building the URL
from it never has to append a cache-busting query parameter to avoid
serving a stale image.
The caller's role in this organization, when resolved.
OrganizationRoleRequest
Distinct from OrganizationRoleResponse because request and response
enums are separate types on /v2 (design doc §43.4), even where they
currently carry the same variants.
OrganizationStandingResponse
restrictedmessageOrganizationWalletResponse
One row per currency the organization holds, ordered by currency code.
A currency with no money in it has no row. The balance is summed from the ledger and only non-zero sums come back, so an organization that has never been credited answers with an empty list, and so does one whose movements happen to net to exactly zero. Treat a missing currency as zero; do not treat an empty list as "no wallet".
organization_idThe organization whose wallet this is -- echoed back so a client that fans several of these out cannot mis-file an answer.
OverflowRangeResponse
countfromtoOverlapPolicyResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
OwnPasswordResetRequest
originThe app URL the emailed reset link should point back at, e.g.
https://zaroz.cloud/console. Same shape and validation as
[ForgotPasswordRequest::origin]; a disallowed or malformed value is a
real 4xx refusal. Omitted, the link points at the platform dashboard.
PaginationMeta
has_next_pageWhether there is a next page
has_previous_pageWhether there is a previous page
pageCurrent page number (1-indexed)
page_sizeNumber of items per page
total_itemsTotal number of items across all pages
total_pagesTotal number of pages
PasswordAcceptedResponse
acceptedAlways true. A real typed field rather than an empty body so a
generated client has a success type to name.
PasswordRequestDto
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: generate | |
| type = object · requires: value | |
| type = object · requires: clear |
generatePasswordSignupRequest
emailpasswordoriginThe app base the emailed verification link should point back at
(ZC-1425, V-0664): https plus a host, optionally followed by exactly
one app mount path -- https://zaroz.cloud/gaming,
https://zaroz.cloud/console, https://zaroz.cloud/admin, or a
reseller's https://<host>/gaming. A bare origin keeps working and
links to the host root. No other path, no query, no fragment. The link
is <origin><path>/verify-email?token=.... Checked against
the same allowlist OAuth's own redirect_to uses; a disallowed or
malformed origin refuses the whole request with a 4xx, never a
silent fallback. Omit to keep the default: the dashboard.
referral_codeA referral link's slug, if the visitor arrived through one (ZC-1032,
owner ruling 2026-09-17: attribution happens at signup). Never
validated here and never blocks or slows down signup, nor changes
this route's response, whether the code is real, expired, self-owned,
or absent -- see signup_handler's own doc comment for why.
PasswordSignupResponse
acceptedAlways true. Kept as a real typed field, rather than an empty
Success(()), so a generated client gets an actual success body;
there is nothing more to report here without reopening the oracle
described above.
PasswordSpecDto
envgeneratedidoptionalV-0703. See [PasswordSpec::optional]: the customer may leave this
password unset, or clear it later.
revealableZC-1379 slice S4. See [PasswordSpec::revealable]'s own doc comment;
the dashboard uses this to grey out the reveal action rather than let
a customer hit the 409 the reveal route otherwise answers with.
rotatableZC-1379 slice S4. See [PasswordSpec::rotatable]'s own doc comment.
min_lengthPasswordStatusDto
envidsetPasswordStatusResponse
email_verifiedhas_passwordemailThe address password login uses, or the provider address a first
password would be attached to. None when neither exists.
linkable_emailThe provider-proven address POST /auth/password/set would attach a
first password to. None once the account already has one.
PathRouteRequest
path/api, /api/v1: a slash, then segments of letters, digits and . _ ~ -; no trailing
slash, never / itself (the domain's own endpoint is the default route).
target_endpoint_idAn open https endpoint of that service.
target_service_instance_idThe service that answers, in the same project.
strip_prefixRemove the path before the request reaches the service (/api/users arrives as
/users). Off by default.
PendingDownsizeResponse
applies_atThe target shape a pending resize would leave the service at, in the same
units ResizeResourcesRequest uses.
PendingGrowthResponse
invoice_idinvoice_statusThe target shape a pending resize would leave the service at, in the same
units ResizeResourcesRequest uses.
capacity_held_untilWhen the capacity held for this growth expires, or null if nothing is currently held (already settled and waiting for the platform to apply it, or a lapsed hold not yet re-attempted).
PendingReasonResponse
codemessagePendingResizeResponse
PendingResizeTargetResponse
cpumemory_gbMemory in GiB, fractional (0.5 = 512 MiB)
storage_gbStorage in GiB.
PlanResponse
descriptionavailableKernel's verdict on buying this plan in the region named by region_id, and the only one -- nothing is to be derived beside it. True when no region was named, because nothing has been judged and so nothing is refused.
cpuidmemory_gbnameproduct_idsort_orderstorage_gbtax_behaviorThe billing terms this plan is sold at (V-0717), monthly first: one entry per term (1, 3, 6 or 12 months) a live Price exists for, each with what one whole term costs and what it saves against buying the same months monthly. Send the chosen entry's cadence_months to POST /checkout and POST /checkout/quote. Empty when the plan has no resolvable price; a single monthly entry means no longer term is sold.
iconpriceThis plan's resolved monthly price, already adjusted for the caller's reseller price multiplier if any. Null when no live Price resolves for this plan's (product, hardware profile) combination -- a broken or ambiguous catalog price hides this one plan's price rather than failing the whole listing; see this crate's report for the full rationale.
unavailable_reasonWhy this plan cannot be bought in the region named by region_id, in kernel's own words, to be rendered exactly as written and never composed, templated or interpolated by a client. Carries no capacity figure of any kind -- no count, percentage, node or cluster. Null exactly when available is true.
PlanTermResponse
cadence_months1, 3, 6 or 12.
monthly_equivalentprice spread over the term's months, rounded to the cent. Display
only: nothing is charged at it.
priceWhat one whole term costs, already adjusted for the caller's reseller
price multiplier; tax per the plan's tax_behavior.
savingWhat this term saves per term against the monthly price times the term's months. Null for the monthly term and when there is no monthly term to compare with. Negative when the longer term costs more.
saving_percentsaving as a percentage of the undiscounted figure, one decimal.
PlayerActionRequest
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, name | |
| type = object · requires: kind, name | |
| type = object · requires: kind, name | |
| type = object · requires: kind, name | |
| type = object · requires: kind, name | |
| type = object · requires: kind, name, mode | |
| type = object · requires: kind, name, message | |
| type = object · requires: kind, name, item +1 more | |
| type = object · requires: kind, message |
kindnamereasonPlayerActionResponse
Every outcome a read or a write can answer with, folded into one status
so a client renders a match rather than branching on HTTP status codes
that are all 200. Ok is the only variant the roster fields or the
action actually succeeding are meaningful under.
PlayerPositionResponse
xyzdimensionNamespaced dimension id such as minecraft:overworld; absent when
the server did not say.
PodLeaveReason
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
PortAllocationResponse
allocated_atexternal_ipexternal_portidinternal_portis_primaryis_systemnetwork_protection_modeprotection_managedTrue when protection is auto-managed by the edge (Warden) and manual modes do not apply. Static, comes from the pool this allocation sits on, and is what a panel's "Protected" flag reads.
protection_stateAlways unknown for a protection-managed allocation on this route,
and not_managed otherwise. The live detector value (normal /
pressure / attack) is served separately by
GET /service-instances/{id}/external-access/live, so this listing
never waits on a Warden node.
protocoldisplayPostpaidDisclosureResponse
credit_limit_centsheadroom_centscredit_limit - open_receivable - pending_settlement, never below 0.
open_receivable_centsWhat the organization owes today (ledger receivables, never negative).
pending_settlement_centsRenewal periods already running on credit and not yet invoiced.
renewals_billed_postpaidtrue when this purchase's renewals will be billed after each period
instead of in advance, as things stand now.
Why not, when the organization has a limit and they will still be prepaid.
PrepaidReasonResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, requested_cents | |
| type = object · requires: kind | |
| type = object · requires: kind |
kindrequested_centsPreviousRunRequirementResponse
What a previous_run guard requires the schedule's own last run to have
been.
PriceLineResponse
dimensionmeasurementrecurrencesort_orderunitPriceSummaryResponse
cadence_monthsThe period this Price's rates are quoted per (1 | 3 | 6 | 12).
currencyidnameterm_monthsPriceTierResponse
flatper_unitup_toPrincipalCopyResponse
carries_keytrue once the copy runs the current pod template, mount included.
A copy that has not restarted since API access changed reads false.
unit_keyThe unit's key, as GET .../units lists it.
ProcessInfoResponse
commandcpu_percentmemory_rss_bytesnamepidppidstateuptime_secsProcessTreeResponse
Always a 200 with a discriminated status: a tree being unavailable is an
expected outcome the page renders an explanation for, not an HTTP error.
truncatedroot_pidProcessTreeStatusResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
ProductFamilyView
Mirrors the domain [ProductFamily] 1:1, as its own /v2 response type --
never ProductFamily itself -- so a domain rename or reorder must be a
deliberate, matching edit to this From impl rather than a silent
wire-format drift. The retired ProductKindResponse (deleted A2-S13c
alongside CatalogServiceKind) existed for the same reason.
ProductPublicPortsResponse
free_port_slotsPorts the plan includes at no charge. Zero on a product whose every port is priced.
https_includedThe product's own template already opens its public HTTPS front door (a Static Site,
WordPress): the purchase asks no question about internet access and sends no HTTPS
endpoint for it. Derived from the template's front_door route, never authored separately.
https_offeredAn HTTPS endpoint can be opened on this product (decision-0308): a free platform host,
the customer's own verified domains and automatic TLS, never metered. True for a
workload that publishes a site (its template owns a front door, or it declares the
custom_domain capability), whatever it says about raw ports above: it needs no free
slot and no port price. False for a Worker, a Cron Job and the databases.
offeredA customer can ask for public ports on this product at all.
pricedPorts beyond the free ones are allowed and billed by the hour held. A quote with ports requested says what they cost.
ProductResizeDimensionResponse
Mirrors the domain [ResizeDimension], same rule as
[ResizePolicyKindResponse] above. Named Product* rather than the bare
ResizeDimensionResponse its admin (contracts::product_definitions) and
subscriptions (kernel_http_v2_subscriptions::contracts::resize)
siblings might suggest: schemars keys /v2's OpenAPI schema components by
Rust type name across the whole document, and
kernel_http_v2_subscriptions::contracts::resize::ResizeDimensionResponse
(a resize QUOTE's dimension: current/requested/growing/available) already
held that name (no_v2_schema_component_name_collides, crates/http/src/controllers/mod.rs).
This one is a narrower, declarative fact -- which dimensions a PRODUCT'S
resize policy grows for free -- so it takes the more specific name rather
than leaving both in the tree under one auto-disambiguated name.
ProductResponse
available_for_orderWhether this product can currently start a new order
categoryThe category derived from this product's service kind. Kept for existing clients; prefer storefront_category, which is authored per display profile rather than derived from a closed enum whose fallthrough files databases, object storage and static sites all as game servers.
created_atWhen this product was created. There is no separate published_at; console uses this as the product's introduced date for discovery dots (ZC-1302).
enabledfamilyThe provisioning shape this product deploys as (design doc §4.2/§4.5: A2 matches ProductFamily exhaustively at the one dispatch site that still needs it). Not a mirror of kind or category: several kind values can share one family, and this is the axis future dispatch actually branches on.
growable_dimensionsThe resource dimensions resize_policy_kind grows for free, if any. Always empty for catalog_plans, and may be empty for plan_change (a product offering only a plan change, no free growth).
has_free_trialWhether this product currently has an enabled, non-expired free-trial configuration. Per-account eligibility is not checked here.
idminimum_cpuminimum_memory_gbFractional gibibytes (2026-09-04 mebibyte migration): 0.5 is 512 MiB.
minimum_storage_gbnameproduct_slugThis product's own unique machine name (design doc §4.2 A2: /v2 exposes products.slug instead of the frozen /v1 service-kind enum). Distinct from slug above: slug is the shared addressable segment of the display profile this product presents under, and several products can share one display profile and therefore one slug. product_slug never collides across products.
Whether this product sells public ports and how many its plans include (V-0546). Decided by the rule checkout refuses by, so a product shown here as offering ports is never refused them for that reason.
purchase_stepsThe questions buying this product asks, in the order a checkout asks them, always ending in review. Derived here from this product's own bounds, its plan list and the regions this caller's storefront may order into -- never authored, and never a capacity signal: a step is present because the product offers a choice, not because a region happens to have room. A product sold in one region on one plan with a fixed shape is ["review"], which is the whole flow and not a flow with four screens missing.
resize_policy_kindHow this product permits a resize once bought (ZC-1481): whether it offers a self-service change to another of its own catalog plans (plan_change), free growth on growable_dimensions within its current plan (free_grow), or neither (catalog_plans). Read from this product's own product_definitions row; catalog_plans also when the product has no such row at all, since there is no kind-level fallback to inherit and no row means no self-service resize either way. Exists so a client can tell whether to offer a plan-change control without probing a quote for PlanChangeNotOffered first.
slugURL-safe segment addressing this product, from its display profile. Use it instead of the UUID id when building a console link. Several products sharing one display profile share this slug, as they share the name and icon beside it.
The display profile's authored teaching copy (ZC-1161): what this product is, how it works, and what people use it for. Null when nobody has authored one yet, in which case the client should fall back to its own equivalent of console's lib/nav/product-about.ts fixture table. Resolved to the platform's one shipped locale; see DisplayProfileAbout's own module doc for how a second locale is meant to be introduced without a wire-format change.
about for EVERY authored locale, keyed by IETF locale tag (V-0870): pick the viewer's locale, then en-US, then any entry. Null when nobody has authored one.
iconAn icon TOKEN from this product's display profile: a brand slug or a Lucide name, resolved by the client through @zaroz/ui's ResolvedIcon. Distinct from icon_asset_id, which is an operator-uploaded image and wins outright when both are present. Null when nobody authored one, in which case the client falls back to a monogram. PlanResponse.icon is the same field one table over, and is why this one exists: a product had the token on its display profile and this response was simply not carrying it (ZC-1125).
icon_asset_idmaximum_cpumaximum_memory_gbmaximum_storage_gbPer-locale names keyed by IETF locale tag (V-0870), e.g. {"es-ES": "Almacenamiento de objetos"}. name stays the canonical English name and the fallback: a viewer whose locale has no entry shows name. Null when nobody has translated this product.
starting_priceCheapest monthly price across this product's plans, in the platform's single supported currency (design doc §44.3, EUR only for now), already adjusted for the caller's reseller price multiplier if any. Null when the product has no priceable plan -- see this crate's report for why a resolver refusal surfaces as null here rather than an error.
The authored storefront shelf, from this product's display profile. Every value is a console route directory, so console links this product as /{org}/{project}/{storefront_category}/{slug}. Null when nobody has categorised the display profile yet, in which case fall back to category.
ProfileAboutResponse
ProjectCycleSpendResponse
amount_centsMoney is integer cents on every /v2 DTO, never a float or a
formatted string -- same convention as InvoiceSummaryResponse.
Pre-tax.
currencyISO 4217, taken from the invoice lines themselves.
tax_amount_centsThe tax on those same lines. Each line snapshots its own tax at issue time, so this is a sum of stated figures rather than a rate applied to a total.
total_amount_centsamount_cents + tax_amount_cents, carried so a caller rendering one
number does not have to decide which of the two it wanted.
ProjectResponse
created_atidnameorganization_idslugURL-safe identifier, unique within the owning organization. Console routes are /{org}/{slug}.
updated_atdescriptionProjectStatsResponse
What the project is being charged for the service it is receiving right now, one entry per currency. Empty when nothing in the project is under a live service window -- which is the honest answer for a project with no subscriptions and for one whose subscriptions have all lapsed, never an error. In practice this holds exactly one entry: the platform transacts in EUR only.
project_idresource_countHow many live subscriptions this project holds. A "resource" here is a subscription -- design doc §34.1 puts Project directly above Subscription, so one purchase is one row -- not a resources row (which would count a single VPS as its VM plus each of its volumes) and not a service instance (which would drop a paid subscription still awaiting activation). "Live" is deleted_at IS NULL and nothing more, the same rule that decides whether the project can be deleted and the same rule GET /console/subscriptions?project_id= pages with, so this number is exactly how many rows the caller sees on clicking through.
PublicCaptchaConfigResponse
enabledWhether any action on this host requires a solved challenge at all. false
for a missing config, a disabled one, or one missing a key -- see
CaptchaConfig::is_active.
protected_actionsStable snake_case action names the widget is required for. Empty when
enabled is false.
providerProvider wire value, e.g. turnstile. Always present, even when enabled is
false, so a client can wire up the right widget component ahead of a
provider ever being turned on.
site_keySafe to render in a browser; this is the half of the key pair that is meant
to be public. None exactly when enabled is false.
PublicIncidentResponse
titleThe headline to show.
idA stable key for deduplicating a poll or remembering a dismissal.
started_atWhen the incident began, so the banner can date itself.
messageFurther detail, if the operator published any.
PublicMaintenanceResponse
titleThe headline to show.
idA stable key for deduplicating a poll or remembering a dismissal.
scheduled_atWhen the maintenance is scheduled to begin.
expected_duration_minutesHow long it is expected to last, if staff said.
PublicPlanResponse
descriptioncpuidmemory_gbnameproduct_idsort_orderstorage_gbtax_behavioriconpriceThis plan's resolved monthly price, already adjusted for the requested reseller storefront's price multiplier if one was named. Null when no live Price resolves for this plan's (product, hardware profile) combination -- a broken or ambiguous catalog price hides this one plan's price rather than failing the whole listing.
PublicProductResponse
available_for_orderWhether this product can currently start a new order
categoryfamilyThe provisioning shape this product deploys as. See ProductResponse's own family field (the /v2/console mount) for the full rationale; kept here too because it is shop-window information, not an account fact.
has_free_trialWhether this product currently has an enabled, non-expired free-trial configuration on this storefront. Per-account eligibility is not checked here, and cannot be: this caller has no account.
idnameproduct_slugThis product's own unique machine name. Not the display profile's shared slug (this mount does not expose that one at all today) -- see ProductResponse::product_slug (the /v2/console mount) for the distinction between the two.
The display profile's authored teaching copy (ZC-1161): what this product is, how it works, and what people use it for. Null when nobody has authored one yet. This is shop-window information a logged-out visitor needs at least as much as a signed-in customer does -- it is the copy an empty product page teaches with -- so it is carried onto this narrower response rather than dropped with the account-scoped fields above.
about for EVERY authored locale, keyed by IETF locale tag (V-0870): pick the viewer's locale, then en-US, then any entry. Null when nobody has authored one.
iconAn icon TOKEN from this product's display profile: a brand slug or a Lucide name, resolved by the client through @zaroz/ui's ResolvedIcon. Distinct from icon_asset_id, which is an operator-uploaded image served from GET /assets/{id} on this same public mount and wins outright when both are present. Null when nobody authored one, in which case the client falls back to a monogram. Same field as ProductResponse.icon (the /v2/console mount) and PublicPlanResponse.icon below -- this response carried icon_asset_id without it, which was the buy-page half of ZC-1144.
icon_asset_idPer-locale names keyed by IETF locale tag (V-0870), e.g. {"es-ES": "Almacenamiento de objetos"}. name stays the canonical English name and the fallback: a viewer whose locale has no entry shows name. Null when nobody has translated this product.
starting_priceCheapest monthly price across this product's plans, in the platform's single supported currency (design doc §44.3, EUR only for now), already adjusted for the requested reseller storefront's price multiplier if one was named. Null when the product has no priceable plan.
PublicResellerResponse
brand_colorcustom_plan_selector_enabledhostnameidnameog_image_modeOne of platform, logo, custom, disabled.
discord_invite_urlicon_asset_idresolved_og_image_asset_idSee [ResellerResponse::resolved_og_image_asset_id].
PurchaseStepResponse
Mirrors the domain [PurchaseStep] 1:1, as its own /v2 response type --
never [PurchaseStep] itself -- so a domain rename or reorder must be a
deliberate, matching edit to this From impl rather than a silent
wire-format drift. Same rule and same reason as [ProductFamilyView].
The five spellings match console's StepId union exactly
(console/components/purchase/registry.ts), because that registry is a
Record<StepId, PurchaseStep> and a value it has no entry for is a type
error there rather than an empty screen.
QuoteDiscountResponse
descriptionWhat the code does, in kernel's own words, e.g. "20% off for your
first 3 billing cycles". Composed by DiscountCode::describe in the
domain so the quote, the invoice and the admin preview cannot drift
into three sentences for one code.
amount_centsNegative, so the ticket is a sum and the panel renders it with the sign it arrived with rather than subtracting anything.
codeThe code as the catalog stores it, not as the customer typed it.
QuoteLineResponse
descriptionComposed by kernel, and identical to what the invoice line will say --
the same
CreateSubscriptionCheckoutServiceImpl::base_line_description writes
both. A customer reconciling a quote against an invoice compares the
words as well as the money.
amount_centsBefore any discount code.
QuoteRequest
plan_idproduct_idcadence_monthsThe billing term to quote. See [CheckoutRequest::cadence_months]:
omitted is the monthly term, and the quote's total is one whole term.
discount_codeAn optional discount code, exactly as the customer typed it. A code that cannot be used is refused here exactly as it would be at checkout, rather than quietly quoting the undiscounted price.
Public ports to price. See CheckoutRequest::endpoints: the same rules
refuse the same requests here. Each comes back as an informational line
of amount zero, and metered_estimate carries the worst monthly cost.
total_cents never includes them.
hardware_profile_idSee CheckoutRequest::hardware_profile_id's own doc comment.
operating_system_idSee CheckoutRequest::operating_system_id's own doc comment.
organization_idWhich organization would be buying. Decides the reseller price multiplier and the tax jurisdiction, so it is quote input rather than bookkeeping.
project_idWhich project the purchase would be filed under.
Optional, mirroring [CheckoutRequest::project_id]. When supplied it
is still checked against the buying organization -- nothing is
written, but a quote is an answer about a purchase this caller could
make, so naming somebody else's project is refused here too. When
absent, nothing is checked and nothing is resolved: unlike checkout,
a quote never creates the buying organization's default project,
because a quote is documented to write nothing at all.
region_idRequired for every family except a licence. See
CheckoutRequest::region_id's own doc comment.
The size to price. Omitting it quotes the plan as authored.
QuoteResourcesResponse
cpumemory_gbMemory in GiB, fractional (0.5 = 512 MiB)
storage_gbStorage in GiB. Zero means no volume at all.
QuoteResponse
amount_centsAfter the discount, in the invoice's own terms: always the net,
pre-tax figure, never the plan's advertised (possibly tax-inclusive)
price. This is the establishing invoice's amount, and the figure the
two can be reconciled on, for both tax behaviours. See this struct's
own doc comment for why it is not a term of the customer-facing
additive chain on an Inclusive plan.
available_centsbalance - required_cents. Compared against required_cents (not
against this purchase's own total) by the caller: kernel does not
know here whether this purchase itself will reserve anything, only
what the organization's standing already looks like.
cadence_labelHow to read the figures aloud, e.g. "per month, billed monthly". Kernel's own words: it is a claim about a billing term, and a client assembling one from a month count would be deciding what that count means.
cadence_monthsThe billing term quoted, in months (1, 3, 6 or 12): the one asked for, or 1 when none was. Every figure below is one whole term (V-0717).
currencyThe currency every figure below is in.
due_now_centsWhat the customer pays now, which is not always total_cents: a
setup fee, a term paid up front or a prorated first period all move it.
Rendered, never derived. Equal to total_cents for every purchase this
endpoint can price today, and a field anyway, because the day it stops
being equal must not be the day a console starts lying.
What is being bought, described the way the invoice will describe it.
Exactly one line today, because a /v2 checkout issues exactly one
invoice line (InvoiceLineItemKind::BaseSubscription). It is a list
rather than a single field so that a setup fee, a term bundle or a
second priced component does not have to reshape the contract, and so
a client renders whatever arrives instead of a fixed row.
required_centsZC-1324 org trust S5 (§8.4): max(organization_floor, already-reserved) -- the buying organization's own standing, not
this purchase's price. Present on every quote, not only a Measurable
one: an unmeasurable product still explains the organization's floor
this way (§8.2's closing paragraph).
The shape that was priced -- the customer's when they sent one, the plan's when they did not. Echoed so a console showing "2 vCPU, 4 GiB, no disk -- EUR 12.40" is reading both halves from the same answer rather than pairing a server price with its own local idea of the size.
subtotal_centsThe sum of lines, before any discount code.
Tax, as data rather than as something to work out.
The client must never derive any of this from a billing country: which
country applies, whether a business is reverse-charged, and what the rate
is on the day are all kernel's decisions, taken by
TaxResolutionService::resolve.
total_centsWhat the customer pays for one billing cycle.
The code that was applied, what it does, and what it took off.
None when no code was sent; a code that was sent and cannot be used
is a refusal, never a silently absent discount.
What the requested public ports can cost, present only when the request
named some. Ports are billed by the hour held, monthly in arrears, so
this is a worst case (every priced port held a whole month), shown
beside the ticket and never added to total_cents or due_now_cents.
V-0449.04: postpaid disclosure, present only for the OWNER of an
organization with a credit limit. See crate::contracts::standing::PostpaidDisclosureResponse.
The organization's own current restriction, if any -- None when its
standing is Good. Kernel supplies the reason and the numbers; the
frontend supplies the words (§8.4).
QuoteTaxResponse
amount_centsincluded_in_linesTrue when lines already contain this tax (a plan authored
tax_behavior: inclusive). Changes the sentence, never the maths --
see [QuoteResponse].
rate_basis_pointsThe rate as an integer, e.g. 2100 for 21%. For rendering only:
amount_cents is the authority, and multiplying by this would be
computing a price.
labelKernel's word for it -- "IVA", "VAT", "Reverse charge". None when no
rate resolved at all, which is not the same as a zero rate.
noteA sentence that has to appear beside the figures when one applies, such as the intra-community reverse-charge notice. Written by kernel because it is a legal statement about this specific transaction.
RangeSettingDto
defaultmaxminRedeemMyWalletCodeRequest
codeThe code as the customer typed it. Case and separators are normalised server-side.
RedeemMyWalletCodeResponse
amount_centscurrencyentry_idThe wallet entry the value landed in.
RefreshTokenResponse
refresh_tokensession_idtokenRegionHardwareResponse
availabletrue when a purchase on this tier would find room and a live price
right now.
disk_typeThe disk technology, e.g. nvme.
idWhat a client sends back as CheckoutRequest.hardware_profile_id.
namedescriptioncpu_modelThe processor model, when the operator named one.
unavailable_reasonWhy not, in kernel's own words; null exactly when available.
RegionResponse
availableKernel's verdict, and the only one. true when a purchase into this
region would find hardware with room and a live price right now.
Nothing is to be derived alongside it: a second verdict computed on
the client could only ever disagree with the real one.
country_codeISO 3166-1 alpha-2, for flag rendering.
The hardware tiers a customer may choose between in this region
(decision-0347: /v1 let a customer pick, say, "Helsinki Budget" or
"Helsinki Performance", each with its own Price). Send the chosen one's
id back as CheckoutRequest.hardware_profile_id (and to the plan
listing to price plans on it); omit it to let kernel place the service
on the cheapest tier that fits. Empty for a product placed on no
hardware (object storage, a registry).
idWhat a client sends back as CheckoutRequest.region_id.
latitudelongitudenameping_endpointA URL a browser can time a request against, so the console can show the customer their own latency to each region.
slugunavailable_reasonWhy not, in kernel's own words, to be rendered as written
(guard rail R2). Never composed, templated or interpolated by a
client, and never containing a number, a node, a cluster or a
percentage. null exactly when available is true.
RegistryCredentialView
created_atidnamescopepull, push or admin.
usernameThe username to log in with.
last_used_atRegistryCredentialsRequest
passwordusernameRegistryCredentialsResponse
RegistryRepositoriesResponse
RegistryRepositoryView
nameFull name, <namespace>/<path>.
size_bytestag_countRegistryResponse
RegistrySource
hostghcr.io, docker.io, registry.example.com:5000. Always present:
a reference with no host is normalised to [DOCKER_HUB_HOST] on the
way in, so a reader never has to know the defaulting rule.
repositoryacme/worker, library/nginx. Never carries the host.
tagThe mutable name the customer chose.
credential_usernameThe username half of the stored pull credential. None is an
anonymous pull.
digestThe immutable name of what was actually pulled, when the stored reference pins one.
Always None for anything this platform wrote, because nothing
resolves a tag to a digest for a third-party registry: the only
manifest client in the codebase authenticates with HTTP basic, and
ghcr.io, Docker Hub and Quay all require the Bearer challenge
exchange. Some only for a reference a customer pinned themselves.
RegistryTokenErrorBody
RegistryTokenErrorItem
codeUNAUTHORIZED, DENIED or UNSUPPORTED.
messageRegistryTokenResponse
access_tokenThe same token: OAuth2-style clients read this name.
expires_inSeconds the token stays valid.
issued_attokenThe signed bearer token the registry verifies.
RegistryUsageResponse
RegistryUsageSampleView
egress_bytesstored_byteswindow_startRegistryUsageView
egress_bytesBytes served out of the platform in the window (billed once the registry's Price carries an egress line).
fromgap_hoursHours with no measurement, filled with the nearest earlier one.
Hourly measurements, oldest first.
storage_gib_monthsAverage stored GiB over the whole window, as a decimal string.
toRegistryView
accessWhat the registry allows right now: open, read_only (over the cap:
no pushes), suspended (unpaid or moderated) or deleted.
cap_bytescreated_atendpointThe host to docker login to.
idimage_prefix<endpoint>/<namespace>: what an image reference starts with.
labelnamespaceThe namespace every repository of this registry lives under.
region_idsubscription_idupdated_atpurge_atWhen the registry's images will be purged, once deleted.
stored_bytesLatest measured stored bytes (logical); absent before the first measurement (measured hourly).
ReinstallVpsRequest
confirmMust be true. Reinstalling erases all data on the disk and cannot
be undone; the client is expected to have shown that to the person
before sending it.
os_imageThe operating system to install: the id of one entry of
GET /api/v2/catalog/products/{id}/operating-systems. May be the
image already installed.
ReinstallVpsResponse
operation_idThe queued rebuild. Poll
GET /api/v2/service-instances/{id}/operations/{operation_id}.
os_imageThe operating system the machine will be rebuilt with.
resource_idservice_instance_idReplaceFirewallRulesRequest
ReplaceGrantsRequest
ReportClientErrorRequest
error_idThe reporter's own correlation id for this crash, echoed back to the user so a support conversation can name it. Caller-supplied and caller-shaped; see this module's doc comment for why it is not a key.
messageThe error message. Truncated to 2000 characters on the way in.
digestNext.js's build-time error digest, when the crash came from a server component and the framework withheld the real message from the browser. Absent for a plain client-side throw.
stackThe stack trace. Truncated to 8000 characters on the way in.
urlThe page the crash happened on.
user_agentThe browser, as the browser describes itself.
ReprovisionServiceInstanceRequest
keep_datatrue keeps the volumes and rebuilds everything around them. false
destroys this service's data volumes and cannot be undone -- only
an offsite backup taken beforehand can bring them back.
Required. See this type's doc comment for why it has no default.
ReprovisionServiceInstanceResponse
operation_idThe queued row's id. Poll GET .../operations/{operation_id} with
it until status leaves pending/processing.
service_instance_idRequestPortAllocationRequest
protocolinternal_portRequired when match_port is false. Ignored when it is true.
match_portResetPasswordRequest
passwordtokenResizeBillingResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, subtotal_cents, tax_cents +2 more | |
| type = object · requires: kind |
currencykindsubtotal_centstax_centstotal_centsResizeDimensionResponse
availableWhether stock currently allows this dimension's growth. Always true
for a dimension that is not growing. This is a live read, taken with
no hold and no lock, so it can change by the time POST .../resize
is called -- the authoritative answer is that call's own refusal, not
this field.
currentdimension"cpu", "memory" or "storage".
growingWhether this dimension is increasing (billed now). A dimension whose
requested is below current shrinks at downsize_applies_at; the
same request may do both on different dimensions.
requestedResizeInvoiceResponse
amount_centscurrencyidstatusResizePlanChangeRequest
plan_idResizePolicyKindResponse
Mirrors the domain [ResizePolicyKind] discriminator (ZC-1481) as its
own /v2 response type -- same rule and reason as [PurchaseStepResponse]
below: a domain rename must be a deliberate, matching edit here rather
than a silent wire-format drift.
ResizeQuoteRequest
The target shape a resize names, in the same units CheckoutResourcesRequest
already uses -- see that type's own doc comment. A resize always names a
full target shape, not a delta: the dimension a customer does not want
to change is simply sent at its current value. Any of the three may change
in the same request, each up or down (storage only up); a request replaces
any reduction scheduled earlier, so send a scheduled dimension at its
scheduled value to keep it.
ResizeQuoteResponse
downsize_applies_atWhen the shrinking dimensions take effect: the end of the current billing period, right before the next renewal is priced at the smaller shape. null when nothing shrinks.
ResizeRequest
The target shape a resize names, in the same units CheckoutResourcesRequest
already uses -- see that type's own doc comment. A resize always names a
full target shape, not a delta: the dimension a customer does not want
to change is simply sent at its current value. Any of the three may change
in the same request, each up or down (storage only up); a request replaces
any reduction scheduled earlier, so send a scheduled dimension at its
scheduled value to keep it.
ResizeResourcesRequest
cpumemory_gbMemory in GiB, fractional (0.5 = 512 MiB)
storage_gbStorage in GiB.
ResizeResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: outcome, invoice | |
| type = object · requires: outcome, scheduled_downsize |
A minimal, self-contained invoice summary for a resize response --
deliberately not the full InvoiceResponse from kernel-http-v2-billing
(a cross-crate dependency this feature crate does not otherwise carry):
enough for a client to know what it owes and pay it through the existing
invoice-id-keyed payment endpoints, nothing more.
outcomeResolvedJarResponse
titlegame_versionsloadersproject_idproject_slugversion_numbericon_urlResourceKindResponse
Mirrors ProvisionKind 1:1, kept as its own /v2 response type so this
crate's wire format cannot drift silently if a variant is ever renamed on
the domain enum without a matching, deliberate wire change here -- the
same convention kernel_http_v2_catalog::contracts::products:: ProductFamilyView already follows for ProductFamily (the retired
ProductKindResponse, which used to follow it for CatalogServiceKind,
was deleted alongside that enum, A2-S13d).
ResourceLifecycleTransitionResponse
kinddeployment or virtual_machine: the only kinds that have a power
state.
The recorded status before the verb.
resource_idThe same id GET /subscriptions/{id}/resources and the status stream's
frames carry, so a client can match this entry to the row it renders.
The recorded status the verb left in its place: running for a start,
stopping for a stop (the settled suspended arrives later on the
status stream), and for a restart the same as previous_status,
because a restart cycles the workload without changing what it is
meant to be doing. A restart of a stopped service does not turn it on,
and saying running here would claim it had.
ResourceLogsResponse
containerThe container these lines came from. Always populated, including when the request named none and the workload runs exactly one.
containersEvery container on this workload's current pod, so a panel can offer a container picker without a second call. A workload with one container yields one entry, and a panel should render no picker for it rather than a select with a single option.
coverageKernel's own sentence about what was actually read, to be shown
beside the results rather than paraphrased or composed in the browser
(R2).
It exists because of one specific way this endpoint can mislead: there is no log store on this platform, so a search covers only the window node log rotation still holds. A customer searching for a line that scrolled out of that window must be told what was searched, not shown an empty result that reads as "it never happened".
Oldest first, which is reading order for a log.
truncatedtrue when the read hit its own bounds, so more output exists on either
side of what was returned.
next_cursorHand this back as cursor to continue forwards from where these lines
stopped. Opaque: its spelling may change.
searchEchoed back so a client can tell a response to its current filter from a late response to the previous one.
ResourceMetricsResponse
coverageKernel's own sentence about what was actually read, to be shown
beside the charts rather than paraphrased or composed in the browser
(R2). The same field, for the same reason, as
[ResourceLogsResponse::coverage] -- named precisely because
00-program.md 15.3.1 calls it LogSearchResponse, which does not
exist, and a citation drift is how the next reader loses ten minutes.
It exists because of one specific way this endpoint misleads. Every
window returns [METRIC_BUCKETS] buckets whether or not anything was
sampled, so a resource with no samples at all comes back as four series
of sixty nulls -- four empty axes, no summary, and nothing said. A
consumer cannot tell that apart from a workload that was genuinely
stopped for the whole window, and it must not try: deciding which from
the points is exactly the reduction R2 forbids.
So kernel says which it is. The distinction the sentence carries is "no sample was stored" versus "usage was zero", and only the server knows it.
fromStart of the first bucket.
resolution_secondsBucket width, in seconds. (to - from) / resolution_seconds is the
length of every points array in series.
toEnd of the window. Exclusive: no bucket contains it.
window_minutesThe window actually served, echoed so a client can tell what it got without re-deriving it from its own request.
ResourceResponse
created_athiddenWhether this resource is hidden from a customer-facing resource list by convention today (sidecar provisions). Exposed rather than filtered out, so this surface never silently drops a resource the caller might reasonably expect to see accounted for.
idis_declared_primaryWhether this is the one resource this subscription's product family declares as primary (its ProductDefinition.primary_role), falling back to the legacy is_primary flag only for the families that declare no primary role at all (design doc §9.1). At most one resource in this response ever has this set to true.
kindMirrors ProvisionKind 1:1, kept as its own /v2 response type so this
crate's wire format cannot drift silently if a variant is ever renamed on
the domain enum without a matching, deliberate wire change here -- the
same convention kernel_http_v2_catalog::contracts::products:: ProductFamilyView already follows for ProductFamily (the retired
ProductKindResponse, which used to follow it for CatalogServiceKind,
was deleted alongside that enum, A2-S13d).
roleThe resource's own declared role (e.g. "server", "sidecar",
"sftp", "namespace"). Backfilled from is_primary for rows that
predate this column -- see Resource::role's own doc comment.
updated_atResourceStatusFrameResponse
Per-container status for a Deployment's pod. Omitted, not empty, for every non-Deployment resource and for any Deployment the kernel could not reach inside the bounded timeout -- an empty array would claim the pod has no containers.
created_athiddenWhether this resource is hidden from a customer-facing resource list by convention today (sidecar provisions). Exposed rather than filtered out, so this surface never silently drops a resource the caller might reasonably expect to see accounted for.
idis_declared_primaryWhether this is the one resource this subscription's product family declares as primary (its ProductDefinition.primary_role), falling back to the legacy is_primary flag only for the families that declare no primary role at all (design doc §9.1). At most one resource in this response ever has this set to true.
kindMirrors ProvisionKind 1:1, kept as its own /v2 response type so this
crate's wire format cannot drift silently if a variant is ever renamed on
the domain enum without a matching, deliberate wire change here -- the
same convention kernel_http_v2_catalog::contracts::products:: ProductFamilyView already follows for ProductFamily (the retired
ProductKindResponse, which used to follow it for CatalogServiceKind,
was deleted alongside that enum, A2-S13d).
roleThe resource's own declared role (e.g. "server", "sidecar",
"sftp", "namespace"). Backfilled from is_primary for rows that
predate this column -- see Resource::role's own doc comment.
updated_atPresent while the workload is stalling on memory reclaim, or was recently. Absent for a healthy workload and on kubelets that do not report memory PSI, so absence means "unknown", not "healthy".
CPU, memory and uptime as the cluster reports them right now. null
for a resource with no such reading: anything that is not a Deployment,
a Deployment with no running pod, and any resource at all while the
cluster is unreachable.
ResourceStatusResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
ResourceUsageResponse
cpu_millicoresmemory_bytesuptime_secsRestrictionResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, available_cents, required_cents | |
| type = object · requires: kind, available_cents, floor_cents | |
| type = object · requires: kind, open_receivable_cents, credit_limit_cents | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind |
available_centskindrequired_centsRevealedEnvironmentSecretResponse
keyvalueRevealedSetupPasswordResponse
idvalueRolloutStatusResponse
replaced_unitsRunning units already on the target template.
stale_unitsRunning units still on an older template.
started_atHow a template change reaches the units. Phase 1 has rolling; phase 2 adds
replace_idle and next_start (plan 3.5), whose selection rules are P2-K8's:
until it lands they are stored and validated, and roll as rolling does.
target_templateThe template the units are moving to, an opaque fingerprint.
The stale units replace_idle waits on, each with why.
RolloutStrategy
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
RolloutWaitingOnResponse
keywhyallocated: replaced when it exits, stops or is destroyed. busy: replaced at its
next idle.
RotateSetupPasswordResponse
What landing the rotation cost the running service. Always restart
in slice 1c (see [kernel_core::domain::setup_steps::apply_mode]'s
own doc comment: any change to any setup step's answers is
Restart), carried as the same typed value the other setup-step
responses use rather than hardcoding the string here.
idpendingTrue when the rotation was saved but the reprovision attempt itself
failed. The same pending vocabulary every other setup-step and
capability write already uses.
RoutingRuleResponse
order1 is evaluated first: the highest priority.
priorityruleThe rule exactly as the ingress evaluates it.
Whether a rule can serve.
strip_prefixpathThe path prefix, absent for the default rule that answers everything else.
shadowed_by_pathFor a shadowed rule, the path of the rule that shadows it (absent when that is the
default).
RoutingSampleResponse
pathupstream_pathThe path the target receives, after any strip.
winning_orderThe order of the rule that takes it.
RoutingStateResponse
How the domain's certificate and route are doing.
RoutingTargetResponse
endpoint_idservice_instance_idservice_nameWhat a rule's target is doing.
RoutingTlsResponse
statusOne certificate covers the whole domain, whatever its paths.
RoutingUsedByResponse
servesThe paths it serves; / is the default.
RuleStatusResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
RunOutcomeResponse
The six, and only six, terminal answers to "what happened to this run". See this module's header for the seventh, unwritten in-flight state.
RunResponse
created_atidWho or what caused a run to be decided.
exit_codefinished_atnull until the run concludes, and always null for a skip.
log_object_keyA pointer to this run's captured log, if one was captured. null
today: log capture is a later slice.
null exactly while a fired run is in flight: decided, not yet
concluded. See this module's header -- do not treat this as a status
string with a seventh "running" value.
peak_cpu_millicorespeak_memory_bytesscheduled_forWhen this run was due. null for a manual trigger, which has no due
time by construction.
skip_reasonWhy a run was skipped or missed. null for one that fired.
started_atnull for a run that was skipped, or one that has not started yet.
termination_reasonThe Kubernetes termination reason, e.g. OOMKilled. null unless the
run concluded abnormally.
RunSnapshotResponse
commandimage_digestschedule_cron_expressionschedule_timezonetimeout_secondsRunTriggerResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind | |
| type = object · requires: kind, triggered_by_user_id |
kindschedule_idRuntimeConfigResponse
One startup value beside the one the image itself declares.
One startup value beside the one the image itself declares.
Kernel's verdict for the deploy commands, which is genuinely different: a pre-deploy command cannot be picked up by a restart, because a restart is not a deployment.
image_defaults_availableFalse when the registry could not be asked at all.
Kernel's verdict for the startup fields, which share one.
stop_signalsThe signals a customer may choose. Closed, because the platform decides, and supplied rather than hardcoded in the client for the same reason a region is never free text.
Empty today, and that is the honest answer rather than an oversight:
there is no signal the platform can deliver but SIGTERM. A panel
renders no options and therefore offers no choice, which is exactly
the state of the world.
One startup value beside the one the image itself declares.
Whether the running container is still started the old way, and which
act would pick the new configuration up. null when nothing is
outstanding.
Same meaning and same reason as
[EnvironmentVariableResponse::pending]: a save that could not be
re-rendered is still a save, and the panel has to be able to say so.
post_deploy_commandpre_deploy_commandstop_grace_period_secondsAlways null today, meaning the platform's own 60 seconds.
stop_signalAlways null: the kubelet always sends SIGTERM and a pod spec
cannot override an image's STOPSIGNAL.
RuntimeOptionDto
default_start_commandidinstall_commandlabellabel_keystart_command_presetsdescriptiondescription_keyiconRuntimeOverrideResponse
image_defaultWhat the image declares.
null means "the image declares nothing" only when
[RuntimeConfigResponse::image_defaults_available] is true. When that
flag is false it means the registry could not be asked, which is a
different statement and must not be rendered as the first one.
valueThe customer's value. null means the image's own is used.
RuntimeStatsBatchResponse
RuntimeStatsEntryResponse
cpu_millicoresmemory_bytesservice_instance_iduptime_secsRuntimeVariantDto
idimagelabellabel_keydescriptiondescription_keySalesChannelQuery
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
ScalingAction
What the evaluator (or a policy change) did about the unit count. Stored as text and constrained in SQL to the same four words.
ScalingDecisionResponse
actionWhat the evaluator (or a policy change) did about the unit count. Stored as text and constrained in SQL to the same four words.
atfrom_unitsidinputsWhat the decision was made from (samples and bounds), as the evaluator recorded them. Its shape is not a contract.
last_atWhy. Stored as text and constrained in SQL to the same words. The last
two (policy_change, rollout_paused) are not the evaluator's: the first
is a customer's PATCH moving a fixed count, the second is the rolling
rollout pausing itself.
repeat_countsummaryOne sentence saying what happened and why ("Scaled 2 to 4: CPU at 83% against a 60% target"), composed by the kernel from the row so clients show words they did not assemble.
summary_codeWhich sentence summary is, <action>.<reason> such as scale_up.cpu_high.
The figures in it (from, to, and used/target/min/max when recorded), for a
client that words the sentence itself.
to_unitsScalingMarkerKind
What a marker on the count chart says happened.
ScalingMode
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
ScalingPolicyQuoteResponse
cap_bindsThe spend cap is what limits monthly_cents.
extra_unitsUnits above the plan's included ones, at the policy's ceiling.
hourly_centsWhat one extra unit costs for one hour, in cents.
meteredThe Price meters extra units. When false every amount is zero.
minimum_billed_secondsEach extra unit start bills at least this long.
minimum_start_centsWhat one extra unit start bills at that minimum, in cents.
monthly_centsThe most the policy can cost in a month, in cents: the worst case held to the cap.
worst_case_centsEvery extra unit running all month, before the spend cap, in cents.
worst_case_hoursHours of extra-unit time the worst case bills (every extra unit, the longest month).
ScalingPolicyResponse
contract_versioncode: what a unit does when its process exits, unless it was created with
its own. Always restart in the other modes.
destroy_stopped_after_daysA stopped unit of the customer's code is destroyed after this many days.
max_unitsmin_unitsWhether the number of units is a constant or follows load and the clock. Stored as text and constrained in SQL to the same two words.
auto: the phase-1 readiness; signal: Ready only once the unit signals it.
ready_timeout_secondsA unit not Ready this long after its pod started is failed (units that carry the agent only).
How a template change reaches the units. Phase 1 has rolling; phase 2 adds
replace_idle and next_start (plan 3.5), whose selection rules are P2-K8's:
until it lands they are stored and validated, and roll as rolling does.
scale_down_stabilisation_secondsscale_up_cooldown_secondsBounds overrides that take effect when their cron expression fires and hold until the next rule fires.
updated_atcpu_target_percentdrain_idle_after_secondsautoscaled: a unit idle this long may be drained while above the minimum.
code: what happens to a unit idle for idle_after_seconds.
idle_after_secondskeep_acceptingautoscaled: keep this many units accepting beside the ones that say they
are full.
memory_target_percentPresent while a template change is still reaching the units; absent once every
running unit is on the current template. Only GET reads it.
spend_cap_centsThe most, in cents, the extra units may cost in a month before scaling refuses to grow. Absent means the worst case the maximum allows.
warm_unitscode: ready, unallocated warm units kept on top of the others. Absent in
the other modes.
ScalingReason
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
ScannerSubscriptionOwnerResponse
display_nameidemailThe owner's primary email (OAuth first, password credential as
fallback), or null when none resolves.
ScannerSubscriptionPeriodResponse
ends_atstarts_atScannerSubscriptionResponse
created_atdisplay_nameThe organization's name, with a distinct owner's name in parentheses.
idThe subscription id, which is the tenant key.
product_idproduct_slugstatusnull when the subscription is not billing (pending or ended).
null when the organization has no owner left.
ScannerSubscriptionStatusRequest
Request-side twin of [SubscriptionStatusResponse]; /v2 keeps
Deserialize and Serialize on distinct enums.
ScheduleActionResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind | |
| type = object · requires: kind, tasks |
kindScheduleConditionResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: condition, starts_at, ends_at | |
| type = object · requires: condition, excluded_dates | |
| type = object · requires: condition, requires, within_seconds | |
| type = object · requires: condition, url | |
| type = object · requires: condition, schedule_id, within_seconds |
conditionends_atstarts_atScheduleResponse
What each fire does.
created_atcron_expressionidinvalidtrue when the stored schedule no longer validates (for example its
time zone is no longer known): it cannot fire until it is edited.
Every other field is the stored value as it is.
nameThe three concurrency policies a schedule may declare. Mirrors
[OverlapPolicy] one for one; see this module's header for why it is not
reused directly.
pausedtimeout_secondstimezoneupcoming_fire_timesThe next few fires after now (at most [UPCOMING_FIRE_TIMES]), in UTC;
empty while paused. The same computation the scheduler runs, so what is
shown is what will happen, daylight-saving changes included.
updated_atinvalid_reasonWhy the schedule is invalid; null when it is valid.
next_fire_atThe next instant the kernel's scheduler will fire this schedule, in UTC.
null while the schedule is paused or invalid, or when the expression never
matches again.
ScheduleRule
cronFive-field cron expression, numeric fields only.
max_unitsmin_unitstimezoneIANA zone name the expression is read in.
ScheduleTaskResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, command | |
| type = object · requires: kind, entrypoint | |
| type = object · requires: kind, action | |
| type = object · requires: kind | |
| type = object · requires: kind, seconds |
commandkindtimeout_secondsSeconds the command may take. Defaults to 300; at most 3600.
ScheduledDownsizeResponse
applies_atWhen it takes effect, right before the next renewal is priced.
idcpuThe vCPU it lowers the service to, or null if cpu is unchanged.
memory_gbThe memory in GiB it lowers the service to, or null if memory is unchanged.
ServerImportListResponse
ServerImportResponse
bytes_transferredcancel_requestedThe customer asked to stop. The import is still running until it moves
to cleaning_up, then cancelled.
created_atdelete_extraneousfiles_transferredhostidremote_pathWhere an import is.
target_pathThe directory in the service the files are copied into.
updated_atusernamebytes_totalcompleted_atcurrent_fileThe file being copied now, when the transfer has reported one.
errorWhy the import failed, in words a customer can act on.
files_totalportprogress_percent0 to 100, by bytes when the total is known, otherwise by files.
ServerImportStatusResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
ServerPasswordsParamsDto
ServerPasswordsRequestDto
ServerPasswordsResponseDto
ServiceInstanceActivityEntry
actionactor_is_staffTrue when a Zaroz staff account did this on the customer's service. The
staff member's identity (principal_id, principal_name, token and
sponsor) is withheld, so the customer sees only that it was staff.
created_atidprincipal_kindUser, Application, or System.
api_token_idapi_token_nameprincipal_idprincipal_nameproject_idservice_instance_idsponsor_application_idsponsor_application_nameServiceInstanceAvailabilityResponse
Whether this row's platform can currently be reached to answer a live
status question -- see MyServiceInstanceSummaryResponse::availability's
own doc comment for exactly what this does and does not mean.
ServiceInstanceFeatureResponse
idServiceInstanceFeaturesResponse
ServiceInstanceLifecycleActionResponse
Mirrors ServiceInstanceLifecycleAction 1:1, kept as its own /v2
response type for the reason ResourceStatusResponse is: a rename on the
domain enum must not silently change a wire value.
ServiceInstanceLifecycleResponse
actionThe verb that ran. Echoed so a client holding several in-flight answers, or a log of them, needs no request to interpret one.
Every workload the verb acted on, in the order it acted. Never empty: an instance with nothing to act on is refused with a 422 instead. More than one entry only when a product's blueprint produces several switchable primaries, all of which a lifecycle verb switches together.
service_instance_idServiceInstanceOperationResponse
attemptskindThe operation's own wire kind, e.g. "service_instance_reprovision".
A plain string rather than a closed response enum: this route is
generic over every kind the Provisioning queue ever carries, not
reprovision-specific, and a new kind must not need a new response
type to be readable through it.
max_attemptsoperation_idservice_instance_idstatusMirrors kernel_domain::domain::operations::OperationStatus 1:1, kept as
its own /v2 response type for the reason every other mirrored enum in
this file is: a rename on the domain enum must not silently change a wire
value.
completed_atSet once status reaches completed. Still None for
dead_letter: exhausting the retry budget is not a completion, and a
client polling for a timestamp here would wait forever on a row that
has already stopped trying.
last_errorA fixed step code ("unroutable:keep_data", "provision", ...),
never a provider or database error string -- see
ProcessOperationError::step (kernel-tasks), which is what writes
this column. None while the operation has never failed an attempt.
ServiceInstanceResponse
created_atidnameproject_idThe project this service is addressed under. Its slug is unique here, not platform-wide.
How much CPU, memory and storage this service is currently configured with (ZC-1287). The same shape MyServiceInstanceSummaryResponse carries per row, published here because until now it was carried ONLY there -- on the route that returns every service the caller owns. A client that wants one service's size had to page the caller's whole inventory to find three numbers, and that listing filters by project_id only, so there was no way to ask about one. That blocked the resize screen, whose form has to open showing what the customer already has. This is the configured shape, which is what the customer bought and what a resize names a full target against -- not a live measurement of what the workload is using. GET .../resources/{resource_id}/volume is where a measurement lives.
slugsubscription_idupdated_atSet only while the debt ladder holds this service stopped (V-0482): own_debt when its organization has an unpaid balance, restricted when it is frozen because of a debt elsewhere (contact the organization's owner). null otherwise, and always null on routes other than GET ./service-instances and GET ./service-instances/{id}. Never identifies the debtor.
operating_system_idFor a VPS, the id of the operating system it runs, as listed by GET /api/v2/catalog/products/{id}/operating-systems (V-0671). A client uses it to offer only reinstall targets with the same monthly fee. null for every other service.
This subscription's pending resize (ZC-1332), or null when there is none. GET .../service-instances/{id} is the only route that populates this -- every other route returning this same shape (rename, reprovision, ...) always answers null here rather than resolving it, since none of them has a reason to.
ServiceInstanceSetupResponse
awaiting_configurationTrue while provisioning is still waiting for a configuration. A service in this state has been paid for and has no workload running.
service_instance_idServiceInstanceSetupStepOptionsResponse
degradedTrue when the upstream this field's provider depends on (Mojang,
Forge, NeoForge, Modrinth, or FTB) could not be reached and options
is either stale or empty. Never a reason by itself to refuse a save
-- see [AnswerSetupStepResponse]'s own admission behaviour.
cached_atWhen the underlying data was last fetched from the upstream, or
null when nothing could be served at all (a fully degraded, empty
result).
ServiceInstanceSetupStepResponse
One declared step's params, typed and tagged by step -- ZC-1379 slice S3
replaces GET .../setup/steps' previous raw
[serde_json::Value] with this, mirroring [StepParams] by hand so
dashboard's generated types carry a real shape for every step's params
(docs/superpowers/specs/2026-09-25-setup-steps-shared-steps-plan.md
§2.4) instead of an opaque blob. Tagged exactly like [StepAnswers]
itself: {"step": "app_runtime", "params": {...}}, or {"step": "none"}
for a step that reads none (every param-less step collapses to the same
None shape here, the same way [StepParams::None] does on the domain
side -- which step this is at all is already the parent
[ServiceInstanceSetupStepResponse::step]'s job, not this type's).
The closed vocabulary of setup steps kernel knows how to ask, validate and
render. Adding a member is a reviewed code change here, in the dashboard's
step registry, and in whichever product template starts reading its
variables -- the same "closed set, matched code change" discipline
[crate::domain::product_definitions::capabilities::CapabilityId] uses,
for the same reason: a step nothing implements is a claim the platform
cannot back.
Ord is derived so this can key a BTreeMap
([StepAnswersDocument::steps]): declaration order becomes iteration
order there, which is incidental (the document is always looked up by
key, never walked in order) but harmless.
null when this step has not been answered yet.
ServiceInstanceSetupStepsResponse
awaiting_configurationWhether provisioning is still waiting on at least one of these steps. A product declaring no steps is never awaiting one.
ServiceInstanceStatusEventResponse
Which of the product's declared [Capability::Lifecycle] verbs make
sense to click right now (ZC-1154): the console renders that
static list as its full set of buttons (a stopped container still
offers Stop, greyed, because the workload kind supports it), and
this is the subset that should render live. It never adds a verb the
static list omits.
The intersection of three independent answers, all required:
- the product's declared
Capability::Lifecycleverb list (what the workload kind supports at all, structural, read off its own resources); - [
kernel_core::domain::provisions::ServiceRuntimeState::permits_lifecycle_verb] (whether the verb does something sensible given the workload's live condition --stateabove, converted); and - [
SubscriptionStatus::permits_lifecycle_verb] (whether the customer is commercially entitled to ask for it right now).
A verb missing from any one of the three is not permitted. This is
deliberately a new field and state is unchanged: the frontend
entitlement decision console/components/apps/bg-status-vocabulary.ts
tried to own client-side is a decision this list now makes instead,
but console still needs both fields -- one to render the full,
disabled set, one to know which of them are live -- and adding a
field to an SSE payload is backward compatible where removing state
would not be.
The instance's visible resources. Empty is normal: a per-seat licence
provisions none (design doc §8.1), and so does an instance whose
workloads have not been applied yet, which is what state: NotProvisioned says.
stateOne word for the whole service, folded from its primary workloads' statuses (or, when it declares none, from all of them).
Live crash detail while state is CrashLooping. Absent otherwise,
and absent while crash looping if the cluster could not be reached
inside the bounded timeout.
Live startup-failure detail while state is Failed because the
workload never started (e.g. an image whose declared user cannot be
verified non-root). Carries the kubelet's own reason and message so a
customer is told why rather than left on a perpetual "Starting".
The in-guest first-boot gate, where the product has one (a Windows
VPS). null means there is no gate, not that the guest is not
ready: a consumer treating absence as "not ready" would never show a
Linux service as usable.
The operation kernel is currently carrying out against this service,
if any (ZC-1162). null is the common case: nothing is happening.
This is the field that answers "is a deploy happening right now",
which state cannot: state: Provisioning does not distinguish a
first-time bring-up from an in-place redeploy or reprovision, and a
rolling update leaves the old pods serving, so state stays Running
for the whole deployment and never signals anything happened at all
(found while building ZC-1154). Kernel already tracks this fact as a
typed, leased operation (kernel_core::domain::service_operations);
this is that fact surfaced, not a new one invented for the stream.
A new field, like permitted_lifecycle_verbs above and for the
same reason: adding a field to an SSE payload is backward compatible,
changing state is not.
ServicePrincipalResponse
Each live copy, lowest slot first.
copies_totalHow many live copies the service has.
copies_with_keyHow many of them carry the mounted key already.
created_atidservice_instance_idThe service the principal is the identity of.
ServiceResourceRefResponse
hiddenA hidden helper (sidecar) that a customer-facing list normally omits.
idkindMirrors ProvisionKind 1:1, kept as its own /v2 response type so this
crate's wire format cannot drift silently if a variant is ever renamed on
the domain enum without a matching, deliberate wire change here -- the
same convention kernel_http_v2_catalog::contracts::products:: ProductFamilyView already follows for ProductFamily (the retired
ProductKindResponse, which used to follow it for CatalogServiceKind,
was deleted alongside that enum, A2-S13d).
roleThe resource's declared role ("server", "sidecar", "sftp", ...).
ServiceResourceRefWithPrimaryResponse
hiddenA hidden helper (sidecar) that a customer-facing list normally omits.
idis_declared_primarykindMirrors ProvisionKind 1:1, kept as its own /v2 response type so this
crate's wire format cannot drift silently if a variant is ever renamed on
the domain enum without a matching, deliberate wire change here -- the
same convention kernel_http_v2_catalog::contracts::products:: ProductFamilyView already follows for ProductFamily (the retired
ProductKindResponse, which used to follow it for CatalogServiceKind,
was deleted alongside that enum, A2-S13d).
roleThe resource's declared role ("server", "sidecar", "sftp", ...).
ServiceRunStateResponse
Mirrors ServiceRunState 1:1, kept as its own /v2 response type so the
wire format cannot drift silently if a variant is renamed on the
application enum -- the convention contracts::resources's own
ResourceStatusResponse already follows for ProvisionStatus.
ServiceSharePermission
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
ServiceShareResponse
created_atemailidservice_instance_idstatuspending until the grantee opens the share in their own list, then accepted.
updated_atavatar_asset_idThe member's avatar asset (/assets/{id}); null until accepted or when they have none.
usernameThe member's username; null until the share is accepted.
ServiceShareStatusResponse
Where a share stands: pending until its grantee opens it in "Shared with me", then
accepted.
SessionResponse
refresh_tokensession_idtokenMinimal caller identity carried on a session payload.
Deliberately not the full /console/me shape
(kernel_http_v2_identity::contracts::me::MeResponse): /v2 feature
crates do not depend on one another (see crates/http/CLAUDE.md), so
this is a small, independent projection sized for what a session
response needs, not a shared type.
SetAvatarSourceRequest
provider_idThe id of an OAuth provider the caller has already linked an account with. Must have a stored avatar (the provider returned one at some login).
SetBillingCountryRequest
country_codeTwo-letter country code, e.g. ES. Case-insensitive.
SetDomainPathsRequest
SetEnvironmentVariableRequest
secretMoving a variable between plain and secret is this same request with a different value here.
valueAbsent or null means keep the stored value, and is accepted only
for a secret that is already stored and is staying secret: those are
the only rows the client was never shown. Anywhere else it is a 400,
never an empty string.
SetInitialPasswordRequest
new_passwordSetRegistrySourceRequest
hostghcr.io, docker.io, registry.example.com:5000.
repositoryacme/worker. A single-segment repository on Docker Hub is qualified
with library/ by kernel, so a customer types nginx.
tagThree states, and two would not be enough.
| Body | Meaning |
|---|---|
| field absent | leave the stored credentials alone |
null | clear them, pull anonymously |
{ username, password } | replace them |
An Option that is None would have to mean either "unchanged" or
"clear", and whichever it meant, the other would be unreachable from a
panel that is never shown the password it would otherwise resend.
watch_tagAccepted so a client that sends it gets an answer rather than silence,
and refused when true. See [SourceResponse::watch_tag].
SetSourceRequest
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: host, repository, tag +1 more | |
| type = object · requires: kind | |
| type = object · requires: kind | |
| type = object · requires: kind |
kindhostghcr.io, docker.io, registry.example.com:5000.
repositoryacme/worker. A single-segment repository on Docker Hub is qualified
with library/ by kernel, so a customer types nginx.
tagThree states, and two would not be enough.
| Body | Meaning |
|---|---|
| field absent | leave the stored credentials alone |
null | clear them, pull anonymously |
{ username, password } | replace them |
An Option that is None would have to mean either "unchanged" or
"clear", and whichever it meant, the other would be unreachable from a
panel that is never shown the password it would otherwise resend.
watch_tagAccepted so a client that sends it gets an answer rather than silence,
and refused when true. See [SourceResponse::watch_tag].
SetSubscriptionCancellationRequest
cancel_at_period_endtrue to stop this subscription at the end of the period already
paid for, false to withdraw a scheduled end and keep it running.
effective_immediatelyStaff only (ZC-0747). true ends the subscription now instead
of at the close of the paid period: cancels_at is written at the
present instant, which the reaper takes on its next tick.
Defaults to false, so a customer's request means exactly what it
meant before this field existed and a staff member who does not ask
for it gets the same safe answer. Sending true without the staff
system permission is 403; sending it alongside
cancel_at_period_end: false is 422, because withdrawing an end and
taking one now are contradictory instructions rather than a pair.
It is not withdrawable afterwards, by anyone. The moment has
passed by the time any later request arrives, and a passed deadline is
refused -- which is /v1's "cancelled by an administrator and cannot
be reinstated", reached through the deadline rather than the status.
SetSubscriptionRenewalRequest
auto_renewtrue to be charged again when the current period ends, false to
stop after it.
SetupOptionDto
labelvaluedetailSetupStepAnswersDto
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers |
SetupStepId::MinecraftSoftware's
answers.
stepSetupStepAnswersResponseDto
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers | |
| type = object · requires: step, answers |
SetupStepId::MinecraftSoftware's
answers.
stepSetupStepId
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
SetupStepParamsDto
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: step | |
| type = object · requires: step, params | |
| type = object · requires: step, params | |
| type = object · requires: step, params | |
| type = object · requires: step, params | |
| type = object · requires: step, params | |
| type = object · requires: step, params | |
| type = object · requires: step, params | |
| type = object · requires: step, params |
stepSftpConnectionResponse
enabledWhether the account is currently reachable.
usernameThe single account name every SFTP deployment is provisioned with.
hostnull when the account's public port has not resolved yet (a
placement fault, or the external allocation is still landing) --
the read itself still succeeds, the same rendering
CustomDomainsResponse.platformHost uses for the same situation.
portSftpCredentialResponse
enabledpasswordThe new password. Shown here once; it is never returned by a subsequent read.
usernamehostportSharedDatabaseColumnView
column_typedata_typeextranamenullableordinal_positionprimary_keydefault_valueSharedDatabaseEntitlementResponse
heldActive databases the subscription holds now. A real count.
limitThe entitlement: 10.
quota_bytes_eachEach database's quota in bytes: 67108864 (64 MiB).
remaininglimit - held, never below zero.
SharedDatabaseRegionAvailabilityView
country_codeengineregion_idregion_nameregion_slugSharedDatabaseRegionsResponse
SharedDatabaseResponse
SharedDatabaseRowsView
columnshas_morelimitpagination_modetablecursor_columnnext_cursorSharedDatabaseSqlResultView
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: kind, columns, rows +1 more | |
| type = object · requires: kind, affected_rows |
columnskindtruncatedSharedDatabaseTableView
nameprimary_keytable_typedata_lengthengineindex_lengthkeyset_cursor_columnrow_estimateSharedDatabaseTransferOperationResponse
allocation_idattemptskind"shared_database_export" or "shared_database_import".
max_attemptsoperation_idstatusMirrors kernel_domain::domain::operations::OperationStatus 1:1, kept as
its own /v2 response type for the reason every other mirrored enum in
this file is: a rename on the domain enum must not silently change a wire
value.
completed_atlast_errorSharedDatabaseTransferStartedResponse
allocation_idoperation_idSharedDatabaseView
created_atdatabasedisplay_nameengineexternal_hostexternal_portidincludedinternal_connection_availableinternal_hostinternal_portpasswordupdated_atusernameover_quota_sincequota_bytesregion_country_coderegion_idregion_nameSharedDatabasesResponse
SharedServiceInstanceResponse
nameowner_nameThe owning organization's display name.
The product a shared service runs, by name.
The service's live resources (id, kind, role, status), which the console, files, logs
and metrics routes are addressed by. Empty when none exist yet. For which one is the
declared primary, call GET /service-instances/{id}/resources.
service_instance_idshare_idshared_atslugstatusThe service's commercial status (active, suspended, ...): a suspended service is
listed, and its capability routes answer 404 until the owner settles it.
SharedServiceProductResponse
idnamenull when the product could not be named.
Source
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: host, repository, tag +1 more |
kindhostghcr.io, docker.io, registry.example.com:5000. Always present:
a reference with no host is normalised to [DOCKER_HUB_HOST] on the
way in, so a reader never has to know the defaulting rule.
repositoryacme/worker, library/nginx. Never carries the host.
tagThe mutable name the customer chose.
credential_usernameThe username half of the stored pull credential. None is an
anonymous pull.
digestThe immutable name of what was actually pulled, when the stored reference pins one.
Always None for anything this platform wrote, because nothing
resolves a tag to a digest for a third-party registry: the only
manifest client in the codebase authenticates with HTTP basic, and
ghcr.io, Docker Hub and Quay all require the Bearer challenge
exchange. Some only for a reference a customer pinned themselves.
SourceArmId
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
SourceResponse
The arms this product permits, in the order it declared them.
A product with exactly one permitted arm renders no chooser at all: a radio group with a single option is a control that asks a question with one answer. Supplied by kernel rather than held as a frontend literal, for the same reason a region list is.
watch_tagWhether the platform re-pulls when the tag moves.
Always false, and that is the honest answer rather than a
placeholder. Nothing polls a registry for a moved tag, so there is no
watcher to turn on; a stored flag would promise a redeploy that never
happens, which 12-source.md §8 names as the failure to avoid and then
asks for anyway. A write that sets it is refused with the reason.
image_referenceThe reference the next deployment will pull, null when nothing has
been chosen.
Composed here rather than in the panel (R2), because the rules that
build it are the platform's: a digest wins over a tag, and Docker Hub's
own images live under library/.
pendingWhether what is running differs from what is saved.
null means kernel could not tell, because the instance's resources
could not be read. That is a third answer on purpose: false would
claim the running workload is up to date, which is a statement rather
than an absence of one.
running_imageThe reference the workload is running right now, read off the
instance's primary resource. null when nothing is deployed.
What this service runs, or null for one that has not been told yet.
null is the panel's empty state and covers a subscription that has
been paid for and never configured. It is not an error and it is not a
broken service.
SpendUsageResponse
current_centsWhat every service of the organization has spent on metered usage this month, in cents.
ok, near (80 percent of the cap or more) or at_limit (growth is refused).
cap_centsThe cap staff set, in cents; absent when there is none and growth is not refused for spend.
SshConnectionDetailsResponse
authorized_key_fingerprintsSHA-256 fingerprints of the public keys the machine was built trusting.
browser_ssh_statusready, enrolling_host_key or unavailable.
commandA ready-to-paste ssh user@host, or empty while there is no host.
hostThe machine's own public address, or empty while it has none.
host_key_fingerprintsSHA-256 fingerprints of the host keys the machine enrolled on first boot: what a client should see on its first connection.
operating_systemAlways linux: the capability is only derived for a Linux guest.
password_auth_enabledportpublic_route_statusready once the public address routes to the machine, else pending.
usernameThe guest account the machine was built with.
SshSessionTicketResponse
expires_insession_idurlwss://<edge>/ssh?ticket=.... Redeemable once, within expires_in
seconds, and only from the dashboard origin it was issued for.
StandingResponse
available_centsbalance_centscredit_limit_centscurrencyfloor_centsopen_receivable_centsrequired_centsreserved_centsrestrictedStartServerImportRequest
hostThe remote server's host name or public IP address. Private, loopback and link-local addresses are refused.
passwordThe remote account's password. Stored encrypted for the length of the transfer and never returned.
usernamedelete_extraneousAlso delete files in the service's data directory that the remote server does not have (a sync rather than a copy). Defaults to false.
portThe remote SFTP port. Defaults to 22.
remote_pathThe directory on the remote server to copy from. Defaults to the account's root.
StartUnitRequest
Replaces the unit's labels whole when given.
user_dataReplaces the unit's user_data whole when given.
StartupFailureResponse
reasonThe kubelet's waiting reason, e.g. CreateContainerConfigError.
messageStaticSiteDto
error_documentindex_documentspa_fallbackSteamBranchDto
branchSteamBranchParamsDto
SteamWorkshopDto
collection_iddownload_collection_idSteamWorkshopParamsDto
collectiondownload_collectionStorefrontCategory
Which storefront shelf a product appears on, authored rather than derived.
Every variant is a console route directory. The seven wire spellings are
exactly the directory names under console/app/[org]/[project]/(document)/,
because console links a product as /{org}/{project}/{category}/{slug}:
| Variant | Wire spelling | Console route directory |
|---|---|---|
Storage | storage | console/app/[org]/[project]/(document)/storage |
Compute | compute | console/app/[org]/[project]/(document)/compute |
Apps | apps | console/app/[org]/[project]/(document)/apps |
Databases | databases | console/app/[org]/[project]/(document)/databases |
ManagedApps | managed-apps | console/app/[org]/[project]/(document)/managed-apps |
ManagedPlatforms | managed-platforms | console/app/[org]/[project]/(document)/managed-platforms |
Registry | registry | console/app/[org]/[project]/(document)/registry |
A category with no matching directory navigates nowhere: the link renders, the click 404s. Adding a variant here therefore requires adding the matching console route directory in the same change, and removing a directory requires removing the variant. That is the whole anti-drift mechanism: this enum reaches the OpenAPI document as a real string enum, admin renders its authoring dropdown from the generated client, and console checks its own route directories against the same generated list.
This is not [CatalogCategory], and does not replace it.
[product_category] derives a category from a product's stored family
and slug, and its fallthrough is blunt: everything that is not a fleet,
a VPS, a container kind or a flat-fee license kind becomes
[CatalogCategory::GameServer], so postgres, object_storage and
static_website all land on one shelf. A v2 product is authored data
(Product + DisplayProfile + ProductDefinition), so its shelf is
authored too, and lives on the display profile alongside the name and icon
it is already presented with. Migrating the derived callers is a later
slice; both answers coexist for now.
SubmitTicketReviewRequest
problem_solvedresolution_speedresponse_qualitycommentSubscriptionCancellationResponse
auto_renewThe renewal setting, untouched by this write and returned so a client can see that for itself. Scheduling an end does not turn renewal off: the billing engine skips every subscription that is not active, so the status alone already stops the next invoice, and leaving this alone is what makes withdrawing the end restore exactly the arrangement that was in force. Change it through PUT /subscriptions/{id}/renewal.
changedWhether this request is what changed the decision. false means it already said this -- a retry, or somebody else deciding the same thing first. Both are successes; a client must not render false as a failure. On a retry the existing cancels_at is returned unchanged: a repeated request never moves the customer's end date.
statusThe subscription's commercial status, which this write does move
-- unlike the renewal decision beside it. pending_termination after
scheduling, active after withdrawing.
subscription_idcancels_atWhen this subscription stops. Non-null exactly when status is pending_termination: the two are written in one statement and cannot disagree. Ordinarily it is the close of the billing period the subscription is currently in, computed from its own anchor and cadence, so it is the same instant the renewal invoice would otherwise have been raised. For a staff cancellation sent with effective_immediately it is the present instant instead. Until this moment passes the decision can be withdrawn by sending cancel_at_period_end: false; after it, it cannot.
SubscriptionHardwareProfileResponse
idnameSubscriptionRegionResponse
country_codeISO 3166-1 alpha-2 code of the region's country (ES, FI), for the flag.
idnameSubscriptionRenewalResponse
auto_renewchangedWhether this request is what changed the setting. false means it already said this -- a retry, or somebody else deciding the same thing first. Both are successes; a client must not render false as a failure.
statusThe subscription's commercial status, unchanged by this write.
Returned so a client can see that for itself rather than take it on
trust: turning renewal off is not a cancellation, and an Active
subscription is still Active afterwards.
subscription_idcancels_atWhen this subscription is scheduled to end. Unchanged by this route, which is why it is returned: turning renewal off is not a cancellation, and a client can see here that no end was scheduled. It is non-null only for a subscription somebody scheduled to end through PUT /subscriptions/{id}/cancellation, which is the only writer of this field.
SubscriptionResponse
anchor_atauto_renewcadence_monthsThe billing period this subscription renews on -- distinct from the
pinned Price's own cadence_months (the period its rates are quoted
per). See price.cadence_months and design doc §3.4, "cadence_months
appears on both prices and subscriptions".
created_atidorganization_idThe Price this subscription is pinned to -- what it renews at. Always the pinned Price's own stored rates, never a fresh selection: design doc §3.4.2 guard rail 1 reserves resolve_acquisition_price for a brand-new purchase, and a subscription's renewal reads its own price_id, never that resolver. The figures below are the Price's stored price_lines verbatim -- no discount, proration, or reseller multiplier is applied, so this can never show a number that does not exist in the pinned row.
product_definition_idproduct_idproject_idThe project this subscription belongs to (§34.1's
Organization -> Project -> Subscription -> Resource).
Always present. The link is NOT NULL in the schema, so there is no
"not yet attributed" case for a reader to handle.
quantitystatusactivated_atcancels_atThe hardware profile this subscription's workload runs on, by name. null under the same conditions as region.
internal_addressThe bare, human-readable Kubernetes Service name for this subscription's internal ClusterIP endpoint (design doc docs/V2Plan/111-internal-naming-and-region.md §7.2) -- e.g. postgres, never the FQDN and never the s-{uuid} form (§7.3). null is the correct, common answer, not a disabled state: it means no provisioned ClusterIpService exists yet for this subscription, or its slug does not qualify as a DNS-1035 label (a leading digit -- Slug::parse allows one, Kubernetes does not). A null must not be read as "this address is unreachable": absence here says only that there is no name to offer at all. Reachability from elsewhere is a separate, pairwise question this field does not answer by itself (§7.1) -- compare region below against the region of whatever would be connecting to it (e.g. the subscription that owns the field this value would be pasted into); the two share a Kubernetes cluster only when their regions match. Kernel does not compute or return that verdict directly, since a single subscription's own read never holds both sides of the comparison.
parent_subscription_idZC-0984: the bundle this subscription is a member of, or null for
a bundle itself and for every ordinary, standalone subscription.
The region this subscription's workload is placed in. null before a hardware profile has resolved (never yet activated, or the profile row itself no longer resolves). Compare id against another subscription's region.id to decide whether internal_address above would resolve from there -- see that field's own doc comment.
trial_converted_atWhen billing converted the trial to a paid subscription. Null until conversion.
trial_ends_atThe persisted trial deadline, or null for a subscription without a trial.
Whether this lapsed free trial can still be bought (ZC-0782). Null for anything that is not an unconverted free trial past its end -- an ordinary subscription, a running trial, or one already bought. available carries the deadline; payment_pending means a purchase invoice is open (resume paying it); closed means the three days are over and the trial is being deleted.
The tax on the next renewal, computed by kernel. Present only on the single-subscription read (getSubscription); null in listings, and when the renewal cannot be calculated (no tax code resolves, or the Price is gone).
SubscriptionStatusResponse
SudoDisableRequest
methodWhich admin-elevation module a credential belongs to, or a verification
attempt is checked against. AdminElevationModule gives each method
(PIN, WebAuthn, TOTP) a home behind this same enum without touching every
caller that only cares about routing by name. Serializable so callers of
/auth/sudo/* can pick a method by name instead of the HTTP layer
assuming PIN.
SudoElevateRequest
pinThe six ASCII digits the caller enrolled. A wrong PIN and an account
with no PIN enrolled are answered identically; see
controllers::sudo::elevate_error_response.
SudoElevateResponse
elevated_untiltokenSudoExitResponse
tokenSudoSetupRequest
pinSix ASCII digits. Format is validated by AdminElevationService.
SudoSetupResponse
elevated_untiltokenSudoStatusResponse
available_methodsThe elevation methods this surface can actually verify.
Was PIN-only before ZC-0716: /v2 ported no challenge-issuing route,
so a client offered webauthn or totp here would have had no way
to produce a secret for either. Now equal to
AdminElevationService::available_methods() (every module registered
in the deployment), because ZC-0716 added the missing enroll/verify
challenge routes for both. See controllers::sudo::V2_ELEVATION_METHODS.
enrolled_methodsEvery method the caller has actually enrolled, unfiltered, which
can include a method available_methods does not list.
That asymmetry is intentional rather than an oversight: a user who
enrolled TOTP while /v1 existed still has that credential, and it is
what makes POST /auth/sudo/setup demand an already-elevated session
before adding a second method (AdminElevationService::enroll). A
client that saw only the filtered list would have no way to explain
that refusal.
is_elevatedWhether the bearer token on THIS request is elevated right now.
Equal to elevated_until.is_some(), and published as its own field so
a client never has to compare a timestamp against its own clock to
answer the only question it usually asks. elevated_until is already
filtered against server time by utils::elevation::elevated_until, so
an expired window reads as false with a null deadline rather than
as a past date.
elevated_untilWhen the current elevation lapses, or null when the caller is not
elevated.
SupportAccessRequestResponse
chat_message_idThe message in the ticket thread that carries this prompt.
created_atidmax_duration_hoursThe longest an approval can last, from the domain's MAX_GRANT_DURATION.
Served on every request, pending ones included, because that is when the
customer needs it: it is the "for how long" half of what they are being
asked to agree to. Closing the ticket ends the grant sooner.
service_instance_idThe one service this request would reach. A grant is scoped to a service instance and to nothing else -- not the subscription, not the organization, not the customer's other services.
stateWhere one request sits in its lifecycle.
Five states and not four: Denied, Revoked and Expired are three
different stories about why access is not live, and collapsing them would
make the audit trail the customer reads disagree with the one the platform
keeps. Mirrors the domain enum's own snake_case wire form
(SupportAccessRequestState), which is persisted, so the two cannot drift.
ticket_idexpires_atWhen an approved grant stops working. Null until approval, and null forever on a request that was denied.
responded_atWhen the request was approved, denied or revoked. Null while pending.
SupportAccessRequestStateResponse
Where one request sits in its lifecycle.
Five states and not four: Denied, Revoked and Expired are three
different stories about why access is not live, and collapsing them would
make the audit trail the customer reads disagree with the one the platform
keeps. Mirrors the domain enum's own snake_case wire form
(SupportAccessRequestState), which is persisted, so the two cannot drift.
SupportTicketReviewResponse
problem_solvedresolution_speedresponse_qualitysubmitted_atticket_idcommentTargetStateResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string |
TextSettingDto
defaultmax_lengthTicketDetailResponse
One ticket visible to the caller, in the detail view (paired with its messages in
TicketDetailResponse) -- any ticket belonging to any organization the caller may see
(design doc §44.2), not only ones the caller personally opened. Same no-staff-identity
rule as TicketSummaryResponse.
TicketEventResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: type, ticketId, messageId +1 more | |
| type = object · requires: type, ticketId, messageId +1 more | |
| type = object · requires: type, ticketId, messageId +1 more | |
| type = object · requires: type, ticketId, isStaff | |
| type = object · requires: type, ticketId, isStaff +1 more | |
| type = object · requires: type, ticketId, claimed | |
| type = object · requires: type, ticketId, isStaff | |
| type = object · requires: type, ticketId |
typeisStaffmessageIdticketIdauthorIdTicketMessageAttachmentRequest
asset_idmime_typeoriginal_filenamesize_bytesTicketMessageAttachmentResponse
asset_idmime_typeoriginal_filenamesize_bytesTicketMessageEditResponse
edited_atidprevious_bodyTicketMessageResponse
author_is_callerWhether the caller wrote this message.
ZC-1110. A ticket thread is visible to the whole organization
(design doc 44.2), so author_name alone cannot answer this: two
colleagues can share a display name, and offering edit or retract on
the wrong bubble is worse than offering neither.
Stated as a boolean rather than by publishing the author's id on
purpose. The id would answer this question and one nobody asked --
which member of staff wrote a staff reply -- and this module
deliberately shows staff only as "Support Team". A boolean cannot leak
that however it is later refactored; an Option<Uuid> could, by being
populated in one branch somebody forgot to guard. It is always false
for a staff message.
author_is_staffauthor_namebodycan_editWhether the caller may correct this message right now.
The server's own rule, not a hint to re-derive. EditSupportMessage
refuses a non-author with Forbidden and refuses ANY edit on a closed
ticket with TicketClosed, so this is both conditions already
resolved. A client computing author_is_caller && !closed for itself
would be deciding an entitlement, which is the boundary every frontend
in this program is told not to cross, and it would silently drift the
day kernel adds a third condition.
can_retractWhether the caller may retract this message right now.
Separate from can_edit because the rules genuinely
differ: retraction stays available on a CLOSED ticket, where editing
does not. Somebody who posted something they regret can always take it
back; rewriting history after the conversation ended is what the
closed-ticket rule exists to stop. Collapsing these into one flag
would quietly pick one of those two behaviours for both.
created_atidkindauthor_avatar_asset_idThe customer author's avatar (V-0880), as an asset id the client
resolves through the asset route. None for every staff message
(staff are shown only as "Support Team") and for a customer with no
avatar; the client falls back to a monogram.
edited_atTicketResponse
claimedcreated_atidreviewedWhether the ticket's owner has already submitted a CSAT review for this ticket, regardless of who is viewing it. Orthogonal to whether staff has answered -- see TicketSummaryResponse::reviewed.
statussubjectclosed_atowner_last_read_atstaff_last_read_atTicketSummaryResponse
claimedcreated_atidorganization_idThe organization this ticket belongs to.
Carried even when the caller filtered to a single organization, for the
same reason InvoiceSummaryResponse carries one: a row that cannot say
who it belongs to forces the client to infer it from the request it
happened to send, and an unfiltered listing then has no way to group or
label rows at all.
reviewedWhether the ticket's owner has already submitted a CSAT review for this ticket (support_ticket_reviews.submitted_by_id). A customer-filed survey tied to the ticket's owner regardless of who is viewing it, entirely independent of last_message_from_staff.
statussubjectunread_countMessages unread since the ticket's own owner last read it (support_tickets.owner_last_read_at), not since the caller personally last read it. For the ticket's own owner this is exactly "tickets you have unread". For another organization member viewing a colleague's ticket, there is no per-member read cursor to compute one from, so this instead reports staff replies the ticket's owner has not yet seen -- still a meaningful freshness signal for the shared workspace, but not a claim about what this viewer has read.
closed_atlast_message_atlast_message_from_staffWhether the most recently posted message came from staff. Independent of reviewed below: a customer may submit a CSAT review at any time regardless of whether staff has replied, and a staff reply does not imply a review exists. 'Answered' and 'reviewed' are orthogonal, not sequential -- see this crate's report.
last_message_previewowner_last_read_atTitleRuleDto
max_lengthTopUpProviderRequest
A provider a top-up can be started with. Mollie is deliberately absent: a Mollie top-up has no checkout and no settlement path in the kernel.
TopUpStatusResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string | |
| type = string |
TotpEnrollConfirmRequest
codeThe current 6-digit code from the authenticator app. Verified against
the secret POST /auth/sudo/totp/enroll-options generated for this
caller, which must still be pending (ENROLL_TTL_SECONDS, 5 minutes)
-- see TotpElevationModule::read_pending_secret.
TotpEnrollOptionsResponse
accountissuerotpauth_urlotpauth:// URI encoding the same secret, issuer and account name,
for a QR code.
secretBase32-encoded shared secret, for manual entry.
TotpVerifyRequest
codeThe current 6-digit code from the enrolled authenticator app. A wrong
code, an already-used code and an account with no TOTP enrolled are
answered identically; see controllers::sudo::elevate_error_response.
TrialPurchaseKindResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
TrialPurchaseQuoteResponse
amount_centsPre-tax amount, in cents.
currencydeadlineWhen the offer lapses: the trial's own end for an upgrade, the moment the trial is handed over for deletion for a restore.
Which way a free trial is bought (V-0153).
subscription_idtax_amount_centsTax, in cents.
total_amount_centsAmount including tax, in cents -- what the purchase charges.
open_invoice_idThe purchase invoice already raised and still payable, whose figures these are; null when buying would raise a new one.
tax_labeltax_rateThe tax rate applied, as a fraction (0.21), when there is one.
TrialPurchaseResponse
amount_centsPre-tax amount, in cents.
createdtrue when this request raised the invoice (201), false when it handed back the invoice an earlier request raised (200). Both are success; a client must not render the second as a failure.
currencydeadlineThe moment the trial is handed over for deletion. Payment must be settled before it; a payment already in progress is honoured for a bounded time past it.
invoice_idThe one payable purchase invoice for this trial.
upgrade for a trial still running (the paid period starts at
payment, on the same running service), restore for a lapsed one.
subscription_idtotal_amount_centsAmount including tax, in cents -- what the customer pays.
TrialPurchaseStateResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: state, kind, deadline | |
| type = object · requires: state, kind, invoice_id | |
| type = object · requires: state |
deadlineWhich way a free trial is bought (V-0153).
stateTrialRefusalCodeResponse
Why a trial cannot be claimed, as a stable wire value.
Three, mirroring TrialClaimRefusal one for one. They are not collapsed
into a single "unavailable" because the customer's next action differs for
each: nothing (not_available), nothing ever (already_claimed), or come
back later (capacity_reached).
TrialRefusalResponse
codeWhy a trial cannot be claimed, as a stable wire value.
Three, mirroring TrialClaimRefusal one for one. They are not collapsed
into a single "unavailable" because the customer's next action differs for
each: nothing (not_available), nothing ever (already_claimed), or come
back later (capacity_reached).
messageUnitAllocationResponse
allocated_atallocation_idThe id the unit's agent acknowledges in /zaroz/allocation.json.
generationHow many allocations the unit has had, this one included.
delivered_atWhen the unit's agent wrote the allocation's files; null until then.
?wait=delivered on allocate waits for it.
UnitControlRefusalResponse
descriptionWhat was refused, in a sentence.
codeStable, snake_case: policy_not_code, unit_input_differs, no_warm_unit,
region_unreachable, container_unit_limit, stopped_unit_limit,
org_unit_limit, start_rate, spend_cap, not_provisioned,
container_busy, invalid_idempotency_key, or an input refusal
(invalid_unit_key, reserved_unit_key, user_data_too_large, ...).
detailscode: description, the shape every units refusal takes.
docs_urlThe page that explains this refusal and what to do about it.
retry_after_secondsHow long to wait before trying again, when waiting helps (also the
Retry-After header).
warm_readyno_warm_unit: warm units ready to allocate (zero) and still starting.
warm_startingUnitCountBucketResponse
atThe bucket's start.
extraThe most units billed as extra (beyond the plan's included units) at one instant inside the bucket.
max_runningThe most units running at one instant inside the bucket.
min_runningThe fewest units running at one instant inside the bucket.
UnitCountResponse
fromincludedThe units the plan includes: units beyond this are billed as extra. Drawn as a threshold.
step_secondstowindowA window a customer may ask for.
Absent for a service that has no scaling policy and no scaling history.
UnitEventResponse
typecontract_versiondataThe type's own fields.
idevt_ and the event's UUID.
occurred_atseqGapless and strictly increasing per Container.
service_instance_idnull for an event about the Container (units.scaled, rollout.*).
UnitEventUnitResponse
idkeyUnitLoadResponse
cpu_millicoresmemory_bytesreadysampled_atWhen this was measured; a client judges how fresh it is.
cpu_limit_millicoresAbsent when the pod has no CPU limit.
memory_limit_bytesUnitLogLineResponse
atid<unit_id>:<incarnation>:<container>:<instant>#<n>. The same line has the same id in a
history page and on the live stream, so a client draws it once.
textThe line, verbatim.
containerincarnationunit_idunit_ordinalThe unit's slot, for the chip beside a line.
UnitLogMarkerResponse
atidStable across reads: a client that polls forward and meets a fact twice draws it once.
kindtextunit_idunit_ordinalcontainerexit_codeincarnationOnly on overflow: the range and number of lines moved to the archive.
reasonFor container_restarted, why the container ended (OOMKilled, Error, ...).
UnitLogsResponse
coverageThe kernel's sentence about what this read covered.
The same, as separate facts a client may word itself.
Oldest first, whatever the direction read.
Lifecycle facts in the span this page owns, oldest first.
poll_after_msHow long a follow polls for, in milliseconds, so a client never hard-codes it.
truncatedMore lines exist in the direction read.
follow_cursorThe cursor that follows the newest line of this page: how a follow starts after the first (newest) page of a backward read, and where the next poll continues from after a forward one. Null for an empty page read backward.
next_cursorWhere to continue in the direction read. Reading backward it is null once the retention edge is reached; reading forward it is the cursor to poll with next.
UnitMetricKind
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
UnitMetricLineResponse
[bucket start in epoch milliseconds, value], 120 of them.
unit_idunit_ordinalThe unit's slot, which is what a chart's legend calls it (u1, u2).
limitThe ceiling this line is measured against, or null when it is unmetered or the unit
has no limit set.
Latest, mean and max of the buckets with a value; absent when there is none.
UnitMetricSeriesResponse
availablefalse when the source of this series did not answer; its lines are then all null.
What a customer may ask a metrics read for.
unitThe unit every number of this series is in: millicores, bytes,
bytes_per_second or lines.
Each unit's own line, lowest slot first, at most ten (the ten with the highest mean over the window).
The whole service: the units summed. Absent when the read was narrowed to one unit.
UnitMetricsResponse
available_windowsThe windows worth offering for this service: a service created an hour ago has no use
for 30d.
bucket_countHow many buckets every points array holds.
coverageThe kernel's sentence about what was read, shown beside the charts as given.
coverage_codeWhich sentence coverage is: metrics_shown or metrics_none_recorded.
The facts in it: window and to (RFC 3339), for a client that words it itself.
fromStart of the first bucket.
omitted_unitsUnits that wrote samples in the window beyond the ones drawn.
step_secondstoEnd of the window.
windowA window a customer may ask for.
unit_idUnitOriginResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
UnitPodEndResponse
atcontainerreasonOOMKilled, Error, Completed, ... or unknown.
exit_codeUnitPodResponse
billing_classincluded when the plan's price covered the pod, extra when it was billed on top.
idincarnation1, 2, 3, ... per unit; the highest is the unit's current pod.
pod_namerestartsContainer terminations inside this pod.
started_atunit_idWhy the pod ended: replaced (the platform made the next one), stopped,
torn_down or lost (it went away unasked: node loss, eviction). Absent while it runs.
ended_atAbsent while the pod is the unit's current one.
The newest container termination inside this pod, with its reason and exit code.
UnitPublicEndpointResponse
endpoint_idThe endpoint's id, to read its bill line or remove the port.
internal_portThe port the unit listens on inside its container.
protocolThe protocols one endpoint carries. TcpUdp is one endpoint, one price,
over one allocation carrying both labels ([PortProtocol::Both]).
public_ippublic_portUnitReadiness
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string |
UnitResponse
desired_staterunning when the platform wants the unit's pod to exist, stopped
when it wants it gone.
keyThe unit's stable name and the first label of its private name: u{ordinal} for a
unit the policy made, the customer's own key otherwise. Addresses the unit in
.../units/{key}.
The unit's labels, {} when it has none. Filter the list with label=key:value.
Who made the unit.
The public addresses that reach this unit alone, one per per-unit port (kind: unit
endpoints). Held for as long as the unit's slot exists, so each survives every pod
restart of the unit. Empty when the service has no per-unit port.
restarts_24hContainer terminations in the last 24 hours.
What the unit's pod says, or what its desired state implies when it has
no pod. A unit that is gone reads as suspended; deleted_at says it is gone.
unit_idThe unit's id, the key of its logs. A slot can have had several units over time.
user_dataWhat the unit was given as input. Present only when asked for (include=user_data
on the list, always on GET .../units/{key}); null means the unit has none. Not a
secret store: every reader of the unit sees it.
Set once allocate handed the unit to a caller (Units phase 2); null while it
has not been. An allocation is never undone: the unit ends by its exit, a stop
or a destroy.
Whether the unit's pod is covered by the plan's price (included) or
billed as an extra unit (extra). Absent while the unit has no pod.
current_incarnationThe newest pod this unit has had, running or not. Present for a stopped or gone unit too.
deleted_atWhen the unit was scaled away. Only listed with include_gone=true.
incarnationHow many pods this unit has had, counting the current one. Absent while it has no pod.
kept_untilWhen a gone unit's logs, pods and terminations age out and are no longer listed.
Present exactly when deleted_at is.
Absent for a unit never sampled, a gone one, or while samples cannot be read.
ordinalThe slot, 1..N, held while the unit can run. Null for a stopped unit of the customer's code or the warm buffer, which gives its slot back (Units phase 2).
pod_nameprivate_nameThe name another service in the same project resolves to reach this unit
alone, <key>.<service slug> (for example u2.worker). The service's slug
by itself reaches every ready unit. Absent when the service has no private name.
started_atWhen the current pod was created.
UnitScalingMarkerResponse
actionWhat a marker on the count chart says happened.
atfrom_unitsidsummaryThe kernel's sentence, for example "Scaled 2 to 4: CPU at 83% against a 60% target".
summary_codeWhich sentence summary is, <action>.<reason> such as scale_up.cpu_high.
The figures in it (from, to, and used/target/min/max when recorded), for a
client that words the sentence itself.
to_unitsUnitTerminationEntryResponse
containeridincarnationThe pod incarnation the container was in.
observed_atWhen the kernel saw the restart.
reasonOOMKilled, Error, Completed, ... or unknown.
restart_countThe kubelet's restart count after this termination.
unit_idexit_codefinished_atUnitTerminationResponse
atWhen the container ended, or when the platform noticed that it had.
containerreasonOOMKilled, Error, Completed, ... or unknown when the kubelet did not say.
exit_codeUnitWebhookDeliveryResponse
attemptThe attempt's number for this batch, from 1.
attempted_atduration_msidkindevents (a batch) or ping (a test).
errorWhy it failed: address_not_allowed, dns, connect, timeout,
http_status, redirect_not_followed, invalid_url, transport.
null for a 2xx.
from_seqThe first and last event seq of a batch; null for a ping.
next_attempt_atWhen the batch is tried again; null unless a batch failed and will be
retried.
response_excerptThe first 4 KiB of the receiver's answer.
status_codeThe receiver's status; null when it never answered.
to_seqUnitWebhookResponse
attemptConsecutive failed attempts of the current batch.
created_atcursor_seqThe last event seq the receiver acknowledged.
event_typesEmpty means every type.
idnext_attempt_atWhen the next attempt is due.
stateactive, failing (retrying the same batch) or disabled.
updated_aturldisabled_reasonWhy it is disabled: failing_72h. null unless disabled.
failing_sinceWhen the current run of failures began. null when the last attempt
succeeded.
previous_secret_expires_atUntil when the previous secret still signs beside the current one after
a rotation; null when only one secret signs.
UnitWebhookSecretResponse
secretwhsec_ and 43 characters. Sign check: Zaroz-Signature carries
v1=<hex HMAC-SHA256(secret, "{Zaroz-Timestamp}.{raw body}")>, with the
whole secret string as the key.
A webhook, never its secret.
UpcomingChargeResponse
currencysubtotal_centsThe renewal's pre-tax amount, in cents.
tax_amount_centsThe tax on it, in cents; 0 when no tax applies.
total_centsWhat the invoice will total (subtotal_cents + tax_amount_cents), in cents.
tax_labelThe tax's name (VAT); null when no rate applies.
tax_rate_basis_pointsThe tax rate in basis points (2100 is 21%); null when no rate applies.
UpdateBucketRequest
cap_byteslabelpublic_readServe the bucket's objects to anonymous readers.
UpdateFirewallRuleRequest
descriptioncidrenabledport_fromport_topriorityUpdateMeRequest
billing_country_codeThe country this account is billed from, ISO 3166-1 alpha-2, case insensitive. Refused with 422 once onboarding is complete and a country is already stored: the value decides tax treatment, so it is deliberately not something a customer can re-answer later.
discord_notifications_enabledWhether to relay notifications to Discord.
languageA new display language tag.
nameA new display name. Moderated by Username::try_new_moderated, so a
name that is too short, too long, wrongly shaped or offensive is
refused rather than stored.
UpdateMyWalletPreferencesRequest
autopay_enabledUpdateNetworkProtectionModeRequest
modeUpdateOrganizationMemberRequest
roleDistinct from OrganizationRoleResponse because request and response
enums are separate types on /v2 (design doc §43.4), even where they
currently carry the same variants.
UpdateOrganizationRequest
nameslugUpdateProjectRequest
descriptionnameslugUpdateRegistryRequest
cap_byteslabelUpdateRuntimeConfigRequest
commandOne string, tokenised by kernel. A client splitting a command line
would be a component computing a value (R2).
entrypointpost_deploy_commandRefused when not null; there is no post-rollout mechanism at all.
pre_deploy_commandRefused when not null; nothing renders an init container from this.
stop_grace_period_secondsThe text that was typed, unparsed, so a browser that rounds or clamps
cannot decide a value the scheduler owns. Refused when not null;
the grace period is hardcoded in the Kubernetes renderer today.
stop_signalRefused when not null; see [RuntimeConfigResponse::stop_signals].
working_directoryRefused when not null; nothing renders a workingDir today.
UpdateScalingPolicyRequest
contract_versioncpu_target_percentdestroy_stopped_after_daysdrain_idle_after_secondsidle_after_secondskeep_acceptingmax_unitsmemory_target_percentmin_unitsready_timeout_secondsscale_down_stabilisation_secondsscale_up_cooldown_secondsspend_cap_centswarm_unitsUpdateScheduleRequest
What each fire does (V-0702). Required: run_job for a cron-job
service, tasks for any other.
cron_expressionnameThe three concurrency policies a schedule may declare. Mirrors
[OverlapPolicy] one for one; see this module's header for why it is not
reused directly.
timeout_secondstimezonepausedUpdateServiceInstanceRequest
nameslugUpdateServiceShareRequest
The complete new set, replacing the old one.
UpdateSftpRequest
enabledUpdateUnitRequest
At most 16 pairs. A key is 1 to 32 lowercase letters, digits, dots, underscores or hyphens; a value is at most 64 characters without control characters; the whole map at most 2 KiB serialized.
UpdateUnitWebhookRequest
event_typesEmpty for every type.
urlUploadTicketAttachmentResponse
asset_idmime_typeoriginal_filenamesize_bytesUsernameRuleDto
denymax_lengthmin_lengthdefaultVerifyEmailRequest
tokenVerifyLoginCodeRequest
challenge_idcodeVmAccessRequestDto
passwordusernameextra_packagesv1's free-text extra packages (commas, spaces or newlines separate); Linux only.
install_qemu_agentv1's "install qemu-guest-agent" checkbox; Linux only, default true.
keyboardlanguagepackage_updatev1's "package update" checkbox; Linux only, default true.
package_upgradev1's "package upgrade" checkbox; Linux only, default false.
ssh_authorized_keysssh_password_authtimezoneVmAccessResponseDto
extra_packagesinstall_qemu_agentkeyboardlanguagepackage_updatepackage_upgradepassword_setssh_authorized_keysssh_password_authtimezoneusernameVolumeSummaryResponse
capacity_bytesThe claim's configured size. A quota rather than a measurement, so it is exactly what the customer bought and it never disagrees with the invoice.
mount_pathWhere the volume is bound inside the workload, for example /data. A
cross reference rather than a property of the claim: the mount lives on
the workload that mounts it, and this is the path the file browser opens
at for the same volume.
last_backup_atWhen the customer's most recent on-demand backup of this volume
finished, or null when they have never taken one that completed.
The customer's own snapshots only. The platform's disaster-recovery backups run on a different mechanism and are not counted here, because presenting one as the other would tell a customer their data is protected by something they never invoked.
used_bytesWhat the volume holds, or null when kernel cannot measure exactly this
claim: the service has no file sidecar, the sidecar's walk covers more
than this volume, or it did not answer in time. Absent rather than
approximated.
used_fractionA number in [0, 1], already clamped. Multiplying it by 100 for a
percentage width is a unit conversion for the widget rather than a
computation; deriving it from the two byte counts instead is not.
null exactly when used_bytes is.
used_labelKernel's sentence about the meter, for example "3.0 GiB of 25 GiB".
Render it as written. null exactly when used_bytes is.
VpsDetails
connect_port22 for Linux (SSH), 3389 for Windows (RDP).
connect_protocolssh or rdp.
operating_systemlinux or windows.
public_ipv4The machine's public IPv4 address; empty while it has none.
usernameinternal_ipv4internal_ipv6public_ipv6VpsOperatingSystemOptionResponse
descriptiondisplay_namedistro_display_namefamily_display_nameidlogo_slugos_kindlinux or windows.
slugtagsfee_per_monthThis image's own recurring monthly fee, if it has one.
min_cpuThe smallest shape this image can run on, when the image declares one. A chosen size below any of these three is refused at checkout with the matching VpsOperatingSystem*BelowMinimum error.
min_memory_gbmin_storage_gbWalletBalanceResponse
amount_centsEvery pocket combined (real_cents + promo_cents + legacy_cents),
signed. Not what a wallet payment can spend -- see
spendable_cents. Kept for a caller reconciling this against the
ledger's own raw sum; a wallet is normally at or above zero, but the
ledger is the only source of truth and this reports what it sums to
rather than clamping.
currencyISO 4217, three uppercase letters.
legacy_centsPre-ledger-cutover money not yet classified into a pocket. Not
currently spendable by any wallet-payment path; included so
real_cents + promo_cents + legacy_cents always equals
amount_cents.
promo_centsPromotional credit (ledger design spec §6): never withdrawable, never
cash. Under the default policy it is not drawn as cash by a wallet
payment; it is applied as an invoice discount line, automatically,
when an invoice is issued AND (V-0882) when an unpaid, unnumbered
invoice is paid from the wallet. A client shows it as its own figure
("promotional credit"), apart from real_cents and not part of
spendable_cents.
real_centsThe pocket a wallet PAYMENT draws under the default policy
(PromoTreatment::Discount): top-ups, refunds settled in cash,
reseller payouts.
spendable_centsWhat a wallet payment can draw right now, under the ledger's
current policy set. This, not amount_cents, is the figure a "pay
with wallet" affordance must compare its total against: a customer
holding only promo credit under the default policy sees a non-zero
amount_cents here but a spendable_cents of zero, which is why a
wallet payment for them is refused as insufficient funds even though
the balance above reads as positive.
WalletCodePreviewResponse
amount_centsFace value in minor units of currency
currencyexpires_atWhen this code stops being redeemable, or null if it does not expire. A code already past this instant is reported as not found rather than returned with a past date.
WalletCreditQuoteLineResponse
base_centsThe refunded amount before tax, in minor units.
invoice_idinvoice_line_idtax_centsWalletCreditQuoteResponse
as_ofThe instant every figure below was computed at; redemption recomputes at exactly this instant.
below_minimumTrue when total_cents is under minimum_cents: the conversion is
not offered and redeeming this quote writes nothing.
currencyeligibleexpires_atminimum_centsperiod_remaining_secondsperiod_total_secondsquote_idOpaque and signed. Send it back unchanged to
POST /subscriptions/{id}/cancel-with-wallet-credit; an altered,
foreign or expired one is refused.
total_centsWhat the wallet would be credited, in minor units of currency.
reasonWhy the subscription is not eligible, when eligible is false: one of subscription_not_active, policy_not_prorated_to_wallet, disputed_or_charged_back_invoice, bundle_member.
WalletEntryReasonResponse
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = string |
WalletEntryResponse
amount_centsInteger cents, signed: positive credits the organization, negative debits it. Never a formatted string, and never a fraction of a cent.
created_atcurrencyISO 4217, three uppercase letters. Entries in different currencies move different balances and must never be added together.
idWhy the movement happened. A closed vocabulary -- see
[WalletEntryReasonResponse].
actor_user_idThe person who caused the movement, when a person did.
The id alone, not a name: an organization is a shared workspace, so
"who spent this" is a real question here in a way it never was on
/me/wallet -- but resolving names is a second query, and the member
listing already maps ids to people for exactly this organization.
Absent for anything the system did on its own (autopay, a scheduled
grant).
invoice_idThe invoice this entry paid or refunded, when it names one.
noteA free-text note, when one was written. Staff-authored on an adjustment; usually absent.
related_entry_idThe entry this one reverses, when it is a reversal. The ledger is append-only, so a correction is always a second row pointing back at the first, never an edit of it.
WalletResponse
One row per currency the caller's personal organization holds.
A currency with no money in it has no row. An organization that has never been credited, or one whose movements net to exactly zero, answers with an empty list -- this is a normal, fully-formed 200, not a sign that the wallet is missing. Treat an absent currency as zero.
WalletTopUpAvailabilityResponse
nowpaymentspaypalWebPanelLogin
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: step | |
| type = object · requires: step, password_id |
stepWebauthnAuthenticateConfirmRequest
credentialThe browser's PublicKeyCredential assertion response (from
navigator.credentials.get).
WebauthnRegisterConfirmRequest
credentialArbitrary JSON.
WorkloadRolloutResponse
is_primaryWhether this is the workload the instance's product treats as primary.
kindMirrors ProvisionKind 1:1, kept as its own /v2 response type so this
crate's wire format cannot drift silently if a variant is ever renamed on
the domain enum without a matching, deliberate wire change here -- the
same convention kernel_http_v2_catalog::contracts::products:: ProductFamilyView already follows for ProductFamily (the retired
ProductKindResponse, which used to follow it for CatalogServiceKind,
was deleted alongside that enum, A2-S13d).
resource_idroleThe resource's declared role, e.g. "server". What a panel labels the
row with when an instance owns several workloads.
updated_atWhen the reconciler last wrote this row. A rollout that landed shows a timestamp after the deployment that caused it; one that never landed shows a timestamp before it. That comparison is the closest thing to a per-deployment outcome the platform can currently support, and it is a hint rather than a verdict, which is why kernel does not present it as one.
WorldNameLabelDto
Mirrors [WorldNameLabel] by hand.
WorldNameSettingDto
defaultlabelMirrors [WorldNameLabel] by hand.
max_lengthWriteFileRequest
contentReplaces the file's contents entirely. Creates it when it does not exist.
RegistryTagView
namedigestThe manifest digest the tag points at (sha256:...).
size_bytesCompressed size of the image: its config and layers.
created_atWhen the image was built. The registry reports no push time.
RegistryTagsResponse
truncatedThe repository has more tags than one listing describes; only the first ones (in the registry's order) are shown.
ObjectView
keyThe full key.
size_bytesetaglast_modifiedObjectListingView
auto_preview_max_bytesPreviewing a file loads it, and a download is billed egress. Show a preview without asking only for images up to this size.
foldersFull prefixes of the folders directly under it, each ending in /.
max_upload_bytesThe largest object the browser uploads.
prefixThe folder listed, "" for the root.
next_tokenPass as token to get the next page; absent on the last.
ObjectListingResponse
PresignedUrlView
expires_atmethodurlDownloadRequest
keysave_asMakes the browser save the file under this name instead of showing it.
DownloadResponse
A GET. Billed egress, like any S3 download.
StartUploadRequest
keysize_bytesThe exact size in bytes. A single PUT is signed for exactly this many.
content_typeStartUploadView
modesingle or multipart.
part_bytesmultipart: every part but the last is this many bytes.
partsmultipart: how many parts there are.
single: PUT exactly size_bytes here.
upload_idmultipart: the upload to add parts to.
StartUploadResponse
PresignPartsRequest
keyparts1-based part numbers, at most 50 per request.
size_bytesThe object's total size, as given to start the upload.
upload_idPartUrlView
numberA URL to call and the headers to send with it (besides Content-Length,
which the browser sets).
PresignPartsResponse
CompletedPartRequest
etagThe ETag response header of the part's PUT.
numberDeleteObjectsResponse
SearchKnowledgeRecommendation
slugA catalog product slug named in products.
expecttierOne sentence saying why, per locale.
SearchKnowledgeConcept
idkebab-case, unique across the knowledge base.
kindWhat people type, per locale.
provenancereviewedAtISO date of the last human review.
platformClaimsIds of claims this entry relies on.
nameA proper noun shown in copy; required for unsupported.
For unsupported: what to say about it.
For game: whether the Gaming bridge goes before or after the answers.
soldInGamingSearchKnowledgePlatformClaim
idstatementsourcescaveatreviewedAtISO date a human last confirmed this claim still holds.
SearchKnowledgeProduct
slugstatusreplacedByFor retired: the products that took over.
SearchKnowledge
version