openvibers/openvibe.sdk Commits

SDK: the product at openre.stream is OpenRestream (owner, 2026-10-09) (#27)

OP OpenVibers committed 9 Oct 2026 · af87ea1621 · 6 files, +10 −10

Every name people read says OpenRestream instead of OpenRe or OpenRe.Stream, and repository paths say
OpenVibers/OpenRestream (renamed on GitHub the same day). Ids are unchanged (openre, openre.*, ov_openre).

Changes

ddiff --git a/README.md b/README.md
iindex 4641c9f..895fcb0 100644
---- a/README.md
++++ b/README.md
@@@ -182,7 +182,7 @@ Until OpenVibe.Tools serves the gateway facade (Tools S6), point the jobs client
| `openvibe-sdk/projects` | both (user token) | `createProjectsClient(client)`: `catalog`, `list`, `create`, `get`, `update`, `archive`, `setAllowance`, `setEnvironmentPolicy`, `members.*`, `apps.*`, `credentials.list/rotate/revoke`, `grants.list/request/approve/deny/revoke`, `quotas.*`, `audit`, `iterateAudit` |
| `openvibe-sdk/resources` | server | `parseResourceName`/`resourceName`/`resourceNameOf` (OVRN, via the pinned `contracts.resources`) and `RESOURCE_KINDS` (only the chosen `med`/`wch` prefixes); `createResourceIndex({authorities, token, fetch, pageLimit, concurrency, timeoutMs, maxPages, maxMs})`: `list({project, kind, limit})` -> `{resources, stale}`, fanning out over the authorities' `GET /api/v1/resources`, following each opaque `next_cursor` and merging `common.resource-list-result@1` pages (an authority that fails — or whose cursor chain repeats, outruns `maxPages`, or outruns `maxMs` — is reported in `stale`, never fatal), and `iterate`; `createResourceClient({origin, token})`: `control(request)` POSTs a `common.resource-control-request@1` to `/api/v1/resources/control` — idempotency-keyed, transient failures retried with the same key and body, a thrown error carrying that `idempotencyKey` — and returns the `common.resource-control-result@1` (`done`/`pending`/`refused`/`failed`, a refused/failed one returned even with a non-retryable non-2xx) |
| `openvibe-sdk/geo` | both | `createGeoClient(client, {samples?, timeoutMs?})`: `nodes({role, region})` from Network's public node registry, `measure(nodes)` (beacon round trips, fastest first), `nearest({role, region, preferRegion})` → `{node, rtt_ms, measured}` (up/degraded nodes only; falls back to preferRegion when nothing can be measured) |
--| `openvibe-sdk/openre` | server | `createOpenReClient(client, {baseUrl?, publicUrl?})`: OpenRe.Stream, the streaming engine. `streams` (`byExternalRef`, `create`, `get`, `update`, `rotateKey`, `destinations`, `addDestination`), `destinations` (`test`, `start`, `stop`, `logs`), `sessions` (`get`, `playback` cached 10 s, `end`, `outputs`), `workers`, `manageUrl`; `{subject}` acts for a person (X-OV-Subject) |
++| `openvibe-sdk/openre` | server | `createOpenReClient(client, {baseUrl?, publicUrl?})`: OpenRestream, the streaming engine. `streams` (`byExternalRef`, `create`, `get`, `update`, `rotateKey`, `destinations`, `addDestination`), `destinations` (`test`, `start`, `stop`, `logs`), `sessions` (`get`, `playback` cached 10 s, `end`, `outputs`), `workers`, `manageUrl`; `{subject}` acts for a person (X-OV-Subject) |
| `openvibe-sdk/vip` | server | `createVipClient({baseUrl?, tokenClient \| getToken, fetch?, timeoutMs?})`: `evaluate({subject, resource, owner, fallback, mode})`, `checkEntitlement({subject, creator, product, mode})`, `isMember(subject, creator)`; every failure is a denial. `createVipCache({vip, ttlMs, denyTtlMs, unavailableTtlMs})`: `entitlement`, `peekEntitlement`, `evaluate`, `invalidate`, `handleEvent` (`vip.membership.changed` and Billing's entitlement events drop a member's answers at once), `clear`, `bounds` |
| `openvibe-sdk/usage` | server | `usageSample(fields)` builds a `platform.usage-sample@1` record (required `id`, `idempotency_key`, `service`, `operation`, `quantity`, `unit`; `at` defaults to now ISO, `source` to `openvibe-sdk/usage`; null fields stripped; money fields never invented); `usageKey(service, ...parts)` joins an idempotency key with `:`; `validateUsageSample(record)` → `{ok, errors}` (openvibe-contracts, required lazily). `createUsageReporter({ db, service, source, table, billingUrl, tokenClient, audience, requireProject, ... })` owns one service's readings: `key(...parts)`/`sample(fields)`, and `record(t, reading)` queues the reading idempotency-keyed in the outbox inside the caller's transaction, relayed to Billing's `billing.usage.record` with backoff (a retry is never dropped; only Billing refusing the reading itself — any 4xx but 401/403/404/408/425/429, which stay pending — marks a row rejected; a 401 drops the cached token). The reporter bills whatever reading it is given: never record first-party or sandbox traffic (pass `requireProject: true` to refuse a reading without a `prj_…` project). `openvibe-sdk/govern` builds its `onUsage` record with it |
| `openvibe-sdk/commerce` | server | `createCommerceClient(config, {caps, fetchImpl?, tokenClients?, timeoutMs?})`: the Billing client Tips and VIP share. `config` = `{billing: {url, audience, timeoutMs = 10000}, network: {internalUrl}, oauth: {clientId, clientSecret}}`; `caps` maps `intent`, `transfer`, `subscription`, `entitlement` (and optional `rates`, default `entitlement`) to capability strings, one lazily created `serviceAuth` token client per distinct string (`scope` = the string) unless `tokenClients` supplies one, keyed by logical key or capability. Methods: `createIntent` (`kind` purchase with `bits`, or subscription with `creator`/`autoRenew`), `createTransfer`, `refundTransfer`, `subscribeWithCredit`, `cancelSubscription`, `getSubscription`, `listSubscriptions`, `entitlement`, `rates`, `baseUrl`. `Idempotency-Key` is sent verbatim; a 401 invalidates the token and retries once with the same key; problem+json becomes `CommerceError` (`status`, `code`, `body`, `retryable`). `intentKey(prefix, parts)` joins the parts that are set; `receipt(kind, fields)` → `{kind, at, ...fields}` (null stripped, never posted). `openvibe-contracts` is required lazily |
ddiff --git a/browser/openvibe-sdk.mjs b/browser/openvibe-sdk.mjs
iindex 6547da7..0005c66 100644
---- a/browser/openvibe-sdk.mjs
++++ b/browser/openvibe-sdk.mjs
@@@ -1850,7 +1850,7 @@ function createBotClient(client, defaults = {}) {
*/
command: (id, input, o = {}) => call({ method: 'POST', path: `/api/v1/robots/${enc(id)}/commands`, json: input }, o),
streaming: {
-- /** The owner's OpenRe toggles (Bot stores no copy). A member read. */
++ /** The owner's OpenRestream toggles (Bot stores no copy). A member read. */
get: (id, o = {}) => call({ path: `/api/v1/robots/${enc(id)}/streaming` }, o),
/** { to?, on? } (a service must also act for the owner) -> the new streaming state. */
set: (id, input = {}, o = {}) => call({ method: 'POST', path: `/api/v1/robots/${enc(id)}/streaming`, json: input }, o),
ddiff --git a/docs/service.md b/docs/service.md
iindex 003987e..fa0c1ae 100644
---- a/docs/service.md
++++ b/docs/service.md
@@@ -13,7 +13,7 @@ dependency, and a service that lacks the package gets an error naming it (`code:
Convert one service at a time, smallest first (the audit's order): Blog, Codes, News, Deals, Coupons, VIP, Tips, Trade
(errors only), Wiki, Reviews, Network, Community, Billing, Bot, Chat, Host, AI, Events, Search, Sources, Media,
--OpenRe.Stream, Live.
++OpenRestream, Live.
## The stop
@@@ -154,9 +154,9 @@ lifecycle = gracefulStop({
with the `accepting` readiness check above replacing `_bootComplete = false`. The drill branch (3 s) stays outside the
kit.
--### OpenRe.Stream
++### OpenRestream
--It has no hard timer today. `gracefulStop({ name: 'OpenRe', server, close: [...] })` adds one (5 s, exit 1): new
++It has no hard timer today. `gracefulStop({ name: 'OpenRestream', server, close: [...] })` adds one (5 s, exit 1): new
behaviour, but a safer one.
## The telemetry
ddiff --git a/src/bot.js b/src/bot.js
iindex 63115f5..bc3ab3d 100644
---- a/src/bot.js
++++ b/src/bot.js
@@@ -96,7 +96,7 @@ function createBotClient(client, defaults = {}) {
*/
command: (id, input, o = {}) => call({ method: 'POST', path: `/api/v1/robots/${enc(id)}/commands`, json: input }, o),
streaming: {
-- /** The owner's OpenRe toggles (Bot stores no copy). A member read. */
++ /** The owner's OpenRestream toggles (Bot stores no copy). A member read. */
get: (id, o = {}) => call({ path: `/api/v1/robots/${enc(id)}/streaming` }, o),
/** { to?, on? } (a service must also act for the owner) -> the new streaming state. */
set: (id, input = {}, o = {}) => call({ method: 'POST', path: `/api/v1/robots/${enc(id)}/streaming`, json: input }, o),
ddiff --git a/src/openre.js b/src/openre.js
iindex 73f974a..6ae0d07 100644
---- a/src/openre.js
++++ b/src/openre.js
@@@ -1,6 +1,6 @@
'use strict';
/**
-- * openvibe-sdk/openre — OpenRe.Stream, the platform's streaming engine (ingest, sessions, restream outputs), for
++ * openvibe-sdk/openre — OpenRestream, the platform's streaming engine (ingest, sessions, restream outputs), for
* every product that puts a stream on air (OpenVibe.Live first). One client instead of a copy in each product.
* Server-side: it sends a Network service token for audience openvibe.openre.
*
@@@ -13,7 +13,7 @@
*
* Grants (on the caller's principal, audience openvibe.openre): openre.stream.read / .write, openre.key.rotate,
* openre.output.read / .write, openre.session.read / .end. `subject` names the person a call acts for
-- * (X-OV-Subject; a usr_ id); OpenRe checks that they own the stream. Errors are OpenVibeError (status, code);
++ * (X-OV-Subject; a usr_ id); OpenRestream checks that they own the stream. Errors are OpenVibeError (status, code);
* a missing stream, destination or session is null from get(), not an error.
* Shapes: Contracts openre.stream@1, openre.destination@1, openre.output@1, openre.session-read-result@1.
*/
@@@ -82,7 +82,7 @@ function createOpenReClient(client, { baseUrl, publicUrl = 'https://openre.strea
sessions,
outputLogs: (id, { subject, limit } = {}) => call({ path: `/api/v1/outputs/${enc(id)}/logs`, query: { limit }, subject }),
workers: () => call({ path: '/api/v1/workers' }),
-- /** The standalone UI's page for a stream (for "manage on OpenRe.Stream" links). */
++ /** The standalone UI's page for a stream (for "manage on OpenRestream" links). */
manageUrl: (streamId) => `${String(publicUrl).replace(/\/+$/, '')}/streams/${enc(streamId || '')}`,
clearCache: () => playbackCache.clear(),
};
ddiff --git a/test/openre.test.js b/test/openre.test.js
iindex 3140e6b..fdf8af4 100644
---- a/test/openre.test.js
++++ b/test/openre.test.js
@@@ -1,5 +1,5 @@
'use strict';
--/** OpenRe: service-token calls with the acting subject, external_ref lookup, key rotation, null for a missing
++/** OpenRestream: service-token calls with the acting subject, external_ref lookup, key rotation, null for a missing
* stream or session, playback cached 10 s, destinations and sessions paths, and errors kept as OpenVibeError. */
const assert = require('node:assert/strict');
const { stubServer, send, run } = require('./helpers');