Changelog
Release notes for the better-compute packages and the documentation site, every notable change, newest first.
Changelog
All notable changes to the better-compute packages are documented here. The format is based on
Keep a Changelog, and the project follows
Semantic Versioning. Every package in packages/ shares one version.
Unreleased
0.1.1 (2026-10-07)
Better IAM 0.3 support. Every package now accepts Better IAM >=0.2.0 <0.4.0 (dependencies and peers), so
npm install better-compute better-iam resolves one Better IAM, the current 0.3.x, instead of a 0.3 umbrella beside
the 0.2 packages 0.1.0 asked for.
Changed
- Better IAM range.
^0.2.0becomes>=0.2.0 <0.4.0on every@better-iam/*andbetter-iamdependency and peer. The workspace builds and tests against 0.3.0 (its full suite and the IAM contract tests pass); 0.2.x keeps working. Better IAM 0.3's breaking changes do not touch Better Compute: it declares none of the newly reserved principal or resource attribute names, and its resource resolver returns noclassification.
0.1.0 (2026-10-07)
The first release on npm: the umbrella package better-compute and 26 @better-compute/* packages, all at 0.1.0.
It needs Node.js 22.12 or later, PostgreSQL 16 or later (PGlite for development and tests) and Better IAM ^0.2.0.
Added
- Control plane.
betterCompute()runs the API, gateway and worker in one process or separately. PostgreSQL is the source of truth: bookings are guarded byEXCLUDEconstraints and all SQL reads one clock,compute_now(). Every mutation makes one Better IAM decision; fleet paths (heartbeats, inventory, commands) make none. Stores for PostgreSQL and PGlite ship in@better-compute/postgres. - Capacity and reservations (
@better-compute/capacity). Pools, selectors, NVLink- and NUMA-aware placement, quotas, previews and reservations for whole GPUs, MIG partitions and shared GPU slots. Reservations also book host resources (vcpu,memoryGiB, hugepages) and hand cgroup limits and a NUMA-local cpuset to the node. Usage is metered in hourly windows. - Bare metal (
@better-compute/metal,@better-compute/provision). Enroll, inspect, commission, deploy, release, retire and rescue workflows over BMC and PXE, driven by a workflow engine with profiles and a signed image catalog. A machine returns toreadyonly after an attested wipe. Also dedicated-root leases, two-phase BMC password rotation, and GPU health remediation within a pool's disruption budget. - VPS, sandboxes and volumes (
@better-compute/vps). Instances on your own hosts (IPAM, flavors with NUMA, pinning and hugepage placement) or on providers (@better-compute/provider-hetzner,@better-compute/provider-proxmox). Sandboxes add templates, TTLs, warm pools, snapshots and SSH exec with short-lived certificates. Sandbox volumes and persistent host volumes attach to instances. - Kubernetes workers (
@better-compute/provider-kubernetes). bcd runs as a DaemonSet and adopts a cluster's nodes and GPUs into a pool; reservations withbinding: 'kubernetes'hand devices to the kubelet through device plugins or a DRA driver. - Gateway and protocol (
@better-compute/gateway,@better-compute/protocol). Daemon sessions over gRPC with mutual TLS, liveness, command dispatch, and join, renew and secret forwarding. The generatedbettercompute.agent.v1wire contracts are frozen. - PKI and the destructive-batch quorum (
@better-compute/pki). Local CAs, SPIFFE node certificates, sealed join tokens, attestors (join token, TPM, cloud instance identity, x509 proof of possession), command signing, a sealed secret store and broker, and trust-root rotation. Destructive command batches can require a quorum of approvers (commandBatches,pki.approvers).@better-compute/auditadds signed Merkle checkpoints over the audit log. - Better IAM integration (
@better-compute/iam). The IAM plugin and catalog, the authorization projection, an embedded or remoteIamPort, and the usage sink, on Better IAM^0.2.0from npm. - CLI (
@better-compute/cli, thebetter-computecommand). PKI setup and certificate issuance, the bcd install script, capacity shortcuts,iam setupand release signing. - MCP (
@better-compute/mcp). Model Context Protocol tools for pools, capacity, GPU reservations, instances and sandboxes, gated by Better IAM with confirmations for risky actions. - Clients and consoles.
@better-compute/clientis a typed, browser-safe API client with live$watch.@better-compute/console-kitprovides framework-free view models for consoles. - Testing kit (
@better-compute/testing). Fixtures, the simulatedFakeDaemon, a sim clock, the fleet simulation and conformance runners. - More packages.
@better-compute/events(signed webhooks and an SSE stream),@better-compute/fleet(fleet configuration as code),@better-compute/observability(Prometheus metrics),@better-compute/rollout(signed bcd releases and wave rollouts) and@better-compute/driver-sdk(out-of-process drivers). - The Go daemon bcd (
daemon/). The node agent is built and tested end to end against a real gateway on the fake-hardware build; the site and ramdisk modes are covered by Go unit tests. The release pipeline (goreleaser, SBOMs, cosign signatures, SLSA3 provenance) is in place, but this release publishes no bcd binaries.
Known limitations
- No real-hardware runs. Everything is tested against fakes and simulations: no real server has run bcd, and the hardware gates (a GPU host, a KVM host, the reference benchmark machines) have not run. Local test runs and the benchmark numbers use PGlite rather than a PostgreSQL server.
- bcd binaries are not released. The install script and self-update need a published bcd, so until a release
carries binaries, build bcd from
daemon/with Go. - See the roadmap for the state of every phase.
Development history (pre-0.1.0)
The internal notes kept while the packages were built, before the first release. They cite sections of PLAN.md
and commit hashes, and are kept for reference; the 0.1.0 entry above summarizes them.
-
Round 5, the complete node daemon (PLAN §3.8, v1.1):
- Host resources on every host:
vcpu,memoryGiB,hugepages2Mi,hugepages1Girows from inventory (capacity.hosts,policy.hostReserve). VPS hosts' memory now excludes hugepage pools. - Reservations take
resources(vcpu,memoryGiB,hugepages1Gi) and default to the pool's per-GPU share (policy.perGpu, else the smallest host share). Host resources are not charged to quota.capacity.previewbooks the same. DeviceAssignment.limitscarry cgroup limits and a NUMA-local cpuset (without the host's reserved CPUs) to bcd.binding: 'kubernetes'works on pools withpolicy.kubernetes. bcd hands those devices to the kubelet: device plugins or the DRA drivergpu.bcd.dev(gpuApi). Releasing a bound one keeps its GPUs and host share booked, and billed, until the node reportsAllocationReleased(pods let go), a lost node, or the booking's end. The placer used to re-book them under running pods: 55/240 failed bindings in the 12-node sim. Meanwhile the reservation carries theDevicesHeldcondition. A booking that pods still hold at its end is extended in 5-minute steps while the devices are free.- bcd advertises the Hello capabilities
devices.limitsandbinding.kubernetes. Reservations that book host resources, or bind to Kubernetes, place only on nodes that advertise them. An older bcd would drop the limits or the binding. - Flavors take
placement(numaAffine,pinned,hugepages). Hugepage guests book hugepages and are charged asmemoryGiB. Pinned guests take isolated CPUs first. Guests that don't get their placement carryPlacementDegraded. Guests of pools that overcommit memory get a balloon. - Guests get their IPAM gateway and DNS (
setIpPool({ dns }),InstanceNic.gateway/nameservers). - Agent memory:
sandboxVolumes, persistent host volumes (InstancesSection.volumes,InstanceSpec.volumes). Placement takesonlyNodes. - Extension kind
pool-policy: provision refuses host policies nodes can't take, atpools.create/update. - Telemetry specs carry
headersRefandresourceAttributes(nodeTelemetryModule,PoolPolicy.telemetry). - Security:
trustedProxies: behind a load balancer, IAM sees the caller, and fails closed.- Hello capabilities
instance.ssh-host-only,instance.placementandinstance.volumesgate where sandboxes, placed flavors and volumes land. - Hosted-Kubernetes join tokens land nodes
tenant-controlled. - Slots per shared GPU are capped at 48.
- MCP
reserve_gpustakesvcpu,memoryGiBandkubernetes. - Breaking (IAM):
sandboxVolumes.createis decided oncompute-sandbox-volume/<draft id>, whose projection carries the requestedsizeGiB, instead of the tenant (6cb30e9). Policies that granted it oncompute-tenantstill reach it through the pool parent; policies that bound volume size now see it.sandboxVolumes.resizestages the new size the same way. - Breaking (API):
sandboxVolumes.listdefaults to the caller's own volumes; passscope: 'all'for everyone's (77bf9f5). - Breaking (metrics): bcd's
bcd.instance.memory.balloonis nowbcd.instance.memory.balloon.reclaimed(9bdd43a). It reports flavor memory minus current guest memory, only for guests with a balloon. Dashboards and alerts on the old name need updating. - Hosted-Kubernetes bcd uses the kubelet's credentials (e7d0765; NodeRestriction confines it to its own Node), never a service account.
- CI builds the DaemonSet image (daemon/Containerfile) and server-side dry-runs the rendered manifests on a kind cluster.
- Host resources on every host:
-
Round 4, server/core/mcp/client:
- Security: admissions decide on the committed row (
IamPort.refreshResource; §12.4 "draft in memory before require" was unimplemented, soextenddecided on stale projection rows: BoundedExtend allowed 72 h + 1 h). A node reports only its own allocations. Withpki.commandSigning, a reservation goes active only on the node's own signedAllocationBound(pkiAllocationBindingCheck). The secret broker releases an instance's user data only when it names a secret of the instance's own tenant. Certificate roles live in the Subject OUbc-role:<role>(no private OIDs; Go cannot parse the 2.25 arc). - Envelope: async-with-wait (
MethodDefinition.poll,wait: { timeoutMs }),MethodAdmission.check(budget checks outside transactions, nodenied), W3Ctraceparentonto enqueued commands. - Server: audit sinks (
sinks.audit, module extensions), module-listed event sinks and scheduler plugins;sinks.usagerefused.GET {basePath}/downloads/bcd/{version}/linux-{arch};supportBundlespresignedlogs.collectuploads;projects.archive,commands.cancel,usage.export; selfCheck §14 operations findings; fewer statements per join; the node pass wakes started reservations on connectivity/schedulability changes;siteNodeSpec sections merge per field (NodeSpecPart);vps-hostnodes may be declared lost. - Core/proto (additive): PoolPolicy runtime/singleTenant/workloadIdentity, InstanceSpec allocationId/nics, CapacityPort.reserve admission, ProviderImpl.identify, Reconciler.role, PlacementRequest.nodeLabels, SiteSpec.cacheImages;
driver.invokepayloads, WorkloadToken frames (sealed JWE, purposeworkload-token), StatusReport.pressure; catalog rows providerAccounts.bootstrap, workflows.pause/resume, metal.unrescue. - MCP:
iamConfirmations(per-request polling),remoteMcpIam(the gate over HTTP IAM), reservation and instance tools. Client:$watch. - Later:
- Sandboxes are a product feature (D24, user decision); the design is PLAN §3.7.
- vps
instances.createwaits (wait: { timeoutMs }) and applies the pool's budget policy (SPEND_LIMIT_REACHED). - A node dedicated to one tenant wakes pending work (
mayBeSchedulableSql). - Ramdisk certificates allow the commissioning kinds under their real names (
inventory.refresh,disk.wipe,logs.collect); before this, commissioning could not inspect or wipe. - Proto
Hello.trust_version/StatusReport.trust_versionfor the command-root switch gate. iamGuard/BETTER_COMPUTE_IAM_GUARD=warn|throwreports or refuses an IamPort call made inside a compute transaction (§8.1);computeFixturedefaults tothrow.- Sandboxes seams: paused instances,
restore_from,instance.snapshotmessages, runtimepause/resume/snapshot. - Workload tokens are refused for suspended or deleted tenants.
- MCP
create_instancewaits for the instance to start; MCP sandbox tools; FleetConfigsandboxTemplates. - Sandbox seams:
InstanceSpec.network_policy(egress/private/none). - CI:
- nightly workflow: simulation plus 10k cold start, the IAM-guarded suite, the whole suite on Postgres, and a green-night streak;
- the bcd release pipeline: SBOMs, keyless cosign, SLSA3 provenance;
- the API surface freeze check in
lint:repo.
- The §16 gateway gate is met on a workstation: 5k mTLS sessions, 0 drops, dispatch p99 26 ms.
- v1.0 destructive-batch quorum, server side: the
quorummodule (commandBatchesget/list/scope/approve/cancel, batch expiry) andpki.approversin the trust bundle. - Quorum security review #6:
- Leaves bind a payload digest, and BMC subjects are site-qualified.
- Approvals sign the trust domain.
- Tiers must be ordered.
- The trust bundle version follows its content;
pki.trustVersionis now a floor. pki.approvers.setSignaturesare published for the version they sign, and an unsigned quorum change is logged.
- Envelope:
MethodAdmission.abandonedcleans up after any failure following transaction 1 (not the IAM refusal, which runsdenied). - Quorum API:
commandBatches.create(batches:create, idempotent), andcommands.run({ batchId }); CommandInfo gainsbatchIdandawaitingApproval.- Leaves may carry their payload, which approvers see in
scope; its type must be the kind's, at most 8 MiB per batch. - Batch subjects must be the tenant's own nodes.
- MCP
propose_command_batch(there is no approve tool).
- The approver set has its own epoch (
pki.approvers.epoch, TrustBundle field 8). A stale replica refuses to start rather than republish an old trust bundle. SiteSpec.proxy_targetsboundssite.httpProxyto the listed machines.- Rollout sends the signed release manifest with
NodeSpec.daemonanddaemon.upgrade, for bcd's self-update. lint:repochecks the generated docs reference before the API freeze.
- Tests: the §16 v0.3 MCP confirmation acceptance and §12.6 example policies end to end, §5.6 walkthrough 2 (acme-cloud), the authz matrix known-key replay step;
pnpm checkruns the remote-IAM suites,proto-gen --checkandbuf breaking. Tools:scripts/private-commit.mjs(compare-and-swap commits),scripts/head-check.mjs(tests the committed tree in a worktree).
- Security: admissions decide on the committed row (
-
Round 4, capacity and sandboxes:
- Capacity:
- The pool-lease placer reads a lazy
PoolIndex: per-class counts fromcapacity_device_counts(trigger-kept), booked devices only, and full devices and links per node on first view. It loads the index before taking the pool lock. At 10k nodes on PGlite,placeQueuedgoes from ~500 to ~1,000 placements/s and lock hold p90 from 875 to 60 ms. - Also: single-tenant offers,
dedicated=<tenant>taints, node label constraints (nodeLabels,'*'any value), the MIG layout gate, attestedAllocationBound, admit hooks for node leases, the budget admission check, reservationoperation/poll, active conditions,onPlacementmetrics, the I7 solver, fast-check planning properties,capacityTenantDeleted, and JSON Schemas for every method.
- The pool-lease placer reads a lazy
- Sandboxes (§3.7, D24), a
sandboxes+sandboxTemplatesgroup onvps():- Each sandbox drives one hosted instance: admission, placement, quota, IPAM, sealed user data, metering and deletion are the instance's. Instance item methods refuse a sandbox's instance.
- Templates are checked against a hosted pool once. They carry TTL bounds,
warm: { min, max },env(tenantsecret://refs written to/etc/sandbox/envinside broker-sealed user data) andnetwork(egress/private/none→InstanceSpec.networkPolicy). - TTL expiry is an ordinary instance delete (
sandbox.expired, thendeleted).extendis decided with the new lifetime. - Warm pools:
pausedwhen the runtime can pause, otherwisestopped. A warm instance is claimed withFOR UPDATE SKIP LOCKEDonly after the create's own allow, and never from an older template shape. Warm capacity is metered asvps.sandbox.warmuntil claimed. - Snapshots:
sandboxes.snapshotsendsinstance.snapshotthroughvps({ snapshots: SnapshotStore })into a tenant-privatesandbox_snapshotstable.create({ fromSnapshot })restores on the same runtime andcpu.model, and FakeHypervisor carries guest memory across. - Exec without an in-guest agent: tunnels'
sandboxes.execreturns ansshticket (act,inst,sbx) plus a ≤15 min certificate from thesandboxSshCA for<account>@<instanceId>, which vps renders into the guest's trust. - Also:
readyAtstamped at first run, selfCheck findings, andvps().tenantDeleted, which deletes every instance of a deleted tenant (hosted instances' inline allocations were never released before). - Later the same day:
- Guest host keys certified by the sandbox CA (exec pins guests). A sandbox never outlives its certificate: claims take only covering warm instances, warm pools recycle short ones, a fresh sandbox's expiry is capped, and restores or extends past it are refused.
sandboxes.execanswershostCertificate: valid|expired|none. - Secrets: templates use only secrets the tenant put, never fleet-scoped ones, and writing one decides
compute:secrets:manage. private/nonenetworks place only on hosts whose bcd enforces them. Warm instances on a host that stops doing so are replaced, and running ones are a doctor error (vps.sandboxes.network).- §12.8 IAM reactions:
withdrawAgentSandboxes,reassignSandboxes(sandboxIamReactionsfor the host) andsandboxHoldersfor the IamReconcile sweep. - Budgets:
extendruns the budget check. Warm pools stop refilling on a spent budget, and adrainoffer empties them. sandbox.expiring(vps/0013), andsandboxes.snapshotisUNSUPPORTEDup front withoutRuntimeTraits.snapshot.
- Guest host keys certified by the sandbox CA (exec pins guests). A sandbox never outlives its certificate: claims take only covering warm instances, warm pools recycle short ones, a fresh sandbox's expiry is capped, and restores or extends past it are refused.
daemon/README.mdrewritten for the v0.1 daemon.
- Capacity:
-
Metal attestation and dedicated-root leases:
- Security fix: a wipe or diagnostics result counts as attested only when the node signed it. The gateway stores
CommandUpdate.node_sig(commands.result_sig*,core/0012_v02_evidence), and metal's defaultnodeSignedResults()verifies it with pki againstnode_certs. Before this, the kind'sattestedflag was trusted, so a gateway could forge a wipe. A lessee'snode-tenantcertificate never attests. - v0.5
binding: 'node'(metal side): a dedicated-root lease deploys the lessee's profile undertenant-controlledtrust with a revoked platform identity, and marks the allocation bound. Its release runs the §13 teardown (fence, attested secure erase, DCGM, firmware baseline check with quarantine on drift, new identity generation). core/0012also addsnode_bindings, whichnodes.deleteand retirement clear. Provision exportsprovisionedTargetResolver()anddiscoveryWorkflowNodeResolver()for pki's attestors.- Two-phase BMC password rotation (
metal.rotateBmcCredential,bmc_credential_versions): the password is generated and sealed, sent as refs only, and becomes current only on a site-signed login check. The old password stays current on failure. The tenant-root teardown rotates, and a failed rotation quarantines the machine. - The ramdisk's discovery token is single-use and MAC-bound. It reaches the site agent only as
ProxyDhcpEntry.discovery_token_ref, andboot.cleanUpdeletes it. - Firmware drift can be reflashed from the pool's baseline images (
policy.firmwareRemediation: 'reflash') before quarantine. tests/metal-capacity-lease.test.tsruns capacity and metal together forbinding: 'node'. The dev fleet gainsjoinSite()for site agents, and FakeDaemon signs attested results.
- Security fix: a wipe or diagnostics result counts as attested only when the node signed it. The gateway stores
-
v0.2 server groups and schema:
joinRequestslist/approve/reject: the approval queue behind deferred joins (discovery, placeholder DMI). Decisions are idempotent, and an approval admits one join (the retry with the recorded CSR consumes it in the join transaction).siteTokenscreate/revoke (rolesite), and the SiteBoot leasesite:<id>:boot: one connected site agent holds it, and the standby is promoted only after it expires, under a new epoch.secretsput/delete: write-only and sealed in the SecretStore, with a version per put. Events and audit rows carry only ref, name and version.- Also:
drivers.list;sites.update/sites.delete(tombstoned once referenced);nodes.delete(retired or never-adopted nodes only; capacity rows released in lock order, certs revoked, hardware key freed, tombstone). core/0010_v02_server:join_requests,node_certs.allowed_kinds,nodes.deleted_at,secret_refs.core/0011_v02_security:sites.deleted_at,attestation_uses+pruneAttestationUses.- PGlite now runs
ANALYZEafter migrations and periodically, so dev and sim plans match Postgres.
-
v0.2/v0.3 metal walkthroughs, chaos and runtime schema:
- Talos (§5.6 #3): agentless
agent: 'none'pools run out-of-band profiles.httpViaSitereaches a machine's API through its site agent (site.httpProxy), and it refuses before sending any command: other hosts, names, plain http off the provisioning network, redirects, oversize responses, and secret headers passed as values. - Ubuntu autoinstall (§5.6 #1): a third-party plugin renders a per-node ISO with a single-use
provisionedtoken, andmedia.inserttakesfromStep. The §16 v0.2 acceptance runs in sim form: 20 unattended enroll → ready → deployed → released → ready loops, and everyreadyfollows a verified wipe. tests/metal-chaos.test.ts: a worker or site agent dies mid-deploy, and no destructive command is sent twice.core/0009_runtime:outbox_cursors,work_queue.attempts,commands.owner, tenant indexes, and retention viapruneBehindCursors, which deletes only rows every cursor has passed.
- Talos (§5.6 #3): agentless
-
v0.1 W5a server runtime:
betterCompute()now runs the control plane. Table leases with epoch fencing (§8.5), the coalescing work queue, 256 sharded reconcilers with rendezvous assignment plusReconciler.periodickeys and deterministiccompute.jobs.*.tick(), modulestart/stop, the command queue (protobufCommandBody, per-nodeseq, idempotency keys, cancel),CommandSweeper, the xmin-ordered outbox with sinks andcompute.events.subscribe, the authz projection writer, and a DB-anchored clock withClockSkew. The envelope runs request-as-resource admission (drafts, idempotent replay, delegatedCONFIRMATION_REQUIRED), 30 s authentication and 10 s read-decision caches (compute.caches), and the list recipe. v0.1 groups: projects, sites, joinTokens, nodes, commands, usage, events. JoinService admits nodes through@better-compute/pki(sealed tokens,hardware_keyfrom inventory, signedJoinResponse, Renew with proof of possession) behindgatewayServices; the NodeLifecycle, NodeSpec, Liveness and drain controllers;capacityModuleis built in and backsctx.capacity;gatewayReportHandlersforcreateGateway({ reports }).tests/server-spine-v01.test.tsruns join → adopt → reserve → bind → liveness end to end with zero IAM calls on fleet paths; the generated authz matrix covers all 42 v0.1 rows. -
v0.1 W3a capacity:
@better-compute/capacity. Selectors (matchExpressions+ CLI shorthand), schedulability with its SQL twin, the placement pipeline (filters, NVLink/NUMA-aware atom pick,binpack/topology/fragmentation/spreadscorers, top-N pick) and the savepoint-guardedinlinePlacer(≤3 replans, thenpending); all-or-nothing quotas; release/extend decided by theEXCLUDEconstraint; rollups (deltas + rebuild);capacity/0001_device_links+syncDeviceLinks.capacityModuleservespools,capacity(summary, byPool, preview, timeline),reservations(admission drafts, placement in tx 2, lifecycle reconciler with bind-timeout retries, leases,maxPending, delegated confirmation) andquotas;markAllocationBound/Failed/Releasedfor the gateway;capacity.usagewrites hourlyusage_windows(gpu.<model>.hours, reserved time from active, D14). The torture exit test (1,000 ops, every §10.4 invariant) fixed a quota/rollup lock-order deadlock. -
v0.3 VPS:
vps()servesinstances(admission drafts; hosted pools placed through capacity with IPAM leases and converged fromreportInstances; provider pools driven throughProviderImploutside transactions; lost-host recreate),flavorsandproviderAccounts(manifest-validated, SecretRef-only credentials);NodeSpec.instances;vps.usagemeters vCPU/memory/GPU hours;providerConformanceCases(); a 200-instance churn test proves no leaks. -
v0.3
@better-compute/provider-hetzner(outside the umbrella):hetznerCloud(label-idempotent create, paginated offers with prices and availability, power/rebuild/list, rate-limit mapping) andhetznerRobotProvider(claims unnamed servers instead of ordering, resets, rescue, installimage bootstrap delivering the join token over SSH stdin only); both pass provider conformance against API emulators. -
v0.2 Health and remediation:
device_healthquarantines (core/0007_device_health) take one GPU out of placement without blocking its node. XID policies (48 quarantine, 63 drain+reset, 64 RMA, 79/95 drain+reboot) and inventory health findings (row remap, uncorrectable ECC, degraded NVLink) feedrecordXid/applyInventory. The provisionhealthreconciler runsremediate-reboot/remediate-gpu-resetafter the node drains, within the pool's disruption budget (policy.disruptionBudget, default 5%), and stops for a pool with >10% unhealthy nodes in 10 min (circuit breaker); a failed, cancelled or exhausted remediation escalates to maintenance. v0.5 fractional GPUs (inventory side):gpu.slotatoms<uuid>/s<k>for timeslice/MPS pools,partitionPendingfreezes a GPU during a MIG mode change, andgpuAtomFamilyfeeds the atom rule.userdata.renderrenders cloud-init with a single-useprovisionedtoken into a secret, which metal's deploy sends asuserDataRef. Metal command payloads are now the proto3 JSON of each kind's message. -
v0.2 metal:
metal()serves themetalgroup.enrollkeeps inline BMC credentials only as a secret reference, and driver bindings are inherited from the pool's hardware profile. Themetalreconciler runs each provision state's workflow (metal-enroll,metal-inspect,metal-commission, the tenant's deploy profile,metal-release,metal-retire,metal-rescue) and appliescomplete/fail. A release returns toreadyonly after an attested wipe. Control-plane steps relay BMC and boot work to the site agent and disk, diagnostics and image work to the ramdisk;boot.kexeccompletes on rejoin. There are site and ramdisk command kinds, andmetal/0001_nodes. -
v0.2 provision additions: the image catalog and
imagesgroup (provision/0002_images: digest plus Ed25519/P-256 signatures against signer allowlists, unsigned images private, platform-signed ramdisks, promotion with a wildcard authz row, site caches with LRU eviction). Also site-step routing to the boot-lease holder, workflowownerwake-ups and profile snapshots (provision/0003_workflow_owner),awaitCommandfor relaying steps,defineStep({ relays })andprovisionModule({ modules }). Migrationscore/0005_audit_commit_orderandcore/0006_pool_archive. -
v0.2 provision: the workflow engine.
provisionModule({ steps, profiles })ownsprovision/0001_workflows(profiles,workflows,workflow_steps, with one active workflow and one in-flight step per node), theworkflowreconciler (sharded by node) andworkflowEngine(ctx)forctx.workflows. Profiles expand into persisted steps: registered steps, or driver operations sent as onedriver.invokecommand, plusfallback:, acceptance, on-failure and cleanup steps. Control-plane steps run between transactions (stepNotReadypolls), agent steps are exactly one command (wf:<id>:<step>,#<attempt>on retry), andawait: 'rejoin'completes on a new boot or role and fails only on timeout. Alsotimeout,retries,onFailure,when:, abort (cleanup still runs), pause/resume and retry-from-step, the built-inwait.agentJoined/wait.generationObserved, and theprofilesandworkflowsAPI groups. -
v0.1 W3b inventory and store: section verification over received bytes, snapshot digests, diffs, devices and MIG atoms,
gpuLinks, GFD labels,GpuCountMismatch/GpuModelUnknown/DuplicateIdentity,hardware_key(withhardwareKeyFromClaimsfor join),recordInventoryHashes/ingestInventorySectionfor the gateway,applyInventory+inventoryReconciler, andinventory.get. Migrationscore/0003_v01(v0.1 columns,node_inventory,node_inventory_sections) andcore/0004_command_cancel. The outbox conformance reader orders byoutbox.txid, not its text alias. -
v0.2 PKI (ready for the server to wire):
localSealedSecretStoreoversealed_secrets(pki/0001_sealed_secrets, AES-256-GCM with ref+tenant AAD, key rotation viareseal), theSecretRequest/SecretResponsebroker crypto with node signatures checked againstnode_certs, a command-signing root with 24 h worker keys andsignCommand/verifyCommand/signDesiredState/verifyDesiredState, trust-root rotation, andverifyAttestedUpdate/verifyAttestedReport. Also: PKI bundles sealed under the deployment secret,agentIdentityFromChain, the agent-side join/renew helpers,doctorPKI findings, the capacity CLI shortcuts andiam setup. -
v0.1 W5c CLI:
pki init(root + node/serving/internal CAs + JoinService keys, sealed underBETTER_COMPUTE_SECRET, optional--offline-root),pki show(bcd pins from the public half),pki issue-gateway(30-day serving certs, atomic replace), anddaemon install-script(POSIX sh: token fromBCD_JOIN_TOKEN/stdin only, pinned sha256 download, 0600config.tomlin bcd's TOML subset, hardenedbcd.service, in-place upgrade without a token). The CLI framework routes two-word commands andhelp <group>. -
v0.1 W2 PKI:
@better-compute/pki. Local root, node, serving and internal CAs with per-kind issuance policy (SPIFFE URI SAN + role extension, ≤ 24 h node certs, ≤ 2 h ramdisk), a strict DER/X.509/PKCS#10 layer onnode:crypto, chain verification, join tokens (issueJoinToken,verifyJoinToken,joinTokenAttestoronjoin_tokensatcompute_now()), sealed tokens bound to the join CSR (JWEECDH-ES+A256KW/A256GCM), signedJoinResponseandSignedTrustBundle,verifyRenewPopwith a malleability-proof replay cache, and aRevocationSet.hardware_keystays ininventory, the single source. Tests include a mutual-TLS handshake and the RFC 7518/3394 vectors. -
P0 scaffold: a pnpm workspace mirroring better-iam's, with the packages, contracts, repository rules and CI that v0.1 builds on. Plan
PLAN.md; guidedocs/development.md.- Packages
@better-compute/core,protocol,inventory,provision,metal,vps,postgres,server,client,cliandtesting, and the umbrellabetter-computewith subpaths./core,./protocol,./inventory,./provision,./metal,./vps,./server,./postgres,./pglite,./client,./cli,./testingand binbetter-compute.inventory,provision,metalandvpsare stubs: they export the frozen contract types, and their factories throwNOT_IMPLEMENTEDnaming the phase that implements them. - better-iam 0.1.0 is vendored as 23 tarballs in
vendor/better-iamand pinned throughpnpm-workspace.yamloverrides(scripts/sync-better-iam.mjs,pnpm sync:iam). - Repository rules under
pnpm lint:repo(part ofpnpm check):scripts/check-deps.mjs(server never imports injected modules,gateway,iam,postgres, providers or drivers; core's root entry imports no Node.js built-in; workspace dependencies match tsconfig references; nothing imports aprovider-*),scripts/check-sql-now.mjs(SQL reads time only throughcompute_now()) andscripts/umbrella.mjs --check(the umbrella is generated frompackages/better-compute/umbrella.json;pnpm umbrellarewrites it). - Packaging, ported from better-iam:
validate:packages(Apache-2.0,publishConfig.access,repository.directory,{ types, import }exports whose files exist, publint, one version),pack:all,check:packed-types(attw --profile esm-only),test:packed(a fresh consumer installs every tarball with the vendored better-iam, importsbetter-compute,/inventory,/provision,/metal,/vps,/pgliteand/client, and runsbetter-compute --help) andscripts/release-version.mjs. - CI:
.github/workflows/ci.yml(Ubuntu and Windows × Node 22 and 24:pnpm check,pnpm proto:check,buf breaking, pack, attw, packed smoke; apostgres:17job forpnpm test:postgres; npm publishing that waits until better-iam is on npm) and.github/workflows/daemon.yml(go vet,go test -tags nonvml,fakehw ./...,goreleaser check). bench/REFERENCE.mddefines the reference hardware for the v0.1 gateway, IAM-lane and placement benchmarks.
- Packages
Better Compute is created by Sean Filimon
Last updated