Skip to content

Operations

Regesta separates protocol facts from operational storage choices. The protocol defines releases, objects, channels, events, and verification rules. Operators choose the database, object store, queue, signer, checkpoint store, and deployment platform.

V0 is not a production registry, but the local implementation already has one important operational rule: persistent state must live outside the ephemeral server process.

Persistent State

The local V0 server uses REGESTA_DATA_DIR as the storage root.

That directory contains:

  • SQLite registry metadata for releases, channels, events, and authorization replay protection;
  • filesystem object storage for source archives, install artifacts, release manifests, and other content-addressed bytes;
  • local queue data for derived or async work;
  • local signer readiness state;
  • optional checkpoint store bytes for future transparency outputs.

Container images must treat local container disk as disposable. In the demo container, /data is the durable mount. In another deployment, the equivalent state must live in external services such as a managed database, object store, queue, signer, checkpoint store, or KMS.

Runtime Configuration

The default Node server accepts these deployment environment variables:

VariableDefaultPurpose
REGESTA_DATA_DIR.regesta-dataLocal SQLite, filesystem object storage, queue, signer, and checkpoint state.
REGESTA_DOMAIN_BINDING_TIMEOUT_MS10000Domain well-known binding fetch timeout. Set 0 to disable it.
REGESTA_MAX_REQUEST_BYTESunlimitedMaximum declared HTTP request body size.
REGESTA_MAX_PUBLISH_ARTIFACT_BYTESunlimitedMaximum uploaded install artifact size per publish request.
REGESTA_MAX_PUBLISH_SOURCE_BYTESunlimitedMaximum uploaded source archive size per publish request.
REGESTA_NPM_ARTIFACT_PROCESSINGtrueRun the default npm artifact metadata processor. Set false for core-only deployments.
REGESTA_NPM_PROJECTIONtrueMount the npm compatibility projection. Set false to disable npm routes.
REGESTA_NPM_UPSTREAM_FALLBACKtrueAllow npm projection misses to fall back to registry.npmjs.org. Set false for local-only npm projection reads.
REGESTA_READINESS_TIMEOUT_MS5000Per-adapter readiness probe timeout.
REGESTA_STATISTICS_CACHE_TTL_MS10000Root deployment statistics cache TTL. Set 0 to disable caching.
REGESTA_NPM_UPSTREAM_TIMEOUT_MS10000npm upstream metadata fallback timeout. Set 0 to disable it.

Numeric runtime values must be decimal safe integers without whitespace, fractional notation, exponent notation, or leading zeroes. Timeout and cache values are milliseconds. Request and publish limits are byte counts. Boolean runtime values must be exactly true or false.

REGESTA_NPM_PROJECTION=false disables the default npm compatibility mount for deployments that want to expose only core routes or a different projection mix. It does not change stored release data, artifact processing, or core registry semantics.

REGESTA_NPM_ARTIFACT_PROCESSING=false disables the default npm artifact metadata processor in the default server entrypoint. This is useful for core-only or non-npm deployments that provide their own artifact processor pipeline. It does not disable HTTP projection routes; use REGESTA_NPM_PROJECTION=false for that.

REGESTA_NPM_UPSTREAM_FALLBACK=false keeps the npm projection local-only. Missing package metadata and tarball routes return 404 instead of contacting or redirecting to registry.npmjs.org. Local Regesta-hosted npm packages still resolve through the npm projection when it is mounted.

Egress Boundary

The default server's external network egress is intentionally narrow:

  • domain well-known binding discovery for signed release.publish, channel.update, and channel.delete write authorization;
  • optional npm upstream metadata fallback when server-side fallback is enabled.

Both egress paths use no-store request cache policy, omit client credentials, and do not follow redirects automatically.

npm tarball routes do not fetch upstream bytes. They redirect to local core object URLs or, when fallback is enabled and no local release exists, to the upstream tarball URL. With REGESTA_NPM_UPSTREAM_FALLBACK=false, the default server should not contact registry.npmjs.org.

REGESTA_MAX_REQUEST_BYTES is a transport guard over declared Content-Length, not a protocol object-size rule. Malformed Content-Length returns 400, and a declared body larger than the configured limit returns 413 before mounted registry routes run. CORS preflight requests are answered before this guard so browser clients can discover allowed methods and headers without sending a body.

Backup Boundary

A backup must preserve a consistent view of:

  • registry database state;
  • object bytes;
  • object metadata;
  • queue state when queued work must survive restore;
  • signer or KMS configuration needed by the deployment;
  • checkpoint store bytes or metadata when checkpoint storage is configured.

Database-only backups are incomplete because releases reference content-addressed objects. Object-only backups are incomplete because package state is derived from events stored in the database. Adapter-owned package-state indexes are recoverable implementation data; event rows are the durable source for rebuilding them.

For the local SQLite/filesystem adapter, a conservative backup should stop writes, snapshot the whole REGESTA_DATA_DIR, then resume service. Future production adapters should provide backend-specific snapshot guarantees such as database point-in-time recovery paired with object-store versioning.

Restore Checks

After restoring state, an operator should verify the registry from public data, not only check that files exist.

Minimum restore checks:

  • /ready returns healthy storage status;
  • public event log verification succeeds;
  • package-state verification succeeds for representative packages;
  • release verification succeeds for representative versions;
  • npm projection reads still resolve known packages;
  • object reads by digest return bytes matching their descriptors.

The local smoke scripts cover a small version of this loop. pnpm smoke:docker checks persistence across a container restart, and pnpm smoke:load exercises the local SQLite/filesystem adapters under repeated reads.

The Docker smoke requires an accessible Docker daemon because it builds and runs a real OCI image before checking persistence across a Docker volume.

Load Smoke Profiles

pnpm smoke:load is a repeatable local gate for the SQLite/filesystem V0 adapter path. It publishes packages, reads root deployment statistics, checks readiness, reads core package state, reads events, lists object inventory, reads objects, and reads the npm projection.

The current load and Docker smokes validate the default npm-enabled deployment shape. They assume the default npm artifact processor and npm projection are enabled. A core-only or non-npm deployment can disable those features with REGESTA_NPM_ARTIFACT_PROCESSING=false or REGESTA_NPM_PROJECTION=false, but that deployment should define its own smoke profile and result schema instead of reusing the npm-first local gate unchanged.

The script supports two profiles. Publish concurrency defaults to the package count, matching the current all-at-once publish behavior. Read concurrency defaults to 1 unless REGESTA_LOAD_CONCURRENCY is set.

ProfilePackagesPublish concurrencyRead loopsRead concurrencyPublish maxRead max
smoke3325130s30s
local10101001120s120s

Use REGESTA_LOAD_PROFILE=local pnpm smoke:load for a heavier local run.

The profile defaults can be overridden with:

  • REGESTA_LOAD_PACKAGES
  • REGESTA_LOAD_PUBLISH_CONCURRENCY
  • REGESTA_LOAD_READS
  • REGESTA_LOAD_CONCURRENCY
  • REGESTA_LOAD_MAX_PUBLISH_MS
  • REGESTA_LOAD_MAX_PUBLISH_P95_MS
  • REGESTA_LOAD_MAX_READ_MS
  • REGESTA_LOAD_MAX_READ_P95_MS
  • REGESTA_LOAD_RESULT_FILE

These thresholds are not production SLOs. They are regression gates for the current local adapter implementation. Production deployments should define their own profiles against their database, object storage, queue, signer, checkpoint store, and deployment platform.

Load smoke override values must be positive safe integers. Configured concurrency values above the package count or read loop count are capped to the effective concurrency reported in the smoke result. The p95 latency budget overrides are optional. Leave them unset for exploratory local runs, and set them in CI or deployment profiles when a specific adapter and machine class has an agreed baseline.

The local smoke result reports the effective concurrency, request counts, throughput rates, publish and read latency summaries, read latency grouped by request category, run start and completion timestamps, total duration, runtime version, deployment target, storage backend labels, durability mode, and cache state used for the run. For the default local adapter path, the deployment target is local-in-process, storage is SQLite plus filesystem objects, queue, signer, and checkpoint adapters, durability is a temporary filesystem root, and reads happen after the publish phase has warmed in-process caches. Read concurrency is the number of concurrent read loops. The result also reports readRequestsPerIteration and maxReadRequestConcurrency so operators can see the effective maximum read request fanout for the run. Set REGESTA_LOAD_RESULT_FILE to write the same JSON result to a file for CI artifacts or deployment baseline records. Use pnpm smoke:load:validate <result-file> to validate a saved result before publishing it as a CI artifact or deployment baseline. Use pnpm smoke:load:ci when CI should run the load smoke and validate the saved result in one command. If REGESTA_LOAD_RESULT_FILE is not set, the CI wrapper writes to a temporary result file.

The load-smoke JSON result has an operations-only schema at /schema/regesta-load-smoke-result.schema.json. That schema describes the local benchmark result artifact; it is not a Regesta protocol object and does not define registry data-model semantics.

The result also includes readCategories, which currently lists: channel-release, event, event-page, npm-packument, npm-tarball-redirect, npm-version, object, object-inventory, package-state, readiness, release, and root.

Production Load Gates

Regesta does not define protocol-level performance SLOs. Operators should still publish repeatable load gates before calling a deployment production-ready.

Minimum pre-production gates:

GatePurposeRequired checks
ci-smokeFast pull-request signalpnpm ci:smoke, which runs tests, typecheck, lint, format check, docs build, and pnpm smoke:load:ci with the smoke profile
container-smokeOCI portability and persistencepnpm smoke:docker on a persistent volume
adapter-localLocal adapter regressionREGESTA_LOAD_PROFILE=local pnpm smoke:load
adapter-productionProduction backend validationthe same load shape against the intended database, object store, queue, signer, optional checkpoint store, and deployment runtime
restore-smokeRecovery confidencerestore from backup, then run readiness, verifier, object, package-state, and projection checks

The production adapter gate should publish its parameters with the result:

  • package count;
  • read iterations;
  • read requests per iteration;
  • publish duration budget;
  • read duration budget;
  • publish p95 latency budget;
  • read p95 latency budget;
  • publish packages per second;
  • read requests per second;
  • publish latency samples, average, p50, p95, min, and max;
  • read latency samples, average, p50, p95, min, and max;
  • read latency grouped by request category;
  • read category names;
  • run start timestamp;
  • run completion timestamp;
  • total duration;
  • concurrency level;
  • runtime version;
  • deployment target;
  • database, object store, queue, signer, and optional checkpoint store backend;
  • data durability settings;
  • whether the run used a cold or warm cache.

For the default npm-enabled deployment shape, a production adapter profile should cover the same behavioral surface as pnpm smoke:load: publish, root deployment statistics, package reads, release reads, event reads, readiness reads, object inventory reads, object reads, npm packuments, npm version manifests, npm tarball redirects, and redirected object downloads. Core-only or non-npm deployments should keep the same core, storage, verification, and readiness coverage, then replace npm reads with projection-specific checks for the ecosystem routes they actually expose.

A production gate fails if:

  • any write or read returns an unexpected error;
  • release verification fails;
  • event-log or package-state replay fails;
  • object bytes do not match descriptors;
  • authorization replay protection fails;
  • the registry is not ready after deployment or restore;
  • measured publish or read duration exceeds the declared profile budget.

Operators should treat these gates as minimum deployment evidence, not a claim that the registry can handle every ecosystem workload. Public SLOs should be defined separately from protocol compatibility.

Operational Logs

The default Node server writes structured request and audit JSON logs to stdout:

  • regesta.request records transport-layer request id, host, method, path, response status, and duration. The logged path excludes query strings;
  • regesta.core-audit records accepted and rejected core write attempts, including publish and channel operations.

Server request-id handling accepts bounded request ids for correlation. Invalid client request ids are replaced before they are written to response headers or operational logs. For accepted write requests, the same normalized request id is used in the HTTP response, regesta.request, and regesta.core-audit entries so operators can correlate transport telemetry with core write decisions.

Recoverable transport refresh failures use structured console.error entries on stderr. For example, regesta.deployment-statistics-refresh-failure means root deployment statistics could not be refreshed and the server served a stale cached value.

Unexpected server errors are also logged with console.error by the transport error boundary while the HTTP response hides internal exception details. Request-log and audit-log sinks are scheduled outside the request critical path, so a slow operator log sink should not add response latency. Operational logs are operator telemetry. They are not public protocol objects, do not replace the append-only event log, and should follow the operator's private log retention policy.

Hot Path Cost Boundaries

The V0 implementation is optimized for simple, cache-friendly read paths before introducing distributed storage.

Current hot-path boundaries:

  • health reads do not touch storage;
  • readiness reads call cheap, bounded adapter probes, including optional checkpoint store probes when configured;
  • root deployment statistics are cached and served from adapter counters or indexes;
  • root deployment info does not run readiness probes;
  • core package-state reads use adapter-owned event indexes instead of replaying the event log on every request;
  • core package-state HEAD reads use indexed package heads instead of reading full package state;
  • domain well-known binding discovery for write authorization is bounded by REGESTA_DOMAIN_BINDING_TIMEOUT_MS;
  • event and object collection reads rely on adapter-owned cursor validation inside the paginated read instead of separate cursor preflight reads;
  • npm tag and version reads use indexed channel and release state;
  • npm tarball routes redirect to the canonical object or upstream URL when available, or return 404 package_not_found, instead of proxying bytes through the npm compatibility layer;
  • upstream npm fallback metadata requests are bounded by REGESTA_NPM_UPSTREAM_TIMEOUT_MS;
  • request-log, audit-log, and derived-queue sinks run outside the committed write path.

These are implementation cost boundaries, not protocol guarantees. A production adapter can choose different indexes or caches, but it should preserve the same behavioral result: public facts remain replayable, immutable objects stay content-addressed, and compatibility projections are derived from core data. The local queue writes newline-delimited JSON entries with topic, payload, and enqueuedAt operational metadata so derived work can be inspected after a restart.

Retention

Regesta's default bias should be preservation.

Immutable release objects and events should not be garbage-collected while they are still part of public release history. Removing or hiding data can break mirrors, auditors, replay, and package-manager clients.

Retention policy should distinguish:

  • immutable public facts, which should be preserved by default;
  • derived caches, which can be rebuilt;
  • local queues, which may be drained or replayed depending on job semantics;
  • private operational logs, which can follow operator retention policy;
  • legally or safety-sensitive content, which needs explicit governance policy.

Until governance events are defined, removals for abuse, legal, or compromise response reasons should be treated as operator policy, not silent mutation of historical protocol facts.

Disaster Recovery

Disaster recovery should assume an operator may lose one instance, one storage backend, or one cloud account.

The recovery posture should prefer:

  • object storage replication;
  • database point-in-time recovery;
  • independent mirrors of public objects and event logs;
  • verifier tooling that can replay state after restore;
  • documented key rotation and compromise procedures;
  • deployment manifests that can rebuild the service without changing protocol state.

Forkability is the long-term governance backstop. A healthy ecosystem should be able to recover public package state from mirrored objects, event logs, and future checkpoints even if one registry operator disappears.

The current manual mirror and auditor workflow is documented in Mirroring.

Production Adapter Expectations

Production adapters should preserve the same logical guarantees as the local V0 adapters:

  • release publication is atomic across release state, default channel state, and event insertion;
  • event ids are immutable and unique;
  • authorization payload digests reject replay;
  • content-addressed objects are immutable by digest;
  • object descriptors match stored bytes;
  • queues do not corrupt messages under concurrent writers;
  • readiness checks are cheap, bounded, independent adapter probes;
  • readiness checks fail closed when a dependency is unavailable.

The default server bounds each readiness probe with REGESTA_READINESS_TIMEOUT_MS, falling back to a 5s timeout when the variable is not set.

The default server bounds domain well-known binding discovery with REGESTA_DOMAIN_BINDING_TIMEOUT_MS, falling back to a 10s timeout when the variable is not set. Set it to 0 to disable the timeout when a deployment uses an external fetch boundary.

The root deployment info endpoint caches advisory package statistics for 10s by default. Operators can tune this with REGESTA_STATISTICS_CACHE_TTL_MS; set it to 0 to disable cross-request statistics caching. In-flight statistics reads are still coalesced. When a refresh read fails after a cached value exists, the default server serves the stale cached statistics and logs the refresh failure; schema-invalid statistics still fail closed. Storage adapters should serve these statistics from cheap counters or indexes. In the local SQLite adapter, package count is maintained in registry_stats; startup migration or repair may scan releases to backfill the counter, but normal root requests should not. Normal root requests must not compute full-table release counts on the request path. HEAD / is a lightweight metadata probe and does not refresh or read package statistics. Status probes such as HEAD /health and HEAD /ready return headers without JSON body serialization. Collection probes such as HEAD /events and HEAD /objects also avoid paginating event or object inventories. Immutable object probes such as HEAD /events/:digest and HEAD /packages/:id/releases/:version skip canonical JSON body serialization after the addressed object is found. Mutable channel release probes such as HEAD /packages/:id/channels/:channel also skip JSON body serialization after resolving the target release. Core JSON HEAD responses, including not-found probes, request-size rejections, and error-boundary responses return headers without serializing their JSON body. Unexpected transport errors still keep status codes and console.error logging.

The npm projection bounds upstream npm metadata fallback requests with REGESTA_NPM_UPSTREAM_TIMEOUT_MS, falling back to a 10s timeout when the variable is not set. Set it to 0 to disable the timeout. This does not affect tarball routes, which either redirect or return 404 package_not_found without serving tarball bytes. Local npm packument HEAD requests use indexed package heads when package state is stable, so metadata probes do not need to build full packuments. Local npm version manifest HEAD requests also skip npm body projection after the addressed release is found. Local npm dist-tags HEAD requests skip JSON body serialization after reading indexed channel state. npm utility HEAD requests such as / and /-/ping, local not-found errors, and upstream fallback failures also avoid serializing JSON bodies.

The backend can be Postgres, DynamoDB, S3, R2, GCS, a platform queue, KMS, or another service. The registry core should continue to see only adapters.

Future Checkpoint Store Adapters

Checkpoint storage is a future transparency adapter, not part of the V0 core database schema.

The current implementation exposes this as an optional opaque checkpoint store adapter boundary. It is storage plumbing only: there are no public checkpoint routes, checkpoint object fields, proof formats, or witness semantics in V0.

The checkpoint store should persist transparency-layer outputs without interpreting the protocol content. Until checkpoint objects, proof formats, and witness policies are designed, the storage adapter boundary should stay focused on durability and retrieval:

  • store opaque checkpoint bytes or descriptors as immutable records;
  • reject mutation when an existing checkpoint id or digest is reused with different bytes;
  • list published checkpoints in a stable order for mirrors and auditors;
  • read one checkpoint by its public identifier or digest;
  • store future witness statements as opaque records attached to a checkpoint;
  • expose readiness status separately from the registry database and object store;
  • support backup, restore, and retention with the same care as events and immutable objects.

A checkpoint store must not be a hidden side table that only one server process can understand. A mirror, auditor, or replacement operator should be able to recover public checkpoint material through documented APIs once the transparency protocol exists.

Local development can use a SQLite table or filesystem directory under REGESTA_DATA_DIR. Production deployments should be able to use a database, object store, append-friendly log service, or another durable backend behind the same adapter boundary.

Checkpoint publication has a stronger consistency requirement than ordinary derived caches. Once a checkpoint is advertised publicly, the referenced checkpoint bytes and any attached public witness statements must be durable and readable. If an adapter cannot make that atomic with its backend, the transparency layer should use an explicit publish marker so incomplete writes are never served as public checkpoints.

This section intentionally does not define checkpoint object fields, inclusion proofs, consistency proofs, witness discovery, or witness thresholds. Those are protocol decisions, not storage adapter decisions.