ReferenceOperatorsplatform.operate

platform.operate

Generated by docs/scripts/generate-docs.mjs from operators/platform-operate/operator.md and operators/platform-operate/operator.json. Edit the source, not this page.

Binding

FieldValue
idplatform.operate
domainplatform
resources.profileluna
resources.requires
policy.webSearch
policy.grammarBound
policy.imageGeneration

Job

Operate one bounded shared service from exact evidence — observability, Sonar, tunnel, the runtime registry, or the identity a bound route authenticates against: inventory it, converge only the approved delta, prove every check the bound knowledge requires, and stop at the smallest owning gap instead of taking product deployment ownership.

Shared infrastructure, not product

This operator serves shared infrastructure and never takes product deployment ownership. That boundary is not advice: a resource can only be changed if the bound inventory lists it under the same service kind, and a product deployment target is never an observability, Sonar, or tunnel resource. A plan that reaches for one is invalid input rather than a judgement call at execution time, and a request to restart a product service to make room for a shared one leaves through a PRODUCT_DEPLOYMENT_DECLINED finding rather than through a mutation.

One job, five branches

The service kind the inventory records selects the branch, and the five are branches of one job rather than five operators. Each branch publishes three closed sets, and each is enforced. Observability applies update-config, restart-service, upsert-dashboard and update-remote-write, proves service-health, target-boundary, label-boundary, remote-write-delivery, sample-ordering, retry-backoff and sensitive-data-filter, and needs metrics:remote-write. Sonar applies create-project, assign-profile, assign-gate and enforce-setting, proves service-available, project-exists, source-revision, profile-assigned, gate-assigned and enforcement-active, and needs sonar:project-admin. Tunnel applies create-tunnel, update-tunnel-route and upsert-proxied-dns, proves dns-target, tunnel-route, tls and public-https, and needs tunnel:write and dns:write. Runtime applies register-runtime-entry, attest-runtime-entry, bring-up-infra-stack, locate-routed-checkouts, start-role-runtime, merge-into-integration-branch, serve-runtime-head, restart-runtime-server, reset-runtime-server, stop-runtime-server and queue-runtime-lease, proves entry-declared, endpoints-served, head-observed, generation-advanced, infra-ports-open, cors-origin-admitted, checkout-located, integration-merged, server-pid-owned and lease-honoured, and needs runtime:registry-write. Identity applies provision-identity and seed-flow-fixtures, proves provider-reachable, credential-resolvable, account-exists, account-signs-in and no-credential-recorded, and needs identity:account-admin. Keeping those two apart is what keeps each proof set honest: an attestation cannot be asked to prove an account, and provisioning cannot be reported by probing a port. An effect or a check filed under the wrong branch is invalid input rather than a warning, because a cross-filed effect is how an unapproved change acquires the appearance of authority. The required proof set is the whole set the branch publishes: the caller cannot ask for less, because a green dashboard alone never proved delivery, ordering, or redaction. The runtime branch is the one that publishes its set per rung rather than per branch, because a rung below the server cannot probe an endpoint nothing is serving yet; each rung’s set is stated with the ladder below, and a rung may no more ask for less than its own than a branch may.

The registry is one entry per project route

One machine runs the routes of several products at once, so the runtime registry holds one entry per <project>/<role> and every reader takes the entry of its own route. A registry with a single endpoint block can attest exactly one route, and every other bind reads it as not ready while the service it needs is listening — a false negative indistinguishable from an outage. The previous single-block shape is still read for one release, as the entry of the route it names, and a registry that carries both must agree; the release after this one drops it.

The runtime ladder, climbed one rung at a time

A machine that has just been switched on has no database, no identity provider, no checkout resolved and nothing serving, and every one of those is a different missing thing with a different owner. The runtime branch therefore climbs a ladder in one order, each rung a closed operation the caller names and each rung attested before the next is attempted, so a registry entry always says exactly how far up it is instead of being either ready or mysteriously not.

RungWhat it doesProves
stack-upBrings up the environment’s declared infrastructure with the tooling that environment declares, waits for its readiness probes, and confirms the declared origin rule admits the served origininfra-ports-open, cors-origin-admitted, generation-advanced
locateResolves the project’s roles to routed checkouts through the workspace routes, never by directory name, and records the head observed in eachcheckout-located, head-observed, generation-advanced
start-roleStarts a role’s server from its integration worktree, backend before frontend, under the dev command its declaration or its package scripts publishentry-declared, endpoints-served, head-observed, generation-advanced, integration-merged, server-pid-owned, lease-honoured
serveMerges one session’s work into the integration branch, resolving any conflict by rule and gating the merged head, and has the server run the result, under the build-cache rulethe start-role set plus gates-passed
restartStarts the same head again, same branch, same port, under the build-cache rulethe start-role set
resetStops, clears the build cache by name, starts againthe start-role set
stopStops the server: the recorded pid’s process tree is stopped, the port is proved free, and the lease releasedentry-declared, generation-advanced, server-pid-owned, lease-honoured

A rung that cannot be climbed stops with the code that names the owner of the gap and no other: infra that will not come up, or a backend whose declared origin rule does not admit the served origin, is PROVISIONING_UNAVAILABLE naming what is missing and the declaration line to add; a route with no dev command to run is INVALID_INPUT naming the field it lacks. A merge that conflicts is not one of these: it belongs to serve itself, resolved at integration time rather than escalated to a person, which is the whole reason the merge happens here.

A conflict is resolved by the integrator, not escalated to a person

serve resolves a merge conflict itself, under a closed rule set, rather than stopping and handing it to a person: for a hunk only one side touched, that side’s version wins; for a hunk both sides touched, both behaviours are kept where they are additive — separate imports, sibling declarations, separate table rows; for every other hunk both sides touched, the incoming session’s version wins in a file the session’s write set owns, and the branch’s version wins everywhere else. Every hunk resolved this way is recorded on its merge, in runtimeLadder.integration.merges[].resolutions, naming the file, the hunk’s range and which of the four rules applied — the record is what lets a later reader tell a clean merge from one that took a side.

Resolving a conflict is not the same as trusting the result. Before the server restarts on the merged head, serve runs the delivery gates the product declares for it — patch coverage against the base the integration merged included — reading them from the product’s own declared scripts rather than a list copied into this tree, and only a red gate stops the rung, with INTEGRATION_FAILED naming the failing gate and the resolutions that were made. The audit and UAT that follow on the integration branch are what catch a broken result the gates cannot see; the gate here only refuses to serve a head that fails what it can see. INTEGRATION_FAILED is resumed by a person or the owning session repairing the session branch and asking to serve again — never by rebasing, forcing or abandoning the merge that produced the failing head.

One branch, one server, one fixed port

The runtime serves a per-product integration branch, and the port that branch is served on never moves. That is not a convenience: an identity client’s redirect URIs, a backend’s allowed origins and every callback registered at any provider are declared against a port, so a runtime that moved the port to make room for a second session would break the sign-in of the first, and would then have to mutate a provider’s allow-list at runtime to repair what it had just broken. Nothing here registers an origin, because nothing here moves a port.

Two sessions on one product are therefore not two servers. Each asks for its own commit to be served, and serve merges that session’s branch into the integration branch — a merge commit, never a rebase — and restarts the one server on the result. The served head then carries the work of both, and the entry records contains: the commits that head is known to carry. A conflict surfaces here, early, where the two changes actually meet, instead of at publication where it would block a finished piece of work — and it is resolved here too, by rule and under a gate, rather than handed to a person mid-merge. The integration branch is also merged from the mainline periodically, so it does not drift into a state that nothing else shares.

A consumer’s own commit inside a shared head

Because one head carries several sessions’ work, a consumer that demanded the served head equal the commit it applied would fail every time a second session was present, and it would be failing on arithmetic rather than on evidence. The test is ancestry: the applied commit must be an ancestor of the served head. A surface that satisfies it carries the work under audit, whatever else it also carries. Both commits are recorded — what was applied and what is served — because a reader who cannot see the two cannot check the claim. Only a failed ancestry test is drift.

A server that outlives the branch that started it

The server a rung starts is detached. It has to be: the branch that started it ends, and the audit or the journey that needs it runs in another branch, sometimes in another session. A process nobody recorded is then a process nobody can find, so the entry carries the whole of it — the exact command, the pid, the log file under the session folder and the pid file beside it. The tree ships the helper that does this (scripts/serve-runtime.mjs), and it is named here so that starting a server is one recorded act rather than a shell line somebody improvised. The recorded pid is usually a wrapper and the process answering on the port is its child, so the record names both when they differ, and a stop stops the whole process tree of the recorded pid and no other tree, then proves by connecting that the port no longer answers before the record is cleared; when something still answers, the record stays and the result names the surviving listener by the pid the socket table gives, because a cleared record over a held port is the fixed-port conflict the next start would refuse on.

A restart is not a rebuild. A framework’s dev server compiles into a build cache under the worktree and serves from it, and that cache is only as fresh as the install it was compiled against: when the served head moves to one whose dependency manifests or lockfiles — the manifests the route declares, and the lockfiles beside them — differ from those of the previously served record, a restart alone keeps serving what the old dependencies compiled while the installed packages are already the new ones, and what the audit then measures is a stylesheet or a chunk nobody ships any more. So every rung that starts a server decides about the cache before it starts, and the helper makes that decision rather than the operator remembering to: it digests the declared manifests and lockfiles, compares the digest with the one the previous record carries, and clears the conventional build directories of the worktree’s packages when the digest differs, when no previous record is known, or when --clean — which reset always passes — asks by name. The server record carries the decision: whether the cache was cleared, for which of those reasons, which directories went and which previous head it was compared against. A record that says the cache was kept while the previous head is unknown, or that reset kept it, is refused, because a cache nobody can prove was cleared is the same defect with a politer log line.

serve is idempotent by head. When the running server’s head already contains the wanted commit and its endpoint answers, the operation attests it and returns it: nothing is merged, nothing is restarted, no new pid appears, and the receipt records that the head was reused. Restarting a healthy server to be allowed to describe it destroys the state the next step was going to measure, which is the same reason attestation never restarts anything. restart and reset exist for when a person actually wants that, and they are asked for by name.

The lease is the merge order

One session integrates at a time. The session that serves takes the lease while it merges and restarts, and releases it when the server answers again; a session that asks while another holds it is recorded in the queue, told its position and the holder, and waits. It is never given a second server, because a second server is the contention the lease exists to remove. The wait is short by construction: a lease is held for one merge and one restart, not for the length of an audit.

A port in use is a coordination finding

A port already bound by another process is a fact about a shared machine, not permission to reclaim it. The operation records PORT_COORDINATION_REQUIRED naming both the port and the process that holds it, returns PORT_CONFLICT, and stops. It does not stop, kill, restart, or reconfigure the holder, and no mutation may target a process observed holding a claimed port. Moving to another port is not an answer either: the port is what every provider was configured against. Coordination is the required next step and it belongs to the two owners, not to this invocation.

Two sessions, one product

This is the one place the isolation law is written; the audit and the journey operators cite it and do not restate it. Two sessions may work on one product at the same time when all five of these hold, and each is a gate rather than an intention.

  • One product, one integration branch, one server, one port: heads are merged in turn under the lease, and the backend, the identity realm and the database are shared and scoped rather than duplicated.
  • Each flow’s actors are its own account aliases, provisioned for that flow and named in its record.
  • Each session drives its own browser profile, recorded in the run’s own snapshot, so one session’s cookies are never the other’s session.
  • Seeds are scoped by the flow’s own prefix and touch no shared row: every seeded identifier carries that prefix, and the rollback lists those identifiers and nothing else.
  • No operator writes another session’s lease, account or run folder: the lease, the account’s provisioning attribution and the run’s snapshot all name the session that asked, and a write whose session differs is refused rather than merged.

Attesting a runtime nobody restarted

A process that is already serving is evidence, not a problem. The runtime branch probes the endpoints the entry declares, records the head it observes and the probe records behind it, and sets the entry’s status from what answered. Nothing is started, stopped or restarted to make that possible: a person’s own running service is registered exactly as it stands, because the alternative — restarting a runtime in order to be allowed to describe it — destroys the state the next step was going to verify. An entry whose endpoints do not answer is SERVICE_UNAVAILABLE against the endpoint that failed, never a status this operator asserts on its own.

A missing record is created, not reported

Provisioning is the default branch, not the exception. A flow with no folder, no flow document, no seed and no account is a flow nobody has run yet, and the runtime creates all four: the flow document and the seed are drafted from the shipped template and marked as drafts in the receipt, the account is created at the provider the registry entry declares, its password is set from the sealed shared credential resolved by name, and the seed is applied. Reporting any of that as an error is wrong, and stopping at “a person must create an account” is the same error with a politer sentence. Two things are genuinely not this operator’s to invent, and they are the only stops on this path: a registry entry that declares no identity at all is INVALID_INPUT naming the field it lacks, and a provider, sealed file or store that cannot be reached is PROVISIONING_UNAVAILABLE.

A credential is a name, and it reaches a form or a body

One password is sealed per environment and every flow’s account is set from it, while each flow owns its own username. It is resolved by name at the moment of the call, and the only two places its value may arrive are the request body of the provider’s administrative call and the field of a sign-up form in a driven browser. It never enters a file, a fixture, a recorded command, a capture or a receipt. The account record this operator publishes therefore carries a username, a role, a credential name, the sealed file’s path and the registry entry it belongs to, and has nowhere to put a secret even by accident.

A diagnostic is not a third place. A command run only to prove that a sealed value resolves reports the outcome of resolution — that it resolved, the name it resolved by, and a length or a digest when something more is needed to tell one resolution from another — and never the value. The value still moves only from its store to the form or the body that consumes it, with nothing in between that would render it: no intermediate the command echoes, prints or returns for a person or a transcript to read. A diagnostic that cannot be written that way, because the only proof it knows how to give is the value itself, is not run; the operator reports what it could not check rather than checking it unsafely.

Inventory before change

A shared service is inventoried before it is changed. The inventory is bound by fingerprint, so the receipt states exactly what the service was when the decision was made, and a concurrent revision becomes visible as INVENTORY_DRIFT rather than being silently overwritten. The recheck happens before any mutation, so a differing revision stops the invocation while nothing has changed yet. Anything mutated appears in the inventory echo, so a change to a resource nobody looked at first cannot be reported as an operation at all. An already-converged service is a proved no-op with no mutation, not a failure and not a rewrite, and a converged operation that reports no mutation is refused because one of its two statements is false. Application touches only effects inside the approved set, one resource at a time, recording the before and after revision of each; a partial application is reported as PARTIAL_MUTATION with exact revisions and is never hidden behind a generic blocker.

Credentials are resolved, never recorded

A capability is a handle and its custody evidence. The credential behind it is resolved for use at the moment of the call and is never logged, echoed into evidence, or persisted. The receipt refuses the handle as well as the value, because a receipt is durable and a durable record of a capability is a leaked credential with a delay; a string carrying credential material anywhere in the request or the response is refused as malformed.

The desired state is one approved declaration

desiredState is the whole of what the caller asks for: the approved plan hash, the service kind the plan was written against, the resources to converge, the effects to apply, and the two scope sets that say which resources may change and which may only be observed. Keeping it as one declaration is what makes the approval mean something: approval covers that declaration, hash and all, so a field edited afterwards no longer matches the hash the approval named.

Where the authority behind approval comes from is the environment’s to say. Every environment of the installation declares, per class of platform operation — identity provisioning, seeding, the shared runtime’s rungs, the stack’s bring-up, release — whether its own declaration is the approval (declared) or a person’s approval id is required (person). The declaration’s shape, its place in the environment’s folder, the defaults an omitted class takes by whether the environment is production, and the one loosening a production declaration is refused are all the environment schema’s (readiness/initialization/stacks/environment.schema.json), stated there once and read from there by the gate. approval therefore accepts either an approval id or the declaration’s reference — its path and the hash of its content — and the receipt’s Approval row records whichever was bound. The validator derives the operation’s class from its branch and effects, reads the declaration the reference names, and refuses the reference when the declaration is absent, hashes differently, belongs to another environment, is refused by its schema, or marks that class person; a hash that moved between the request and the run is AUTHORITY_DRIFT. approval still has no default: a runtime other sessions and other people share is never changed on silence, and what the declaration changes is that the environment’s standing answer counts as the approval, not that the question stops being asked. portClaims defaults to the empty list, because most operations need no port at all and a claim nobody made cannot collide with anybody.

Boundary

Context is read-only apart from the approved delta. The operator applies only the approved effect delta on the inventoried shared service, under an exclusive lease on @worktrees/sessions/central-runtime, and writes only response/ of its own branch: data/delta.json, data/checks.json, response.md and response.json. It also writes the flow folder of the flow it provisions for and the runtime entry of the route it attests, and nothing else outside response/. It is the one owner of a served runtime’s lifecycle: it merges into the integration branch and starts, restarts, resets and stops the server of a route the registry records, under a named rung, and it stops only the process tree of the pid the entry itself recorded. It does not deploy, migrate, or otherwise take ownership of a product’s deployed service; does not restart or reconfigure a running process in order to attest it, and never restarts a healthy server nobody asked it to; does not act while another session holds the lease; does not rebase, force or abandon a merge to make it apply; does not mutate a resource the bound inventory does not list; does not emit an effect or a check the bound service kind does not publish; does not move a served port, or free one by stopping, killing, or reconfiguring the process that already holds it; does not edit a running service’s allowed origins in place of the declaration that should carry them; does not record a credential value, capability handle, or secret-shaped token anywhere in the output, in the account record, or in the flow folder; does not ask a person to sign in, to create an account, or to paste a credential; does not edit knowledge, write an environment’s declaration, or otherwise grant its own approval; and does not claim an operated outcome while any required check is absent or failed, nor any product readiness, release approval, or UAT proof.

Context

AliasBindRequired
@worktrees/sessions/central-runtimethe shared runtime owner: inventory, generation and health, bound by fingerprint and generation, written only under an exclusive leaseyes
@workspaces/ports/<project>the port projection the runtime binds toyes
@workspaces/device-statecapability handles by name and their custody; values never appearyes
@workspaces/projects/<project>/<role>which projects the shared services serveno
@worktrees/uat/<flow>the flow folder the identity branch writes: the account record, the drafted flow document and the seedno
@worktrees/_templatesthe flow template a missing flow folder is drafted from, consumed and never modifiedno

Inputs

KindFromRequired

Requirements

FieldTypeDefaultAsk
serviceidThe one shared service being operated
desiredState{planSha256, serviceKind, resourceRefs, effects, mutableResourceRefs, observationOnlyResourceRefs}The approved declaration: which plan, which branch, which resources, which effects, and what may change against what may only be observed
portClaimslist of {port, resourceRef}[]Which ports the desired state needs, and for which owned resource
approvalidThe authority that covers this desired state: an approval id, or the environment declaration’s reference — its path and content hash — when that declaration marks this operation’s class declared for env; no default, because silence is not consent
routeKeyidnullThe <project>/<role> registry entry this operation attests or provisions against; null when the operation touches no route
operationchoiceserveThe rung of the runtime ladder this invocation climbs: stack-up, locate, start-role, serve, restart, reset or stop
commitidnullThe commit this session needs served, merged into the integration branch when the served head does not already contain it
flowidnullThe flow whose dedicated identity is provisioned and whose folder receives the account record, the drafted document and the seed
enviddevThe stack the attested entry and the provisioned accounts belong to; an account of one stack is not an account in another
resumetokennullThe blocked branch’s token when re-entering after a stop

Steps

#StepParamsReadsWritesStops with
1Validate the gate and resumeresumerequest/request.json, @worktrees/sessions/central-runtime at the frozen generationINVALID_INPUT, SOURCE_DRIFT, NO_PROGRESS
2Bind the authority: the runtime, the device state, the projects and the approval — an id, or the environment’s declaration re-read and re-hashedservice, approval, env@worktrees/sessions/central-runtime for the inventory fingerprint and generation, @workspaces/device-state for each capability handle with its custody evidence, @workspaces/projects/<project>/<role>, the environment’s declaration when approval references it, @tools/secretsAUTHORITY_DRIFT, CAPABILITY_MISSING
3Recheck the inventory once before anything changes@worktrees/sessions/central-runtime, the declared resources re-observed once, @tools/gitINVENTORY_DRIFT
4Resolve the port claims against the projection, and observe who holds eachportClaims@workspaces/ports/<project> for the projected ports, @worktrees/sessions/central-runtime for their observed holdersPORT_CONFLICT
5Derive the delta between what is observed and what is desireddesiredState@worktrees/sessions/central-runtime for the observed state, request/request.json for the desired stateresponse/data/delta.json
6Apply the approved delta, one resource at a time, under an exclusive lease@worktrees/sessions/central-runtime, @workspaces/device-state for the handles by name@worktrees/sessions/central-runtime, response/data/delta.json, @tools/container, @tools/shellEFFECT_UNAUTHORIZED, SERVICE_UNAVAILABLE
7Climb the named rung for the bound route — bring the environment’s infra up, resolve its checkouts, start a role, or merge this session’s commit into the integration branch and serve, restart, reset or stop the one detached server, queueing behind a lease another session holds — then attest the entry: probe the endpoints, record the served head, what it contains and the evidence, and set the statusrouteKey, operation, commit, env@worktrees/sessions/central-runtime for the entry of that route with its server, lease and queue, @workspaces/projects/<project>/<role> for the role’s dev command, the integration worktree and the session branch merged into it, the environment’s declared infra, the endpoints re-observed once, @tools/git, @tools/http, @tools/container, @tools/shell@worktrees/sessions/central-runtime, response/data/delta.jsonSERVICE_UNAVAILABLE, PROVISIONING_UNAVAILABLE, INTEGRATION_FAILED, INVALID_INPUT
8Provision the flow’s identity against that entry: read the account record or create the account, set its password from the sealed name, write the record, draft what is absent and seedrouteKey, flow, env@worktrees/uat/<flow> for the account record, the flow document and the seed, @worktrees/_templates for what is absent, @worktrees/sessions/central-runtime for the entry’s identity declaration, @workspaces/device-state for the credential by name, @tools/secrets, @tools/http, @tools/browsercontrol, @tools/database@worktrees/uat/<flow>, response/data/account.json, response/data/delta.json, @tools/sourcewriteINVALID_INPUT, PROVISIONING_UNAVAILABLE
9Prove every required check@worktrees/sessions/central-runtime re-read against the branch’s complete proof set, @tools/httpresponse/data/checks.jsonPROOF_FAILED
10Write the receipt and emiteverything aboveresponse/response.md, response/response.json

A resume begins again at validation, reuses only unchanged fingerprinted observations, and consumes the exact delta; a resume that adds no authority, inventory, desired-state or scope change is NO_PROGRESS, and a re-observed inventory must arrive as a new fingerprint because the same fingerprint cannot yield a different answer.

Outputs

KindFileTypeRequired
platform-operation-receiptresponse/response.mdmdyes
deltaresponse/data/delta.jsondatayes
checksresponse/data/checks.jsondatayes
uat-accountresponse/data/account.jsondatano

Stops

CodeDisposition
INVALID_INPUTterminate
SOURCE_DRIFTterminate
NO_PROGRESSterminate
AUTHORITY_DRIFTterminate
CAPABILITY_MISSINGterminate
INVENTORY_DRIFTterminate
PORT_CONFLICTterminate
EFFECT_UNAUTHORIZEDterminate
SERVICE_UNAVAILABLEterminate
PROVISIONING_UNAVAILABLEterminate
INTEGRATION_FAILEDterminate
PROOF_FAILEDterminate

Next

WhenOperator
the routed checkout or its head no longer matches the frozen bindingworkspace.bind
the runtime a frontend surface must be audited against is now servingfrontend.surface.audit
the shared service is operated and the release that waited on it may continuerelease.deploy
the flow’s identity is provisioned and the run that waited on it may verify the flowuat.verify

Source: operators/platform-operate/operator.md.