Skip to content

runtime: harden the extension event/subscription seam (duplicate-kind detection + second consumer) #517

Description

@mfw78

From review of #447 (review). Confirmed still valid at HEAD. Non-blocking. Target: L1 nexum-runtime.

The Extension::subscriptions / Extension::events seam (EventSources, ExtensionEvent) is mechanically generic, but two gaps remain:

  1. No duplicate-kind detection. Subscription kinds aggregate into a BTreeSet<String> (host/extension.rs:119, via extension_subscription_kinds()), which silently dedupes. Two extensions declaring the same kind string merge into one vocabulary set with no error - their event routing silently shares a kind. Harmless today (single consumer), a latent footgun once a second extension lands. Detect and reject (or namespace) the collision at boot, the way HostServices::from_extensions already bails on a duplicate service namespace.

  2. Single consumer. videre-host is the seam's only real user; cow-api does not use it. "Proves the seam" is by construction, not by a second independent consumer. Landing or stubbing a second consumer would validate the generality before the seam is leaned on as shared infrastructure.

Acceptance criteria

  • Two extensions declaring the same subscription kind fail boot (or are explicitly namespaced), covered by a test.
  • Optionally: a second consumer (real or a test stub) exercises the seam independently.

Also: duplicate manifest-section names (from #448 review, 2026-07-21)

The same at-least-one-vs-at-most-one gap exists on the manifest-section seam. enforce_extension_sections (supervisor.rs:358) checks a section is claimed by at least one wired extension via .any(|ext| ext.manifest_sections().contains(...)), never at most one. Two extensions claiming the same section name (e.g. both declare "venue") silently coexist; whichever parser runs first wins, undetected.

So this issue now covers three collision classes with one root fix - assert uniqueness of the extension-claimed string at boot, the way HostServices::from_extensions already bails on a duplicate service namespace:

  • service namespace (already bails)
  • subscription kind (the original scope above)
  • manifest section name (this addendum)

One boot-time uniqueness pass across the wired extension set should cover all three.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions