npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@serve.zone/interfaces

v32.29.0

Published

Shared TypeScript interfaces and TypedRequest contracts for the serve.zone ecosystem.

Readme

@serve.zone/interfaces

@serve.zone/interfaces is the shared TypeScript contract package for the serve.zone ecosystem. It contains the public data shapes and TypedRequest interfaces used by Cloudly, Coreflow, Spark, Coretraffic, platform clients, SDKs, and external integrations to exchange infrastructure state without duplicating DTOs.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

Install

pnpm add @serve.zone/interfaces

Public API

The root export exposes six namespaces:

import { appstore, data, platform, platformservice, protocol, requests } from '@serve.zone/interfaces';

| Namespace | Purpose | | --- | --- | | appstore | App Store catalog, manifest, service requirement, and upgrade contracts. | | data | Durable platform object shapes such as clusters, services, deployments, images, domains, DNS entries, secrets, users, status, settings, backups, registries, BaseOS metadata, and task executions. | | requests | TypedRequest contracts for Cloudly and serve.zone control-plane RPC methods. | | protocol | The handshake two peers exchange when a session opens: what each side speaks, the oldest peer it accepts, and the named refusal when they cannot serve one session. | | platform | Current platform-service contracts for email, SMS, push notifications, letters, AI, databases, object storage, logging, backups, and SIP. | | platformservice | Legacy platform-service namespace kept for older consumers that still depend on the previous layout. |

This package intentionally has no service implementation logic. It is a stable vocabulary for services that need to agree on payload shape, method names, and response types.

Identifier Vocabularies

Two vocabularies name things in these contracts, and which one a member uses is part of the contract.

| Vocabulary | Rule | Members | | --- | --- | --- | | Canonical identifier | ^[A-Za-z0-9][A-Za-z0-9:._-]{0,199}$ — first character alphanumeric, up to 200 characters | organizations, clusters, services, namespaces, sessions, assignments, attempts, authorities, pools, endpoints and every content id derived from them | | Node id | ^[A-Za-z0-9_-]{1,128}$ — the URL alphabet, a leading - or _ included, up to 128 characters | every member that names a node of a cluster |

A node may be named -abc or _abc: enrollment, the runtime session registration and the Spark wire admit a node id that begins with a separator, so every member that names the same node admits one too. data.isClusterNodeId(value) is that rule, and it is the rule at every node-bearing member: nodeId on a session binding, a registration, an enrollment, a Spark heartbeat, a relay block, an assignment, a workload lease, a handoff lease, a DNS-lease renewal run, a protection receipt, an egress authority, a cluster VPN node, an ingress registration, a traffic bucket, a Corestore inventory and an isolated-restore node control; id on a router incarnation and on a node retirement; cloudlyNodeId on a cluster runtime target and on a secret runtime target; and placement.nodeIds on a service runtime spec. A service that stores or forwards a node id should judge it with the same reader rather than with the canonical one, which would refuse a node these contracts themselves enrolled and registered.

A replica id is the one composed name: a producer names a replica slot <node id>.<index>, counted from zero. data.isRuntimeReplicaId(value) reads it by decomposition — the part before the last dot in the node vocabulary, the index on its own and never zero-padded — and reads a name that carries no such index, a zero-padded node-a.01 among them, as an opaque slot name in the canonical identifier vocabulary.

WorkloadInit release verifiers should use the dedicated Node-compatible subpath:

import {
  validateWorkloadInitReleaseAttestationStatement,
  validateWorkloadInitReleaseIdentity,
  workloadInitReleaseContract,
} from '@serve.zone/interfaces/runtime/workloadinit';

@serve.zone/interfaces/runtime/workloadinit exposes only the WorkloadInit release identity, attestation, approval, authority, digest, and validator contracts. Its runtime dependency graph is limited to the immutable-image digest validator; unlike @serve.zone/interfaces/runtime, it does not load the general runtime graph, plugins.js, SmartCrypto, TypedRequest, or Corestore runtime modules.

Directional Image Streams

Image transfer contracts use @api.global/typedrequest-interfaces 7.1.0 and the directional VirtualStream protocol used by TypedRequest 8 and TypedSocket 8. Directions in shared DTOs describe the requesting peer:

| Contract field | Requester endpoint | TypedHandler endpoint | | --- | --- | --- | | requests.image.IRequest_PushImageVersion.request.imageStream | TVirtualStream<'send'> | TVirtualStream<'receive'> | | requests.image.IRequest_PullImageVersion.response.imageStream | TVirtualStream<'receive'> | TVirtualStream<'send'> |

The method names remain pushImageVersion and pullImageVersion. Each stream carries ordered Uint8Array chunks. TypedRequest reverses stream directions for the handler automatically; do not reverse the shared declaration yourself.

Consumers must replace the removed undirected IVirtualStream API with explicit transport-created endpoints. Senders use send() or writable, then close; receivers use receive() or readable, then explicitly accept() after draining EOF and completing application storage or delivery. completion confirms the receiver's accepted receipt, while closed confirms transport cleanup. The upload response's allowed flag permits sending; it does not confirm storage. Receiver rejection, aborts and failed completion must reach the caller. Existing deployment log and shell push-message contracts retain their message shapes.

Human Credential Administration

requests.admin.getHumanCredential and mutateHumanCredential describe human credential inspection and mutation for recently authenticated administrators. Operations rotate a password, revoke password login, or revoke existing sessions. Each successful mutation advances the generation and invalidates older human UI/API and OCI registry sessions. Upstream OIDC identity bindings remain intact.

Send the expected generation and a stable mutation ID. After a lost response, authenticate again and repeat the same request. A replay returns the original metadata without applying the operation again; inspect current metadata separately. Requests containing passwords must never be logged. Responses contain no passwords or verifiers. Cloudly owns validation, atomic persistence, and session enforcement; these shared contracts alone do not implement an endpoint.

Node Credential Administration

requests.node defines getNodeCredential, rotateNodeCredential and revokeNodeCredential for verified platform-infrastructure administrators. getNodeConfig now also requires identity; callers using the previous unauthenticated request shape must update. Its response remains the public IClusterNode, never a persisted backend document.

data.INodeCredentialMetadata separates spark and pallet purposes and exposes lifecycle state, generation, rotation-required status and session epoch, but no bearer, hash, socket peer or controller process identity. Infrastructure credentials do not grant organization or workload permissions.

Mutations require the exact generation and session epoch plus a stable mutation ID. Rotation takes the SHA-256 hash of a node-generated CSPRNG credential that the node has already durably retained with that mutation ID. Lost-response retries repeat the complete request and receive the original metadata, never newly minted plaintext. A replay result is historical and cannot authorize a current session. Treat rotation request hashes as sensitive in transport hooks and logs.

