pub struct DiskRegistry { /* private fields */ }Expand description
Production disk-persisted kernel registry (roadmap feature #3, T35).
DiskRegistry is a thin layer on top of
tensor_wasm_artifacts::DiskArtifactStore — the artifact store
brings HMAC-SHA256 envelope, zstd compression, content-addressing,
size caps, and atomic rename-on-publish. The registry contributes
the application-level keymap
(name, version, sm_version) → (ContentHash + cached manifest)
so callers can resolve manifests by stable name@version (with
sm_version as a tie-breaker for kernels published for multiple
compute capabilities).
§Wire-format guarantee
Manifests are still subject to the same v2-envelope HMAC-SHA256
signature InMemoryRegistry enforces (the registry’s own,
independent signing key). The artifact store’s HMAC is a SEPARATE
integrity layer over the bincode-encoded (manifest, ptx_text)
blob; both must verify before a manifest is exposed to the caller.
This is defence in depth: the artifact store’s HMAC catches bit
flips on disk, and the manifest’s own signature proves the
publisher signed off on the content of the manifest (and
transitively the PTX via digest).
§Restart recovery
DiskRegistry::open reads every blob in the artifact store’s
directory, decodes each one, and re-populates the in-memory keymap.
A blob that fails the artifact store’s HMAC, fails bincode decode,
or fails the registry’s own signature check is skipped with a
tracing::warn — restart is best-effort and never panics on partial
corruption.
§Threat model — publisher allowlist
Today every caller in possession of the registry HMAC key can sign a
manifest under any publisher field they please. The v2 envelope
(T12) covers publisher and published_unix_ms cryptographically,
so a passive intermediary cannot rewrite publisher post-sign — but
a legitimate holder of the signing key still has free rein.
The optional publisher_allowlist field closes that gap by
refusing publish when manifest.publisher is not in the
configured set, regardless of whether the signature otherwise
verifies. This is a separate authorization layer over and above the
HTTP route’s kernel-publish scope check (T1) — the route check
gates who can call publish at all, while the allowlist gates
which publisher field the call can claim. With both layers in
force, an operator can have a single signing key shared across
trusted publishers without any one publisher being able to forge
claims under another publisher’s identity.
None (the default) preserves the historical permissive behaviour
— any signed publisher is accepted — and matches what
InMemoryRegistry does today.
Implementations§
Source§impl DiskRegistry
impl DiskRegistry
Sourcepub fn open(dir: PathBuf, hmac_key: [u8; 32]) -> Result<Self, RegistryError>
pub fn open(dir: PathBuf, hmac_key: [u8; 32]) -> Result<Self, RegistryError>
Construct (or re-open) a disk-persisted kernel registry rooted at
dir, signing/verifying manifests under hmac_key.
On success, the artifact store directory is opened (created
lazily on first put) and the keymap is rebuilt from any blobs
already on disk. Each blob is read via
DiskArtifactStore::get (which runs the artifact store’s
HMAC + zstd verification), bincode-decoded into a
(KernelManifest, ptx_text) pair, signature-verified under
hmac_key, and only then admitted into the keymap. Corrupt or
foreign-keyed blobs are skipped with a tracing::warn; the
registry never panics on a partial-corruption restart.
The returned registry has no publisher allowlist (permissive
mode); chain through Self::with_publisher_allowlist to
enable one.
Sourcepub fn with_publisher_allowlist(self, allowlist: HashSet<String>) -> Self
pub fn with_publisher_allowlist(self, allowlist: HashSet<String>) -> Self
Builder method: install a publisher allowlist. See the
type-level docstring for the threat model. Chain after
Self::open:
let reg = DiskRegistry::open(dir, key)?
.with_publisher_allowlist(["alice", "bob"].iter().map(|s| s.to_string()).collect());Sourcepub fn publish(
&self,
manifest: KernelManifest,
ptx_text: String,
) -> Result<(), RegistryError>
pub fn publish( &self, manifest: KernelManifest, ptx_text: String, ) -> Result<(), RegistryError>
Verify + persist a signed manifest plus its PTX text.
Check order:
publisherallowlist (if configured) — cheapest failure for a publisher who legitimately holds the signing key but is not authorised to publish under their claimed identity.- BLAKE3 digest match against
ptx_text. - HMAC v2 signature verification.
- Uniqueness — refuse if
(name, version, sm_version)is already in the keymap. - bincode-encode the
(manifest, ptx_text)pair and hand it to the artifact store. The store computes the BLAKE3 content-address and HMAC-signs the envelope; the returnedContentHashis recorded in the keymap.
Sourcepub fn list_paginated(&self, offset: usize, limit: usize) -> Vec<KernelManifest>
pub fn list_paginated(&self, offset: usize, limit: usize) -> Vec<KernelManifest>
Page-aware listing: skip the first offset keymap entries and
return up to limit manifests. limit is clamped to
DISK_REGISTRY_MAX_LIMIT.
The iteration order is NOT specified — DashMap’s iteration is
hash-bucket order, which is stable per process but differs
across restarts. Callers that need a deterministic page sequence
should sort the result themselves on whatever field they care
about (name, published_unix_ms, etc.).
Trait Implementations§
Source§impl KernelRegistry for DiskRegistry
impl KernelRegistry for DiskRegistry
Source§fn list_paginated(&self, offset: usize, limit: usize) -> Vec<KernelManifest>
fn list_paginated(&self, offset: usize, limit: usize) -> Vec<KernelManifest>
Override the trait default with the native paginated walk over
the keymap (no intermediate full list() materialisation).
Source§fn get(
&self,
name: &str,
version: &str,
) -> Result<Arc<(KernelManifest, String)>, RegistryError>
fn get( &self, name: &str, version: &str, ) -> Result<Arc<(KernelManifest, String)>, RegistryError>
(name, version) to the verified manifest + PTX text.Source§fn publish(
&self,
manifest: KernelManifest,
ptx_text: String,
) -> Result<(), RegistryError>
fn publish( &self, manifest: KernelManifest, ptx_text: String, ) -> Result<(), RegistryError>
Source§fn list(&self) -> Vec<KernelManifest>
fn list(&self) -> Vec<KernelManifest>
Auto Trait Implementations§
impl !RefUnwindSafe for DiskRegistry
impl !UnwindSafe for DiskRegistry
impl Freeze for DiskRegistry
impl Send for DiskRegistry
impl Sync for DiskRegistry
impl Unpin for DiskRegistry
impl UnsafeUnpin for DiskRegistry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more