Skip to content

capabilities: providers cannot declare logging, and an undeclared logging import is not enforced #76

Description

@mfw78

Problem. PROVIDER_CAPABILITIES (crates/nexum-runtime/src/manifest/capabilities.rs) lists only chain and messaging, so a provider module.toml cannot declare logging.

A provider that declares it fails at Supervisor::boot:

load provider .../logging_venue.wasm: manifest: unknown capability "logging" in [capabilities] (known: chain, messaging, http, wasi-sockets, wasi-filesystem)

This blocks nullislabs/videre-nexum-module#26, which admits logging to the venue-adapter world as a declared opt-in. The guest world synthesis, the host linker binding, and the nexum:host/logging host impl all work today, but the manifest declaration that is supposed to gate them is unrepresentable, so the videre integration test has to boot the fixture with a manifest that omits the declaration.

Two halves of the same gap.

  1. PROVIDER_CAPABILITIES has no logging row, so CapabilityRegistry::provider().is_known("logging") is false and manifest load rejects the declaration.
  2. CapabilityRegistry::provider().wit_import_to_cap("nexum:host/logging@0.1.0") returns None, so enforce_capabilities does not hold a provider to its declaration either. A provider importing nexum:host/logging without declaring it is admitted.

The second half is the more interesting one: it means the opt-in is not enforced in the direction that matters. local-store, remote-store, and identity are still refused structurally by the provider linker, so this is not an authority escape, but logging is presently ungated in both directions rather than opt-in.

Proposal. Add nexum_world::Cap::Logging.as_str() to PROVIDER_CAPABILITIES. Both halves follow from the one row: is_known admits the declaration, and wit_import_to_cap maps the import so enforce_capabilities refuses an undeclared one.

CapabilityRegistry::provider() is constructed inside Supervisor::boot with no injection point, so an extension cannot register the row itself. The change has to happen here.

Related. A second, smaller ask from the same integration: bind_host_via_wit_bindgen!'s base block emits From impls between nexum::host::types::Fault and nexum_sdk::host::Fault. A domain world that remaps nexum:host/types onto its own SDK bindings makes both types foreign, so the orphan rule blocks the whole macro, including the logging arm that only needs the freshly generated nexum::host::logging. A public logging-only entry point (the current __bind_host_cap_via_wit_bindgen!(logging) arm, minus its WitBindgenHost dependency) would let a domain SDK reuse the level mapping and facade install instead of restating them.

Done when.

  • A provider module.toml declaring logging loads and boots.
  • A provider importing nexum:host/logging without declaring it fails enforce_capabilities.
  • videre#26's integration test boots the fixture with the fixture's own module.toml.

AI Assistance: Claude Fable used to trace the capability path and reproduce the boot failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:capabilitiesCapability model and egress gating: manifest [capabilities], HttpGate, world guaranteebugSomething isn't working

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions