This profile mirrors a trusted Kastrick/RPX registry export through the existing Cloud Node provider-history engine and stores the Cloud Node copy in Supabase Storage using Supabase's S3-compatible endpoint.
The live Kastrick publisher remains the registry authority. Cloud Node does not discover or scrape the publisher's private S3 namespace by itself: a trusted registry export must first be materialized and ingested into the Cloud Node store. Once ingested, the registry objects participate in normal Cloud Node provider history and synchronization.
Why the S3 transport is used
Supabase Storage exposes an AWS Signature V4-compatible S3 endpoint. Cloud Node already has a bounded, streaming S3 transport with immutable-object creation and provider revision history, so the registry integration reuses that transport instead of introducing a separate upload implementation.
Use the example at:
engine/crates/cloud-node/examples/supabase-registry.setting.node.cn.example.json
Replace only the non-secret project values:
endpoint: the direct Supabase Storage S3 endpoint, normallyhttps://<project-ref>.storage.supabase.co/storage/v1/s3region: the project region shown in Storage S3 configurationbucket: the Storage bucket used for the registry; the example usesrbe-registry
The provider is intentionally configured as kind: "s3". Supabase is the backing service, while the wire protocol Cloud Node speaks is S3/SigV4.
Credentials
Do not put live credentials in setting.node.cn.json or commit them to Git.
The Supabase S3 profile reads:
The Kastrick server may separately use these environment names for Supabase REST/database operations when configured:
Those are not substitutes for the S3 access-key pair. S3 access keys are server-side credentials with broad Storage access and must stay on trusted backend surfaces.
Registry export contract
ingest_registry_export() and the cloud_node ingest-registry command accept a complete frozen registry snapshot, not an incremental patch. The export may contain these top-level collections:
index/snapshot.json is mandatory. Cloud Node validates the complete export before changing active registry state. Metadata collections contain JSON only. artifacts/ may contain JSON metadata and published .rbe.zip payloads.
A typical export is:
Ingest a materialized export without contacting the provider with:
The command reports files, metadataFiles, artifactFiles, and removedFiles, followed by the resulting Cloud Node logical path, object key, and content SHA-256 for each stored object.
Ingestion rejects missing index/snapshot.json, symlinks, unsafe paths, duplicate logical paths, unknown collections, non-JSON metadata, non-.rbe.zip artifact payloads, and package.rbe.json before snapshot replacement begins.
Cloud Node stores accepted files under the logical registry/ prefix in its normal content-addressed store. After every file in the new export has been stored successfully, active registry/ objects absent from the validated snapshot are removed from the active storage tree. Registry objects with the wrong Cloud Node BlobKind are removed as well: the accepted registry view is made only from normal file objects. Non-registry Cloud Node objects are never touched by this replacement step.
Removal affects only the active registry view used to calculate the next sync root. Cloud Node's backup/ history for a removed registry object is deliberately retained, so accepting a newer complete registry snapshot does not destroy the node's local historical copies.
That replacement behavior is important: registry ingestion is not an overlay. If a path existed in the previous complete export but is absent from the next one, the next Cloud Node provider snapshot must not continue advertising that stale path.
Only one local registry replacement transaction may run at a time. Cloud Node holds an OS-backed exclusive lock at <storageRoot>/rbe/.registry-ingest.lock; a second local ingest-registry or sync-registry operation fails fast instead of interleaving two snapshots. The operating system releases the lock automatically if the owning process exits or crashes.
Interrupted replacement recovery
The OS lock prevents two live writers from interleaving, but it intentionally disappears when a process dies. Cloud Node therefore also keeps a durable transaction marker at:
The marker is written and durably synced before the first active registry object is changed. It is removed only after the replacement has finished, stale active registry objects have been removed, and the final active registry/ path set exactly matches the validated export.
If the process exits, the machine loses power, or an I/O error interrupts replacement after the marker is written, the marker remains. Normal SyncPlan generation then fails closed. As a result, sync-plan, provider synchronization, peer synchronization/negotiation, and provider/peer daemon synchronization cannot publish a mixed pre/post-replacement registry view.
Recovery is intentionally simple: rerun ingest-registry or sync-registry with a complete trusted export. Registry ingest is allowed to inspect and repair local storage while the pending marker exists. Once the repaired active registry path set verifies successfully, Cloud Node removes the marker and normal synchronization becomes available again.
Do not manually delete .registry-ingest.pending to bypass recovery. The marker is the evidence that the active registry view may be incomplete.
package.rbe.json is deliberately not accepted as registry archive metadata. Published package archives are opaque to Cloud Node. The trusted Kastrick publisher must verify the .rbe.zip and its internal package.rbe.yaml before exporting a release artifact to Cloud Node.
One-shot registry provider synchronization
Provider-backed nodes can ingest a trusted export and immediately run normal provider-history synchronization in one command:
sync-registry is intentionally a composition of existing Cloud Node behavior, not a second registry protocol. It performs these steps in order:
- verify that provider mode is configured before changing local registry state;
- acquire the local registry replacement lock;
- validate the complete frozen export through the same path used by
ingest-registry; - durably mark the local registry replacement as pending;
- store the new snapshot and remove stale or wrong-kind active
registry/objects that are absent from it; - verify the final active registry path set and clear the durable pending marker;
- while still holding the registry lock, run the normal
synchronize_provider()transaction, including its provider-history namespace lock, ancestry checks, conflict policy, immutable object uploads, and provider HEAD compare-and-swap behavior; - report
ingestFiles,ingestMetadataFiles,ingestArtifactFiles,ingestRemovedFiles, then the normal provider sync relation, action, final head, and final root.
Holding the registry lock through provider synchronization prevents another local registry revision from replacing the active registry/ tree between ingest and provider snapshot creation. The provider lock remains independently responsible for serializing remote history changes for the configured namespace.
Package publishing must not depend synchronously on this command. A publisher can materialize a frozen export and schedule sync-registry independently so a temporary object-provider outage does not make package publication itself unavailable.
If provider synchronization fails after ingestion, the accepted registry snapshot remains in the local Cloud Node store and the command returns an error that states the local ingest completed. Re-running the same frozen export is safe with respect to snapshot identity: Cloud Node's sync root is derived from object kind, logical path, content SHA-256, and logical size rather than manifest timestamps. Replaying byte-identical registry files therefore keeps the same sync root; changing object content or the active path set changes the root and produces the expected new provider snapshot.
Because sync-registry uses the configured provider conflict policy, a diverged remote does not get silently overwritten. The default fail policy still fails. prefer-local and prefer-remote retain their existing explicit meanings.
Revision behavior
Registry data does not get a second synchronization algorithm. It uses Cloud Node's existing provider history after ingestion:
- local and provider heads equal: no-op
- provider head is an ancestor of local: local is ahead, push
- local head is an ancestor of provider: provider is ahead, pull
- unrelated heads: divergence; apply the configured conflict policy
Immutable release artifacts remain content-addressed in Cloud Node and are uploaded through provider synchronization. The registry's own release immutability/yank semantics remain enforced by the Kastrick registry backend; Cloud Node is the durable synchronization/storage layer.
The trusted publisher-to-export materialization step is intentionally separate from Cloud Node's storage engine. That boundary prevents Cloud Node from becoming a second registry authority or requiring access to client-facing RPX credentials.