openvibers/openvibe.network Commits

Network: Inventory and MediaHub get Media grants on their own tenants (C-71) (#145)

OP OpenVibers committed 11 Oct 2026 · 90b8acb6f9 · 1 file, +5 −0

Groundwork for compatibility register C-71, which retires Media's app-key seeding once no tenant uses a key.

Two first-party services still call Media with their own tenant's app key:
- **Inventory:** `INVENTORY_MEDIA_APP_KEY`, for Workshop badge images.
- **MediaHub:** `MEDIAHUB_MEDIA_APP_KEY`, for its library: create, upload, multipart, get, download URL and delete.

Live (C-70) and OpenRestream (C-42, OpenRestream#54) already use service tokens. These grants let the other two do the same, on their own tenant namespaces only:

- `[inventory, media.object.upload, openvibe.media]`, namespace `inventory`
- `[media-hub, media.object.upload, openvibe.media]`, namespace `media-hub`
- `[media-hub, media.object.read, openvibe.media]`, namespace `media-hub`

Media's object routes take `media.object.upload` for writes and for deletes (its delete verb accepts upload), and `media.object.read` for get and download. `X-OV-Subject`, which both services send to name an object's owner, is accepted with a service token as well as with a key. The code changes in Inventory and MediaHub follow, and the app keys are dropped after those deploys.

`ov test`: 38 covering files pass.

Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex 3ee41f45..60a72043 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -86,6 +86,11 @@ const DEFAULT_GRANTS = [
// recordings and thumbnails it produces there too.
...['media.object.read', 'media.object.list', 'media.object.upload', 'media.object.delete'].map(cap => ['live', cap, 'openvibe.media', ['live']]),
['openre', 'media.object.upload', 'openvibe.media', ['live']],
++ // Compatibility register C-71: Inventory (Workshop badge images) and MediaHub (its library) reach Media with their
++ // own tokens on their own tenants, not with app keys. Upload also covers the delete of an object.
++ ['inventory', 'media.object.upload', 'openvibe.media', ['inventory']],
++ ['media-hub', 'media.object.upload', 'openvibe.media', ['media-hub']],
++ ['media-hub', 'media.object.read', 'openvibe.media', ['media-hub']],
// Plan T3: Chat owns the six chat tables. Emote images go to Media under the chat namespace, and
// the chat-AI summaries run in Chat with its own token.
['chat', 'media.object.upload', 'openvibe.media', ['chat']],