These types do not implement authentication, storage, enrollment or endpoints. Cloudly must verify current administrator authority, validate complete inputs, atomically persist the credential transition and immutable actor-bound receipt, and fence subsequent control effects against current durable credential/session authority. Node identity storage and transport integration must be qualified before enabling rotation or Pallet enrollment.

Spark Host Reporting

data.sparkNodeHeartbeatContract defines the HTTPS POST endpoint /spark/nodes/heartbeat, transport byte limits and protocolRefusalStatus, the status a refused offer is answered with. Its exact request snapshot contains a Spark-purpose bearer, the sender's protocol offer and ISparkNodeReport: fractional host CPU, memory and disk observations, Linux host facts, and the verified bundle version, source commit and manifest digest. It has no Docker or container-count fields. Local runtime readiness remains distinct from unverified workload readiness.

The route reads the bounded body, reads the offer with protocol.readProtocolOffer, negotiates it against its own sparkNode offer and answers a refusal with protocolRefusalStatus and an IProtocolRefusal body — all before the node is authenticated, so a peer of another major is refused by name instead of by a credential verdict it cannot act on. The receipt carries the controller's own offer, so an accepted node judges the session it just reported into.

The Swarm-era Spark runtime keeps its own four routes in data.sparkSwarmNodeContracts, each stating the same three facts as the route above — heartbeat (/spark/swarm-nodes/heartbeat), metricsSample, actionResult and swarmObservation, every one of them an { endpoint, maxRequestBytes, maxResponseBytes } — so one bounded read serves every Spark route. The bounds differ because the bodies do: a heartbeat states the node's whole runtime description, a metrics-sample answer carries every action queued for that node, and one observation carries up to 1024 observed Swarm nodes. That is a second runtime, not an older version of this one: a worker in coreflow-node mode posts those bodies and a pallet node posts this one, and the family retires with coreflow rather than with this release. ISparkSwarmNodeHeartbeatRequest is now owned here, so Cloudly and Spark no longer carry private copies of it, and every Swarm-era body — request and answer alike — carries protocol and is judged in the same order. For fleet cutover, that same observation may carry a bounded local Docker snapshot from the reporting node and, only when control is available, a manager-visible service/task snapshot. The existing node-token, reporter-session, sequence, digest and accepted-receipt rules authenticate both; no separate fleet-report route exists.

Each of the four routes has its validator here, so a server never writes its own member checks: data.validateSparkSwarmNodeHeartbeatRequest, data.validateSparkMetricsSampleRequest, data.validateSparkActionResultRequest and data.validateSparkSwarmObservationRequest. All four answer the same way — one string per refused member, naming the member, and an empty list for an admissible body — so a route table can hold them side by side. They read the envelope first (exact key set, the sender's offer, then the reporter's identity), then the payload: a heartbeat's metrics and full runtime description including each described serve.zone service, a sample's four observations and optional network rates, and an action result whose status is one a node can actually report, never pending. Bodies are judged member by member rather than as canonical bytes, because only the observation is digested and the others carry fractional CPU, memory and rate observations; every level is copied away from the caller's object first, so an accessor is refused instead of run. None of them authenticates a node or acts on the body.

Cloudly must authenticate the bearer against current Spark authority and fence credential generation and session epoch transactionally before recording host liveness. ISparkNodeHeartbeatReceipt contains only server-derived acceptance evidence; the sender must match its node ID and credential generation to its exact active identity. Neither a receipt nor the sender's observation time grants current authority or workload readiness. Persist only the report and receipt in IClusterNode.data.sparkNodeReport, never the bearer. Keep legacy reporting separate. This endpoint does not deliver or acknowledge operator actions.

The snapshot functions reject unknown keys, accessors, malformed identities and nonfinite/out-of-range numbers, then return detached frozen records. Transports own byte limits, timeouts and cancellation. These contracts do not implement a listener, credentials, persistence, freshness or shutdown.

Independent Node Enrollment

requests.node defines getNodeEnrollmentState for current Spark-authenticated adoption preconditions and enrollNode for atomic Spark/Pallet enrollment. These contracts do not implement endpoints, authentication, a database or a daemon.

The enrollment proposal binds the canonical HTTPS Cloudly origin, hostname, enrollment identity, original bootstrap proof hash and an exact ordered pair of independently prepared Spark/Pallet credential hashes and CAS counters. Fresh Jump starts both at zero; existing-node adoption rotates current Spark and requires Pallet authority to be absent. snapshotNodeEnrollment returns a detached, frozen snapshot; computeNodeEnrollmentDigest hashes strict canonical JSON under nodeEnrollmentContract.digestDomain, serve.zone/node-enrollment. Neither helper generates or persists credential material.

Transport proof is excluded from the digest to permit exact lost-response recovery. Bootstrap proof must hash to the original proof hash and is allowed only before a receipt exists. Pending-Spark proof must hash to the prepared Spark hash and is allowed only for an existing exact receipt. verifyNodeEnrollmentProof checks this binding and mode only: Cloudly must derive receipt state itself and fence live bootstrap/credential authority in the same owned transaction. Current Jump codes are 12 random bytes encoded as 16 canonical base64url characters.

bindNodeEnrollmentAcknowledgement checks the complete digest, both owners, exact next generations and unchanged adopted node ID, returning a detached frozen acknowledgement. Authenticate Cloudly before accepting it. The acknowledgement is immutable commit evidence, not ongoing authority or workload readiness. Server replay must still verify both active credential generations and hashes; reporter reconnect alone does not invalidate the credential. Spark and Pallet commit their local activation independently and converge after restart; there is no shared plaintext vault or cross-local-database ACID claim. Never log proof/request bodies or hashes, put them in URLs, or expose them through transport hooks.

requests.pallet defines the node-local preparePalletNodeEnrollment, bindPalletNodeEnrollment and activatePalletNodeEnrollment methods. They belong only on the protected root-owned Unix control socket, never a network router. Preparation requests initial Pallet authority (zero generation and session epoch) and returns only its independently retained credential hash. snapshotPalletNodeEnrollmentPreparation and bindPalletNodeEnrollmentPreparation validate that exact exchange.

Local confirmations explicitly distinguish a durable pending binding from the exact current active Pallet identity. bindPalletNodeEnrollmentBound verifies the whole enrollment digest and its pre-assignment node ID (null for fresh Jump). snapshotPalletNodeEnrollmentActivation captures the exact activation request, rejecting extra wrapper fields as well as malformed nested data. bindPalletNodeEnrollmentActive takes that complete activation request and verifies the full Cloudly acknowledgement, including both owners and the assigned node ID. Both confirmation binders return detached frozen snapshots captured before hashing. These are pure content checks: authenticate the local transport separately, and have Pallet prove its current owned state before issuing a confirmation. A historical receipt is insufficient, and Pallet activation does not imply Spark activation or workload readiness.

palletNodeEnrollmentContract specifies one four-byte unsigned big-endian length-prefixed UTF-8 JSON frame per direction, followed by write-half-close, at most 32768 request bytes and 16384 response bytes excluding the prefix. Implement the listener with half-open response support, strict EOF/trailing-byte rejection, bounded time/concurrency, root-only directory/socket permissions and drained cleanup. The package supplies no listener, permission checks or persistent state. No bearer, generic rotation operation or database access is part of this IPC API.

Node Runtime Routing Binding

requests.node.getNodeRuntimeBinding { nodeId, nodeToken } is a current Spark-node-authenticated read. Cloudly derives data.INodeRuntimeBindingRead from its current credential, node, cluster, durable runtime-controller, relay and cluster-runtime records. The answer contains the exact routing identity { cloudlyOrigin, nodeId, clusterId, controller, runtimeNamespace, relay }, the current { id, phase, generation } runtime reference and the Spark credential generation and session epoch that authenticated the read. snapshotNodeRuntimeBindingRead requires the runtime id to equal the routing cluster, and bindNodeRuntimeBindingRead binds the answer to Spark's exact immutable Cloudly origin, node and credential generation. Neither helper authenticates the server.

requests.pallet.bindPalletNodeRuntimeBinding and readPalletNodeRuntimeBinding belong on the existing root-owned Pallet enrollment control socket. Bind is absent-to-present only: the current active Pallet enrollment must name the same canonical Cloudly origin and node, an exact replay is idempotent and every different origin, node, cluster, controller, namespace or relay conflicts. Read requires the requested origin and node to equal both the active enrollment and the stored binding; an absent binding rejects. Spark applies and reads back the binding before starting runtime-serve. On an offline reboot it may read the exact persisted routing identity to select the relay, but that record grants no workload permission and no right to advance or run a cluster phase. Fresh authenticated runtime-session state remains the only workload authority.

The local operations carry no bearer, signing key, generic configuration field, phase mutation or caller-authored permission. nodeRuntimeBindingContract states the immutable local mutation and routing-only persistence rules.

A node can instead be driven by a controller on its own host, such as Onebox. data.INodeRuntimeLocalRoutingBinding is { nodeId, clusterId, controller, runtimeNamespace, registryHosts } with a controller of kind onebox; it names no Cloudly origin and no relay. nodeRuntimeLocalControllerContract fixes the transport: the controller is the TypedSocket client on Pallet's root-only Unix socket /run/serve.zone/pallet/controller.sock (mode 0600, server URL http://localhost), whose file permissions authenticate the peer. A node carries a Cloudly binding or a local one, never both, and the local binding, like the Cloudly one, grants no workload permission by itself.

The first request on a local connection is bindPalletLocalRuntimeController (see Authenticated Runtime Sessions). It is first bind or exact replay. Pallet answers data.INodeRuntimeLocalBindingConfirmation: the exact persisted binding plus the generation and SHA-256 hash of a bearer that Pallet generates and keeps. bindNodeRuntimeLocalBindingConfirmation binds that answer to the binding sent and to the credential the controller pinned in its own durable state at the first bind (null for that first bind). A different credential for the same binding rejects rather than being adopted, because it means the node lost the state the controller enrolled.

registryHosts lists, strictly ordered, the canonical host[:port] registries (isCanonicalRegistryHost) whose pull credential the local controller issues. isNodeRuntimeLocalRegistryWorkload is the local registry rule: a workload's registryHost, and its pullEndpoint when one is stated, must both be listed.

Service Machine Credentials

requests.admin.getServiceMachineCredential inspects redacted metadata; mutateServiceMachineCredential creates, rotates or revokes authority for one exact existing service and organization. ensure requires absent authority and a null expected generation. Rotation and revocation require the exact current generation. Retain the mutation ID and complete input for retry; a receipt replay returns historical metadata without restoring authority.

IServiceMachineGrant currently grants only platform:session. This is separate from deployment grants, human membership and infrastructure permissions. The backend must authenticate each JWT against the current active credential generation, expiry and exact service ownership. Structural snapshot helpers do not perform these checks. Credential changes, encrypted service SecretSet delivery and the replay receipt must commit in the same authorized transaction. The response contains only the immutable secret/version reference; no bearer or hash is returned. Revocation removes current delivery from the metadata.

Private Networks

requests.network defines organization-scoped network create/update/retire and service attachment operations. Mutations require a retained idempotency ID and an exact expected revision; null means no prior document. Cloudly must authorize each request against live canonical membership and policy, reserve aliases transactionally, reject cross-organization attachments, and retain historical receipts. These contracts do not implement the backend or node enforcement.

data.buildPrivateNetworkFqdn produces <alias>.n-<26 lowercase base32 characters>.o-<26 lowercase base32 characters>.internal. from server-owned immutable DNS keys. Aliases are lowercase ASCII labels unique per network. Display-name edits do not rename DNS. A sole attachment selects its search suffix; several attachments require an explicit default or no search suffix. Fully qualified names remain unambiguous across networks. Network policy permits member-to-member connectivity and explicitly configures or denies external DNS forwarding. Creating an alias does not publish public DNS, ingress or ports.

data.composeServicePrivateNetworkDnsPolicy(membership, networks) derives the service's network suffixes, the single selected search suffix, and the intersection of external forwarding permissions. Supply every attached network exactly once, with active state and matching canonical organization/DNS keys. Missing, extra, inactive or inconsistent network definitions are rejected. Forwarding requires every attachment to permit both the queried public name and the same exact upstream IP/port; a denied or empty intersection returns externalDns: null. The default network changes only short-name search. Nested suffix unions are intersected at DNS label boundaries and canonicalized without dropping permitted branches; the composed list can contain up to 1,024 suffixes across 16 networks. This pure helper returns detached policy metadata. Its caller must authenticate and fence the included membership/network revisions before issuing node authority.

The snapshot helpers validate and detach content; they do not authenticate it, reserve names, prove membership, or report applied state. Packet authority remains until an applied denial or independent fence. DNS snapshots have a separate maximum 15-minute validity, with positive TTLs capped at five seconds and negative TTLs at one second. DNS expiry does not prove packet revocation or permit identity reuse. Retirement and attachment responses describe desired or historical metadata; consumers must separately track outstanding node revocations and readiness.

IRuntimeNetworkProtectedAuthority declares the complete controller-owned IPv4 protection set, disjoint private workload/transit pools, protected resolver and platform endpoints, and every affected egress authority, including offline nodes. Its snapshot and digest helpers bind the exact predecessor and all declaration content. They cannot prove that an operator's inventory is complete. Install the union of old and new protection on every affected egress owner, or independently fence that owner, before exposing a newly allocatable pool. Removing an entry from the declaration is not a revocation acknowledgement. Prefix arrays are sorted lexically and nonoverlapping; pools and endpoints are sorted by ID; egress owners are ordered by canonical JSON of [nodeId, runtimeNamespace].

IRuntimeNetworkProtectionReceipt reports a worker's durable, joined native protection journal separately from projection admission. It binds a complete protected-authority reference, node/controller scope, authenticated reporter, boot identity and exact native journal reference to a monotonic receipt chain. A null nativeBarrier explicitly removes allocation eligibility. A boot or protection change requires new native journal evidence. These portable values do not inspect a kernel or authenticate their own producer.

reportRuntimeNetworkProtection uses the current authenticated physical peer. Its request binder accepts a historical outbox only against receiver-owned reporter history and identifies that use as historical. The response must match the exact sent receipt. bindRuntimeNetworkAllocationProtection requires the current persisted protection receipt and durable session for every declared egress owner, in canonical owner order. Missing, unavailable, stale-protection and superseded-session evidence reject. An offline owner cannot be omitted. The controller must fence all those records together with lease insertion, before reserving any handoff or workload address. No generic independent-fence flag is provided; such a mechanism needs its own verified owner. Protection receipts neither prove workload readiness nor release packet/address/name quarantine.

IRuntimeNetworkHandoffLease binds an immutable node/router incarnation to its protected-authority reference, transit subnet and peers, protocol-qualified source ports, nonzero conntrack zone and 128-bit label. The label is exactly 32 lowercase hex characters. Port ranges are inclusive, sorted by protocol then first port, and disjoint within each protocol. bindRuntimeNetworkHandoffLease verifies both digests, scope and transit-pool containment and returns detached values. It does not authenticate a projection or attest to an actual namespace/interface.

snapshotRuntimeNetworkHandoffLedger verifies at most 256 retained leases for one node/controller epoch, including quarantined allocations. It rejects host handoff-port collisions even across router/runtime namespace changes, and zone or label reuse within one router incarnation. The caller must transactionally supply the complete retained set, serialize allocation and fence controller-epoch changes. These are collision checks, not an IPAM allocator or a native capability. No expiry, empty conntrack dump, process exit or table removal establishes flow drainage or permits handoff identity reuse. Signed complete projections, live interface proofs and the separate router/host apply journal remain responsibilities of Cloudly and Pallet; neither packet admission nor readiness follows from these helpers.

IRuntimeNetworkWorkloadLease is the immutable material referenced by assignment.workload.network. It binds one execution attempt and router incarnation to a workload pool, dedicated unbridged linkSubnet, workload address, exact /32 sourcePrefix, and router-side gateway. The gateway also supplies dnsServer on port 53, because CRI DNS settings cannot encode a port. Canonical private point-to-point subnets through /31 are accepted; the owning CNI implementation must qualify its chosen layout. The source prefix, link subnet, VPN control prefix and host/router transit subnet have different roles. bindRuntimeNetworkWorkloadLeaseToAssignment verifies immutable assignment identity without a circular assignment digest. Membership, aliases, readiness and projection revisions never change this address material.

IRuntimeNetworkProjection contains complete relevant network definitions, service memberships and endpoint leases, including remote ready endpoints and declared services with no replicas. It carries the current protected authority, exact historical allocation authorities, local handoff, a maximum 15-minute DNS window and explicit packet/lease/handoff withdrawals. All arrays use the documented canonical ordering: networks and endpoints by ID, memberships by canonical [organizationId, serviceId], references by canonical complete reference, and withdrawals by canonical complete grant. Projections are bounded to 896 KiB, 128 networks, 256 memberships/endpoints, 16 historical authorities and 4,096 directed grants. These transport bounds do not assert native capacity; the node must preflight the actual SmartVPN, Smartnftables and DNS limits before effectful application.

validateRuntimeNetworkProjection checks complete digest and scope bindings, pool containment, disjoint link subnets, network/organization keys, aliases, resolver authorization and ready-replica uniqueness. It does not authenticate controller inventory, prove observation provenance or authorize allocation reuse. Cloudly must derive readiness from the current authenticated assignment report, retain all affected offline authorities and complete its allocation/barrier transactions before issuance.

An endpoint may publish node ports through the optional IRuntimeNetworkEndpoint.publishedPorts. Each IRuntimeNetworkPublishedPort binds one hostPort (1..65535, unique per node and protocol across the projection) to the workload's targetPort, optionally on an explicit uplink hostIp (never the wildcard or loopback; binding it to the node's uplink is Pallet's enforcement, because the projection carries no uplink fact), and carries the Cloudly authorization reference that permitted it: a published port without that reference cannot exist, and the projection signature covers every byte of it. An endpoint that publishes nothing omits the member entirely and keeps its exact canonical bytes and digest; a present member is never an empty list, so "publishes nothing" has exactly one encoding.

Operators author that authorization through getServicePublishedPorts and setServicePublishedPorts, modelled on the private-network membership pair. IServicePublishedPorts returns the current authorized list with its policy revision, or null when a service never had one. ISetServicePublishedPorts returns the accepted IServicePublishedPorts document with its new revision and a replayed flag, and carries expectedRevision (null for the first document), a retained mutationId for replay, and IRuntimeNetworkPublishedPortRequest entries of exactly protocol, hostPort and targetPort: the request accepts no hostIp (an omitted address means the node uplink) and no ranges. An empty list is a valid policy meaning the service publishes nothing. Callers never supply an authorization reference: Cloudly derives each projection entry's reference from the accepted policy revision and digest, and node-level host-port placement stays Cloudly's decision.

getRuntimeNetworkProjectionPacketGrants derives directed member connectivity and explicit local public/platform egress independently of DNS readiness. composeRuntimeNetworkProjectionDnsViews builds one union view per local workload source address, with every authorized FQDN and complete ready-replica A set. An empty array declares NODATA; absent/unauthorized names remain NXDOMAIN, and IPv4-only service names have AAAA NODATA. The view carries the existing forwarding intersection and zero or one search suffix. Pallet must prove the actual sandbox/veth/source binding, block private/bare-name forwarding, clip TTLs and convert the effective window from getRuntimeNetworkEffectiveDnsWindow (see DNS Lease Renewals) using its qualified boot/time authority. These helpers neither cache queries nor renew a lease.

The DNS composer accepts an optional second argument of exact local workload lease references. Selection happens before view expansion while the complete validated projection still supplies every eligible local or remote target and declared empty name. Omit it for all local views or pass [] for none. Unknown, remote, stale and duplicate references reject. Selection is captured before asynchronous validation and output retains projection order. This lets Pallet compose only its currently attached sources without duplicating membership rules; the references themselves do not prove native attachments or DNS authority.

The optional IRuntimeNetworkProjection.router member carries explicit router-origin egress selections and withdrawals. A projection that omits it retains its exact canonical bytes, digest and signature and grants no router-origin flows. New issuers can select resolverIds and platformEndpointIds from the current protected inventory; an empty selection denies all router egress. DNS forwarding policy, workload egress and inventory presence alone supply no router grant. The whole member is signed with the projection; it is not an unsigned runtime option.

getRuntimeNetworkProjectionRouterPacketGrants validates the complete projection and returns up to 96 detached exact grants. Each binds the current local handoff reference and its router transit source address to a selected destination ID, IPv4 address, protocol and port. Resolver selection explicitly authorizes both TCP and UDP at the declared resolver port. Platform selection authorizes only its declared transport tuple, for example a VPN relay endpoint. Every selected protocol must have a source-port allocation in that handoff. No public wildcard, workload source or alternate source address can be supplied in this selection.

Router withdrawals retain these complete grant bodies, including the old handoff and source address. Removing a selection, changing an inventory endpoint or retiring the handoff must explicitly withdraw the old grants. Unknown denials and denials overlapping current grants reject. Up to 4,096 retained withdrawals carry forward until the caller supplies its exact joined application of the preceding projection, with the same receipt boundary as workload withdrawals. These values do not prove packet drainage, native enforcement or allocation reuse. Consumers must compose workload, router and host grants and their separate withdrawals; they must also fence the actual native source, routing and process lifetimes. DNS expiry or readiness changes do not revoke packet authority.

A projection whose controller kind is onebox names a controller that runs on the node itself, so it has no other node: it refuses every endpoint whose lease is not placed on the projection's own node and runtime namespace. Projections of a cloudly controller keep their remote endpoints.

The optional IRuntimeNetworkProjection.host member exists only on onebox projections; any other controller kind carrying it rejects. It lets the node's own host namespace, for example Onebox's reverse proxy, dial exact local workload ports directly, with no loopback publication, no loopback DNAT and no change to martian filtering. A projection that omits it retains its exact canonical bytes, digest and signature and grants no host-origin flows. Each ingress entry names the exact lease reference of a local endpoint of the same projection, a protocol, the workload's own port and an authorization reference. The authorization is signed with the projection but is not part of the grant identity, so re-authorizing an unchanged port neither creates nor withdraws a grant. Entries are unique and strictly ordered; at most 1,024 are allowed (runtimeNetworkHostContract).

getRuntimeNetworkProjectionHostPacketGrants validates the complete projection and returns detached exact grants. Each binds the current handoff reference and its transit host address as the source to the lease reference, lease IPv4 address, protocol and exact port as the destination. Unlike router grants, host grants need no per-protocol source-port allocation in the handoff. Host withdrawals follow the router rules: removing a selection or retiring the handoff or lease must explicitly withdraw the old complete grants, unknown denials and denials overlapping current grants reject, and up to 4,096 retained withdrawals carry forward until the caller supplies its exact joined application of the preceding projection.

The optional IRuntimeNetworkProjection.workloadIngress member exists only on cloudly projections; any other controller kind carrying it rejects. It is how the cluster ingress workload reaches the workloads it routes to without a published host port: each grants entry names the exact lease reference of the ingress workload (source), the exact lease reference of the target workload (destination), a protocol, the target's own listening port and an authorization reference. Unlike the full-mesh workload grants, it needs neither the same organization nor a shared private network, it opens exactly one port, and it is one-way: nothing flows back except the replies of a connection the ingress opened. Both leases must be endpoints of the projection, they must differ, and at least one of them must be placed on the projection's own node. Entries are unique and strictly ordered by [source.id, destination.id, protocol, port]; at most 1,024 are allowed (runtimeNetworkWorkloadIngressContract). The authorization is signed content, not grant identity. A projection that omits the member retains its exact canonical bytes, digest and signature. getRuntimeNetworkProjectionWorkloadIngressPacketGrants validates the complete projection and returns detached IRuntimeNetworkWorkloadIngressPacketGrants ({ source, destination: { lease, protocol, port } }). Their withdrawals follow the host rules: an omitted grant needs its exact withdrawal, unknown or current denials reject, and up to 4,096 retained withdrawals carry forward until the exact joined application of the preceding projection is supplied. Cloudly routes a cluster ingress route to the target lease address and port once the grant exists.

The optional IRuntimeNetworkProjection.hostPlatformEndpointIds lists the ids of the protected authority's platform endpoints whose address the projection's node's own host carries, such as a relay listener or a Corestore beside the node on one machine. A node delivers workload flows to those endpoints locally instead of forwarding them. The list is sorted, unique, never empty when present, and every id must be a current platform endpoint; omitting it keeps the canonical bytes and states that no endpoint is local. It grants nothing: a workload still reaches only the endpoints it selects. The platform endpoint contract itself ({ id, address, protocol, port }) names no node, which is why this statement is per projection.

admitRuntimeNetworkProjection checks exact predecessor/replay identity and rejects changed same-generation content, regressed membership/readiness evidence, changed immutable address/DNS keys, and omitted packet grants without explicit withdrawal. Pending withdrawals/tombstones must carry forward until the caller supplies the exact previous projection reference from its own durable joined application receipt. That reference is never taken from an incoming ACK. Keep the accepted history and apply journal until native effects and DNS/allocation quarantine are settled; a complete new snapshot does not erase that history.

IRuntimeNetworkSigningAuthority is separate from human JWT signing. Install its current revision through the existing authenticated physical connection and commit it with a durable CAS fence. Newly enrolled nodes may bootstrap the controller's current key generation; existing trust cannot be reset to do so. Exact successor revisions rotate the Ed25519 public key; publicKey: null revokes it. Rotation/revocation stops acceptance under the previous key, and requires newly signed authority for DNS. It does not deny outstanding packets or permit allocation reuse.

The Node-only @serve.zone/interfaces/runtime export supplies createRuntimeNetworkSigningKey, signRuntimeNetworkProjection and verifyRuntimeNetworkProjection. Signing produces ISignedRuntimeNetworkProjection { authority, projection, signature }, and the signature covers the canonical envelope { domain, authority, projection } under the dedicated serve.zone/runtime-network-projection-signature domain, so it binds the complete projection and the exact signing-authority revision. Verification requires receiver-owned trusted authority and node scope; an envelope contains no key to trust. Private KeyObjects stay process-local; Cloudly persists their exported material only through its encrypted internal secret store. The dedicated requests.runtimesession key/projection push contracts bind the current physical peer. Their response acknowledges durable admission only, never application, readiness, independent fencing or pool activation.

The getRuntimeManagedVpnCredential method contract in requests.runtimesession uses IGetRuntimeManagedVpnCredentialRequest and IGetRuntimeManagedVpnCredentialResponse. Its request carries the exact current session and signed projection reference. The secret response repeats those bindings and supplies the hub tuple the node dials, the transport it dials it over (quic, the one transport a managed hub serves), the managed authority ID, the Noise server public key, the client keypair and the expiry in Unix milliseconds. The response states no TLS name: QUIC is dialled on the address alone. The hub is the node's own cluster's relay (see Cluster VPN Hub And Network). Keep the response process-local; never persist, hash, log or embed it in a signed projection.

snapshotGetRuntimeManagedVpnCredentialRequest and its response counterpart capture closed detached JSON shapes and canonical 32-byte key encodings. bindGetRuntimeManagedVpnCredentialRequest(request, projection, trustedSession) validates the complete projection digest and binds node, controller, namespace, physical-session identity and projection reference. The response binder takes (response, request, projection, trustedSession, now, renewal = null) and additionally requires the hub's exact tuple to be selected in router.platformEndpointIds, carrying the protocol of the credential's transport — udp for quic, as runtimeNetworkAddressPlanContract.hubTransports states. A relay therefore cannot name itself: the endpoint has to be one the node's signed projection already selected. Expiry must be after the caller-qualified time and no later than the referenced projection's effective DNS window (see DNS Lease Renewals); acceptance before that window starts rejects.

These helpers perform content validation. Callers authenticate and fence the current physical peer and projection before and after native work, qualify time independently, and retain ownership through revocation and shutdown. The native Noise implementation owns cryptographic validation and authentication. Credential delivery does not prove a connected VPN, TUN ownership, packet enforcement or workload readiness, and does not replace explicit packet withdrawals.

DNS Lease Renewals

A projection's dns window lasts at most fifteen minutes and is signed content, so a node's private DNS stops when the window ends unless a newer signed statement extends it. Re-issuing the projection would extend it too, but a node applies every new projection as new network state, which restarts its data plane. IRuntimeNetworkDnsLeaseRenewal extends the window and nothing else: it carries the node scope (controller, nodeId, runtimeNamespace), the exact projection reference it renews, a sequence, a fresh dns { issuedAt, notBefore, expiresAt } window and its digest. It names the projection by reference, so it never joins the projection chain and never changes what the node applied. The new shapes carry no schemaVersion and no version suffix; the installed package version is the protocol version.

issuedAt is the start of the window's slot, not the moment of signing: Cloudly signs renewals ahead of time on a grid, so the fifteen-minute rule (maximumDnsLeaseMs, the same limit a projection's window has) is measured from the slot. computeRuntimeNetworkDnsLeaseRenewalDigest hashes every field except digest under its own domain, and validateRuntimeNetworkDnsLeaseRenewal checks structure and digest only; a digest authenticates nothing.

The Node-only @serve.zone/interfaces/runtime export signs and verifies renewals with the same authority and key that sign the controller's projections, under a separate signature domain. signRuntimeNetworkDnsLeaseRenewal(renewal, authority, privateKey) produces ISignedRuntimeNetworkDnsLeaseRenewal { authority, renewal, signature }. verifyRuntimeNetworkDnsLeaseRenewal(signed, trustedAuthority, trustedScope, projectionAuthority) takes the authority and scope from the node's own stored trust, never from the envelope. projectionAuthority is the reference of the authority revision that signed the projection the node admitted, and a renewal verifies only when it was signed under exactly that revision. Rotation and revocation end renewals exactly as they end projections: nothing signed under an earlier revision verifies after, and a renewal signed under a rotated revision does not renew a projection signed under the one before. A renewal never closes a key gap; after rotation, DNS continues only with a newly signed projection.

admitRuntimeNetworkDnsLeaseRenewal(renewal, currentProjection, previousRenewal | null, trustedScope, now) is the pure admission decision after verification. The projection and the previous renewal are the node's own admitted state, and now is its caller-qualified clock, read before the first await like every other input. It admits a renewal only when:

  • the renewal and the projection are in the trusted scope, and the renewal names the current projection's exact reference. Once a successor projection is admitted, every renewal of its predecessor is refused, and a renewal never introduces a projection the node has not admitted;
  • its sequence is higher than the previous renewal's, with gaps allowed, or equal with byte-identical content, which is answered as replay whatever now is, so re-delivery is idempotent. The same sequence with any other content is refused;
  • its window is current: notBefore <= now < expiresAt. Admitting a window that has not opened would displace the coverage the node has now, so a sender delivers a window only once its slot has opened; a renewal refused for arriving early is simply delivered again once it has. An expired window is refused as well;
  • its window does not move issuedAt back and ends later than the previous window. Without a previous renewal, the projection's own window is the baseline. Windows need not touch, so a node whose lease lapsed can still admit the next renewal it is given.

The caller stores the admitted renewal in the same transaction as its trust fence, and deletes it in the transaction that admits a successor projection. Admission is not conversion: the node still turns the window into a deadline with its qualified clock, and must not use a window before its notBefore.

requests.runtimesession.IReq_Controller_Pallet_ApplyRuntimeNetworkDnsLeaseRenewal (applyRuntimeNetworkDnsLeaseRenewal) delivers one renewal as IApplyRuntimeNetworkDnsLeaseRenewalRequest { session, signed }. bindApplyRuntimeNetworkDnsLeaseRenewalRequest(request, trustedSession) requires the node's current physical-session binding and a renewal in that session's scope. It does not care who sent the request: a cluster relay pushes under the binding the node obtained itself. The answer, IApplyRuntimeNetworkDnsLeaseRenewalResponse { status, renewal }, repeats IRuntimeNetworkDnsLeaseRenewalReference { projection, sequence, digest }. bindApplyRuntimeNetworkDnsLeaseRenewalResponse(response, sentRenewal) compares it with the exact renewal that was sent. The ACK asserts durable admission only, not that the node serves DNS.

