Skip to content

dweb: declared capability needs in DWAPP_META — grow the bridge surface by manifest + per-need consent, never new ambient ops #319

Description

@NotASithLord

Context

The dwapp bridge surface (peerd-distributed/apps/bridge.js) is deliberately small and frozen — "growing it is a security event, not a convenience." That's the right Phase-1 posture. This issue is about how to grow it when growth becomes necessary (a second room, content put/get, an app-visible sign(), notifications, …) without sliding into ambient authority.

The pattern

An extension-manifest / Sandstorm-powerbox / Cloudflare-OS-blueprint hybrid: the app declares the shapes of what it needs; the platform mediates each grant; the app can never use what it didn't declare.

Concretely:

  1. DWAPP_META gains a needs list — publisher-signed, versioned, size-capped like the rest of the card (peerd-distributed/apps/meta.js). Each need is a {kind, params?, description} from a closed, versioned vocabulary (e.g. room is the one implicit need today; future: rooms:2, content-store, sign, …). Shapes only — a need is never a grant.
  2. Render needs at install and launch. The install consent dialog (already per-install, never remembered) lists them, Cloudflare-OS-blueprint-style with the author's description per need — so "what can this thing ask for" is visible before any bytes run.
  3. Consent per need at first use, granted narrowly (peerd already does this for the one existing need: room grants are keyed per content-hash × per room). New needs follow the same template: specific, remembered-or-not per kind, audited.
  4. The bridge refuses undeclared ops — even post-consent. The signed card thus commits the app's maximum authority. This composes beautifully with an invariant peerd already has: grants are keyed by content hash and reset on version change, so an update that grows needs is both visible (signed card diff, new seq) and re-consented automatically.

Why this beats the alternatives

  • vs. growing ambient bridge ops: every new op would be available to every dwapp ever installed, silently.
  • vs. a runtime-only powerbox (request capabilities dynamically with no declaration): loses the "reviewable maximum authority" property; the card is where peerd already puts signed, versioned app claims.
  • Cloudflare OS's binding annotations add a nice UX detail worth copying: per-need author-provided name/description/suggested-value, so the consent moment is comprehensible to a non-technical user.

Open questions

  • Vocabulary governance: closed enum in meta.js, versioned with the card schema; unknown kinds must fail closed (refuse install? or install with the need inert and visibly unsatisfiable?).
  • Should hello()'s DID disclosure become a declared need? Today it's implicit in opening the app; under this model it's arguably identity:read — which also intersects with the derived-subidentity issue (if per-dwapp identities land, the disclosed DID is fork-scoped and the stakes drop).
  • Whether the seeded commons app (apps/seed.js) declares needs retroactively (it should — it's the reference dwapp).

Nothing here is urgent — it becomes the required design the first time anyone proposes bridge op #14.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions