Skip to main content

DiskRegistry

Struct DiskRegistry 

Source
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

Source

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.

Source

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());
Source

pub fn publish( &self, manifest: KernelManifest, ptx_text: String, ) -> Result<(), RegistryError>

Verify + persist a signed manifest plus its PTX text.

Check order:

  1. publisher allowlist (if configured) — cheapest failure for a publisher who legitimately holds the signing key but is not authorised to publish under their claimed identity.
  2. BLAKE3 digest match against ptx_text.
  3. HMAC v2 signature verification.
  4. Uniqueness — refuse if (name, version, sm_version) is already in the keymap.
  5. 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 returned ContentHash is recorded in the keymap.
Source

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

Source§

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>

Resolve (name, version) to the verified manifest + PTX text.
Source§

fn publish( &self, manifest: KernelManifest, ptx_text: String, ) -> Result<(), RegistryError>

Verify and persist a signed manifest + PTX text.
Source§

fn list(&self) -> Vec<KernelManifest>

Enumerate all registered manifests (PTX text omitted).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Send + Sync>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more