A cluster is outbound-only, so while its relay cannot reach Cloudly nobody can sign a new window. Cloudly therefore hands the elected relay a run of renewals it signed ahead of time, with requests.cluster.IReq_Cloudly_Relay_HoldRuntimeNetworkDnsLeaseRenewals (holdRuntimeNetworkDnsLeaseRenewals): IHoldRuntimeNetworkDnsLeaseRenewalsRequest { nodeId, projection, renewals } answered by { held }. Each request replaces what the relay held for that node, and an empty run holds nothing. The relay keeps the run in memory only, pushes only the renewal whose window is current and only while it has no Cloudly session (escrowRelease), and holds no key and no trust. snapshotHoldRuntimeNetworkDnsLeaseRenewalsRequest checks the rules a relay can evaluate without the projection itself; the node still measures the first window against its admitted projection, and every window against its clock, when it admits it. The run must have:

  • one node, one projection and one signing authority revision, in one scope;
  • strictly ascending sequences, each window extending the one before;
  • at most maximumEscrowedRenewals (32) renewals;
  • at most maximumEscrowHorizonMs (four hours) from the first window's issuedAt to the last window's expiresAt. On the intended grid of fifteen-minute windows every ten minutes, the horizon allows 23 windows, so it is the limit that binds.

validateHoldRuntimeNetworkDnsLeaseRenewalsRequest adds every renewal's digest check and verifies no signature. bindHoldRuntimeNetworkDnsLeaseRenewalsResponse(response, sentRequest) requires held to equal the number of renewals sent.

A hold is the one call whose outcome the controller cannot read back from its own records, so the refusal is the whole answer. data.holdRuntimeNetworkDnsLeaseRenewalsRefusals is the frozen list of names a relay leads its refusal with — escrow-run-invalid, escrow-node-not-carried, escrow-run-foreign-session, escrow-run-stale, escrow-run-unordered and escrow-cloudly-only — with data.THoldRuntimeNetworkDnsLeaseRenewalsRefusal as their union. The relay writes <name>: <reason> and the controller matches the name, so neither side keeps its own copy of the vocabulary.

The horizon is also the revocation latency: a detached cluster keeps DNS authority until its last held window ends. So a controller must not release an address or a DNS name before the latest expiresAt it has signed for that node. Renewals extend DNS only. They grant no packet authority and cannot introduce new network state, and they do not extend an already-issued VPN credential; a newly issued one may be bound to the renewed window.

getRuntimeNetworkEffectiveDnsWindow(projection, renewal | null) is the one rule for the window a node may use: the admitted renewal's if there is one, else the projection's own. renewal is the bare IRuntimeNetworkDnsLeaseRenewal that admission takes and returns, which is what a node stores; Cloudly passes signed.renewal. It checks digests and that the renewal names exactly that projection, but verifies no signature. Controller and node use it for every limit tied to the window, and bindGetRuntimeManagedVpnCredentialResponse takes the same bare admitted renewal as an optional last argument, so a newly issued managed-VPN credential may run to the end of the renewed window instead of the projection's original one.

import { data } from '@serve.zone/interfaces';
import { signRuntimeNetworkDnsLeaseRenewal, verifyRuntimeNetworkDnsLeaseRenewal } from '@serve.zone/interfaces/runtime';

const renewal: data.IRuntimeNetworkDnsLeaseRenewal = {
  ...scope,
  projection: { id: projection.id, generation: projection.generation, digest: projection.digest },
  sequence: 1,
  dns: { issuedAt: slotStart, notBefore: slotStart, expiresAt: slotStart + 900_000 },
  digest: `sha256:${'0'.repeat(64)}` as data.TSha256Digest, // well-formed placeholder, replaced below
};
renewal.digest = await data.computeRuntimeNetworkDnsLeaseRenewalDigest(renewal);
const signed = await signRuntimeNetworkDnsLeaseRenewal(renewal, signingAuthority, privateKey);

// On the node: stored trust, then the node's own admitted state and qualified clock.
const verified = await verifyRuntimeNetworkDnsLeaseRenewal(
  signed, storedAuthority, nodeScope, admittedProjectionAuthority);
const { renewal: admittedRenewal } = await data.admitRuntimeNetworkDnsLeaseRenewal(
  verified.renewal, admittedProjection, previousRenewal, nodeScope, qualifiedNow);
const window = await data.getRuntimeNetworkEffectiveDnsWindow(admittedProjection, admittedRenewal);

Runtime Network Address Plan

data.IRuntimeNetworkAddressPlan is the address space an administrator gives the runtime network, and the single input Cloudly composes the protected authority from: { id: 'address-plan', revision, prefixes, pools, resolvers, platformEndpoints, vpn: { controlPrefix, hubPrefix } }. Pools, resolvers and platform endpoints use the protected authority's own element shapes. controlPrefix is the private prefix VPN control addresses are allocated from, and hubPrefix is the protected prefix every cluster's VPN hub binds inside. The hub endpoints themselves are no administrator's input: each cluster's relay reports what it bound, and the composition turns that into platform endpoints, so platformEndpoints never lists one.

snapshotRuntimeNetworkAddressPlan refuses any plan that could describe an authority the authority contract refuses: it runs snapshotRuntimeNetworkProtectedAuthority over the plan's own sets, so overlapping pools, more than 16 resolvers and a resolver or endpoint outside prefixes or inside a pool are all refused by that one validator. On top it requires both VPN prefixes to sit inside prefixes, to overlap no pool, to hold no resolver or platform endpoint, and never to overlap each other — control addresses live inside the tunnel, hub endpoints on the underlay. controlPrefix is additionally a private prefix no longer than /30 (runtimeNetworkAddressPlanContract.maximumControlPrefixLength); no minimum length is stated, because the private-range rule already keeps it at /8 or longer. data.runtimeNetworkVpnControlPrefix(value) is that reader on its own, exported because a cluster's VPN network repeats the prefix its hub binds and has to read it exactly as the plan does.

Every list of a plan is stated in one canonical order, and a plan is never reordered for its writer: prefixes strictly ascending by the prefix text, and pools, resolvers and platformEndpoints strictly ascending by id. Both compare as strings, so the order is lexicographic, not numeric — 100.64.0.0/10 comes before 20.0.0.0/8, and resolver-10 before resolver-9 — and a value stated twice breaks it as well. A list out of order is the one plan refusal the contract names: snapshotRuntimeNetworkAddressPlan (and admitRuntimeNetworkAddressPlanChange through it) throws data.RuntimeNetworkAddressPlanStructureError, whose violation is { field: 'prefixes' | 'pools' | 'resolvers' | 'platformEndpoints', rule: 'order' } and whose message quotes nothing from the plan. Every other refusal stays the contract's generic rejection.

try {
  data.snapshotRuntimeNetworkAddressPlan(plan);
} catch (error) {
  if (error instanceof data.RuntimeNetworkAddressPlanStructureError) {
    error.violation; // { field: 'prefixes', rule: 'order' }
  }
}

data.IRuntimeNetworkVpnHub { clusterId, address, quicPort } is one cluster's hub as its relay bound it. runtimeNetworkVpnHubEndpoints(hub) is the one derivation of what it contributes: <clusterId>:quic on udp, one endpoint per row of runtimeNetworkAddressPlanContract.hubTransports. That table has one row, because a managed hub terminates TLS on its QUIC listener alone and no other transport of it can be dialled over a protected connection. Every reader calls the derivation — the composition that seals the authority and the router selection that names which endpoint a node may dial — so two readers can never derive two ids for one hub. composeRuntimeNetworkProtectedAuthority(plan, frame, hubs) is the composition itself: the producer supplies the frame (TRuntimeNetworkProtectedAuthorityFrame: authority id, generation, controller, previous reference and egress authorities) and the hubs of the clusters that registered one, and receives the complete authority with its digest, so the validator and the protection producer can never compose differently. Each hub's address must sit inside vpn.hubPrefix and one cluster is named once; an empty hubs composes the authority of a runtime network whose clusters have no hub yet. One hub costs one of the authority's 64 platform endpoints, so 64 clusters fit one authority.

A single host that carries both a cluster's hub and platform endpoints, for example the relay listener and a Corestore, holds more than one address. The hub address sits inside vpn.hubPrefix, as every hub's does. The plan's own platform endpoints may not: they sit on another address of the same host, inside prefixes, outside every pool and outside both VPN prefixes. Several endpoints may share that one address on distinct ports, because the authority requires only each address:port:protocol to be unique. For example, with hubPrefix 192.0.2.0/28, the hub binds 192.0.2.1 and the plan lists the relay listener and Corestore on 192.0.2.17 with two ports. The node's projection then names those endpoints in hostPlatformEndpointIds.

admitRuntimeNetworkAddressPlanChange(previous | null, next) is the pure decision for a plan write at the following revision; any other revision is a contract violation. Leases and the managed VPN outlive a plan revision, so it answers:

  • unchanged when the content equals the stored plan; Cloudly writes nothing;
  • refused with plan-vpn-immutable when either VPN prefix differs, plan-pool-removed when any pool is gone or changed its purpose or prefix, and plan-prefix-shrunk when the new prefixes, however split, no longer cover every address the old ones did;
  • accepted with the ids of the resolvers and platform endpoints the change removes or changes. An entry that keeps its id but differs in any field counts, so moving it goes through the same reference check as removing it.

TRuntimeNetworkAddressPlanRefusal adds plan-resolver-referenced and plan-endpoint-referenced, which only Cloudly can decide against live references, and plan-unsorted, which Cloudly answers for a RuntimeNetworkAddressPlanStructureError with the list as its reference, so every plan refusal has one type. requests.network carries setRuntimeNetworkAddressPlan { identity, expectedRevision, plan } (expectedRevision: null when no plan exists yet) and getRuntimeNetworkAddressPlan, which answers null until the first plan is set.

Node Network Readiness

requests.network.getRuntimeNetworkNodeReadiness { identity, nodeId } answers data.IRuntimeNetworkNodeReadiness: ready: true with nothing missing, or ready: false with at least one TRuntimeNetworkNodeReadinessGap. The gaps follow the node producer's order: the node joins the protected authority's egress (egress-pending), every egress owner reports current protection (protection-receipts-pending, naming those owners, at least one), a handoff is reserved (handoff-pending), the router selection carries it (selection-pending), the node's acknowledged projection carries it (projection-pending), and the node is a managed VPN member (vpn-member-pending).

data.IRuntimeRouterIncarnation { id, incarnation } is a node's router incarnation, from which its handoff and router incarnation ids derive; snapshotRuntimeRouterIncarnation checks the record. reincarnateRuntimeNetworkRouter { identity, nodeId, expectedIncarnation } advances it, so the node producer reserves the router a fresh handoff, and answers with the new incarnation.

Node-Bound Runtime Assignments

The data namespace exports IRuntimeAssignment, canonical digest helpers, evaluateRuntimeAssignment, and assignment observation validators/evaluators for Cloudly/Onebox controllers and Pallet nodes. These are shared contracts; they do not install a runtime, schedule containers or expose an RPC endpoint.

Each assignment binds a controller incarnation, organization, stable node and replica IDs, one immutable execution attempt, image/configuration and opaque network/storage/secret references. Group and site IDs are nullable topology provenance. Those workload references are also the authority vocabulary: data.runtimeWorkloadAuthorities is ['network', 'secrets', 'storage'], and data.requiredWorkloadAuthorities(workload) names the ones this workload cannot run without — filtered out of that vocabulary and sorted, so the answer is duplicate-free and compares byte for byte against the resolvedAuthorities a node stated when it registered. data.isResolvedWorkloadAuthorities(value) is the same rule read the other way, for a receiver checking a list it was sent. Canonical is strictly increasing in the code-unit order of the names themselves — a rule a peer in another language implements from the vocabulary alone, rather than from the order this package happens to declare it in — and both directions compare through that one rule, so neither can drift from the other.

workload.registryHost is the registry that published the image, which is the publication identity the image release is bound to, and it is never rewritten. workload.pullEndpoint is the optional host[:port] the node fetches the bytes from instead — a cluster whose relay forwards the registry states the relay's own origin, so a node pulls inside its cluster and nothing cluster-side dials the control plane. data.buildRuntimeAssignmentImageReference(workload) is the one place that choice is made: pullEndpoint ?? registryHost, digest-pinned either way, so the endpoint decides reachability and never content, and a controller and a node cannot disagree about the reference. Absence stays absence: an assignment that states no endpoint is different content, and so a different digest, from one that does.

All fields except the digest itself participate in a domain-separated SHA-256 digest. Digests provide integrity and compare-and-swap identity; authentication must separately establish the trusted controller/node scope.

An attempt starts at generation one with run, then advances through stop-preserve and remove-runtime-preserve-storage using exact predecessor generation/digest references. Exact retries return replay; conflicts, stale revisions, gaps, changed execution specifications and resurrection are rejected. Consumers must atomically persist the evaluator's detached snapshot before effects, retain removal tombstones and storage, and serialize ownership of each replica. Omission causes no change. A new attempt requires separate admission proving any older exclusive writer stopped or fenced. The supported offline policy is continue-node-bound; no heartbeat timeout or lease expiry proves a writer absent.

Observations bind the exact assignment, authenticated reporter session, durable per-assignment sequence and digest. Reconnect does not reset the counter. Observation history must reference the same assignment revision or its exact predecessor; receivers process each disposition's observations in order. Session authorization, clock/freshness policy and durable receipt persistence belong to the receiving service. Readiness requires matching running image evidence and run intent; assignment acceptance alone is never readiness. A valid observation can describe drift (such as a removed runtime while intent remains run), and does not authorize storage relocation or prove fencing.

Resolved Runtime Configuration

data.IRuntimeConfig seals the public environment, working directory, resource and identity policies, target ports, readiness timing and log limits together with the immutable image invocation. `computeRuntimeConfig