Commits
-
Contracts 0.41.1 (plain-language module descriptions); the AI & Data tab names who keeps each record (OpenVibe.Chat, OpenVibe.Tools…)OpenVibers · 25 Sept 2026
c47ad2fc -
User modules (Contracts 0.41.0, WS-B task 9): a service reading another's namespace sees only the fields readers lists for it; stored records read at the current version through the namespace's migrations and are stored at it on the next write; grants for chat.tts_defaults/dm_settings/presence_prefs (Chat), live.stats (Live, which loses its chat.* grants), ai.preferences/ai.usage_summary (AI), community.profile, wiki.projects; my.openvibe.network stars favourite tools (tools.usage v2)OpenVibers · 25 Sept 2026
707504c2 -
Contracts 0.40.0: openvibe.chat joins the first-party origins (the shared navbar on the new Chat site talks to Network)OpenVibers · 24 Sept 2026
ee78598d -
Username history (WS-B task 6): admins rename people (admin → Users → Rename, owner-protected, audited); every rename is kept in username_history, the old name stays reserved for 180 days (registration and renames refuse it for anyone else), and GET /api/v1/users/renamed/:name gives the current name so sites redirect /@old → /@new. Admin users also get 'Sign out everywhere'. test/usernames.test.jsOpenVibers · 24 Sept 2026
74d46102 -
Revocation propagation (WS-B task 4, Contracts 0.39.0): revokeTokens() moves token_valid_after, ends Network sessions and queues network.user.token_valid_after in the same transaction; password change and reset, bans, POST /api/auth/sign-out-everywhere and admin POST /users/:id/sign-out use it. 'Revoke All Sessions' only deactivated session rows while every token stayed valid: it is now 'Sign out other devices' (all tokens end, this browser gets a fresh one), next to 'Sign out everywhere, this device too'. test/revocation.test.jsOpenVibers · 24 Sept 2026
8033d016 -
User tokens carry staff_map (the staff map version their staff_caps come from; Contracts 0.38.0, map 1.1.0), so services judge capabilities added later by the role instead of waiting for new tokensOpenVibers · 24 Sept 2026
196c76ef -
The GitHub token is configurable in admin (Settings → GitHub, owner-only): GITHUB_TOKEN in the environment first, else the saved value; admin shows its source and last four characters and a Test that asks GitHub for the rate limit, never the value. The registry's library tags read it at call time; OpenVibe.Blog reads it over GET /internal/integrations/github-token with capability network.integration.github.read (Contracts 0.37.0, granted to blog only, no shared key). test/github-integration.test.jsOpenVibers · 24 Sept 2026
8c9fa757 -
The moderation audit log (ADR-022): Network records chat.moderation.action (Chat and Live), community.moderation.action, tips.interaction.moderated and billing.staff.action from Events, once each inside the consumer's inbox transaction and never as notifications; staff with staff.moderation.logs list them at GET /api/v1/staff/moderation-audit (service/actor/target filters, paged) and in admin's Moderation log tab; openvibe-contracts 0.36.0OpenVibers · 24 Sept 2026
b1b9f92c -
openvibe-shared 1.12.0 (the navbar loads its siblings from its own origin)OpenVibers · 24 Sept 2026
6be99391 -
The registry reports each released library's latest published tag (read from GitHub at boot and hourly; the installed version until then, and whenever a lookup fails) instead of the version Network happens to install — it said openvibe-sdk v0.5.0 while v0.8.0 was outOpenVibers · 24 Sept 2026
eb9a1617 -
Brand assets (/assets/*: logo, app icons, OG images) are readable cross-origin and cached for a day: helmet's Cross-Origin-Resource-Policy same-origin blocked the logo on every placeholder siteOpenVibers · 24 Sept 2026
fce09312 -
openvibe-shared 1.11.1: the footer's shipped line follows each site's own serviceOpenVibers · 24 Sept 2026
b95d2d0f -
The OpenVibe Frame: server/chrome is server/frame; /api/frame and /api/frame/hit (the /api/chrome names stay as aliases for openvibe-shared older than 1.11.0); chrome_cache/chrome_hits are renamed frame_cache/frame_hits once on boot, rows kept (tested); openvibe-shared 1.11.0 (openvibe-shared/frame)OpenVibers · 24 Sept 2026
7571ba73 -
What shipped, network-wide: /api/v1/changelog proxies OpenVibe.Blog's changelog (60 s cache, stale on failure, public CORS) so every site's shared widget reads it from openvibe.network; /updates renders the whole network's log (server-side first page, then openvibe-shared shipped.js: days, Load more, a filter per site, Patch notes). openvibe-shared 1.9.0 (footer 'shipped X ago' line and Updates link on every site, navbar stale-token fallback to the site session, footer empty-bar fix); home links All updatesOpenVibers · 24 Sept 2026
0b3b2e36 -
CORS: every first-party domain the service manifests declare is an allowed origin (exact https origins, never a wildcard). openvibe.blog, openvibe.wiki and openvibe.codes were missing from the hard-coded list, so the shared navbar's /api/auth/me was refused there and signed-in people saw 'Sign In'OpenVibers · 24 Sept 2026
90cd58e7 -
Recently shipped across OpenVibe on the home page: openvibe-shared v1.8.0 (served as /shared/shipped.js for every site) renders the network changelog from openvibe.blog, each change linked to its commit and the latest Patch notes post; connect-src allows openvibe.blog; a no-JS link to the Patch notes seriesOpenVibers · 24 Sept 2026
6e794b93 -
Community may publish its events (events.event.publish on openvibe.events); openvibe-contracts v0.35.0 (community.* payload contracts)OpenVibers · 24 Sept 2026
1837cb89 -
openvibe-contracts v0.34.1 (Tools platform S7): sandbox apps hold tools.tool.read and tools.tool.run by default (the run API is live); the self-service catalog lists public capabilities only (partner ones like tools.net.probe are staff-granted); the publishing library joins the registry's libraries; realtime is retired (ADR-005) in the registry testsOpenVibers · 24 Sept 2026
1664d042 -
openvibe-contracts v0.33.1: tools.tool.read is active (Tools serves GET /api/v1/tools on the gateway and every satellite), so the registry and /status show it as such; tools.tool@1 1.1.0 adds optional keywords and examples. Additive; pins only (npm install on the host rewrites package-lock.json with npm 9: git checkout -- package-lock.json after)OpenVibers · 24 Sept 2026
9a59212a -
Provider secrets from the environment first (roadmap §18.2(12)): the Resend API key and webhook secret, the Discord bot token and OAuth client secret, and the VAPID private key were read only from site_settings in plaintext. Each now has a variable (RESEND_API_KEY, RESEND_WEBHOOK_SECRET, DISCORD_BOT_TOKEN, DISCORD_OAUTH_CLIENT_SECRET, VAPID_PRIVATE_KEY; server/secrets.js) that db.getSetting reads first, so every reader is environment-first; the database row stays the fallback, so nothing changes until the operator moves a value. Which source each uses is reported by name only: the boot line [Secrets] key=env|database|unset, GET /api/admin/secrets (owner), api_key_source in the email status and sources in the Discord settings. The admin panel shows an environment-provided secret as set in the environment (input disabled), and the email, settings and Discord endpoints never save one into the database while its variable is set. Web push derives the VAPID public key from the private key, so a private key in the environment (or a stale public key beside it) still gives a matching pair and no new pair is generated over it. scripts/secrets-out-of-db.js lists the secret setting names with their variable, whether the env file sets it to the same value and whether the running service has it (never a value); --apply --backup <new file> blanks only the copies the environment and the restarted service already provide (a different value only with --allow-different) plus the settings Network never reads (net.* tokens, old ses_* keys); --restore-from <backup> [--apply] rolls back. Run with sudo, it reads the env file and /proc/<pid>/environ, then becomes the database owner. test/provider-secrets.test.jsOpenVibers · 24 Sept 2026
70050bca -
Refresh tokens (roadmap §18.2(2)): oauth_tokens held each refresh token in clear, and presenting a rotated token again only failed. Now only its SHA-256 is stored; every token belongs to the family of the sign-in that issued it (family_id) and carries a generation (0 at sign-in, +1 per rotation); presenting an already rotated token revokes every live token of its family (revoked_reason reuse) and writes an oauth_refresh_reuse audit row with the presented and current generation, never a token. A second use within 10 seconds of the rotation is refused without revoking the family (two tabs refreshing through Live's cookie at once). Boot adds the columns only. Rows written before keep working: a raw row is matched and hashed on first use, and a stored hash presented as a token matches nothing. scripts/hash-refresh-tokens.js hashes the rest in place, one-way: dry run by default, --apply requires --backup <new file> (online, 0600, quick_check), --restore-from <backup> [--apply] puts the raw values back for a rollback to the previous release; run as root it becomes the database owner first (scripts/lib/db-ops.js). server/auth/refresh-tokens.js; test/refresh-tokens.test.jsOpenVibers · 24 Sept 2026
1cf0191c -
OpenID Connect discovery at the issuer (roadmap §4.1, §15.4): https://openvibe.network/.well-known/openid-configuration answered with the account page; discovery lived only at /oauth/.well-known/openid-configuration. The document is now served at the issuer's root, at RFC 8414's /.well-known/oauth-authorization-server and still at the old path, and /.well-known/openvibe points at the standard one. The metadata is made true rather than aspirational: it advertised scope openid and RS256 id tokens while none was ever issued, and named /api/auth/me (not OIDC-shaped) as userinfo. Scope openid now adds an RS256 id_token to the code grant (kid ov-network-1 as the JWKS publishes, aud = client, sub = the Network id as a string like access tokens, subject_id, and the authorize nonce, threaded through the account chooser and stored with the code in oauth_codes.nonce); /oauth/userinfo returns the same claims for an unexpired access token. Without openid the token response is unchanged. server/auth/oidc.js; test/oidc-discovery.test.js boots the real server for the documents and runs the code flow for id_token and userinfoOpenVibers · 24 Sept 2026
abee5dc1 -
Unknown paths answer 404 (roadmap §2.5, D44): the apex sent the account hub (my.html) with 200 for any path, so openvibe.network/<anything> looked like a page. Every real page keeps its own route; the account hub answers only at its own sections (server/not-found.js ACCOUNT_HUB_PATHS) and /admin/* stays the admin SPA. Anything else, any method, gets a 404: JSON under /api, /internal and /oauth, otherwise a small noindex page with links home, to the account, sign-in and status. test/unknown-paths.test.js boots the real server (test/helpers/boot-server.js: scratch database, loopback, ephemeral keys, no egress) and checks both sidesOpenVibers · 24 Sept 2026
f87b5149 -
openvibe-shared v1.5.1, openvibe-contracts v0.33.0OpenVibers · 23 Sept 2026
f76130d5 -
openvibe-shared v1.5.0 (Track R release manifest), openvibe-contracts v0.32.0, openvibe-sdk v0.5.0OpenVibers · 23 Sept 2026
0b756833 -
User modules (roadmap Wave 1 item 24): every change emits network.module.updated, account removal and merge handle module rows, onOwnerRemoved is enforced, and chat.preferences belongs to Chat. Events: server/identity/module-events.js builds the envelope (source network, visibility internal, subject { type user_module, id <owner>:<namespace>, revision }, actor = the person, the owning service or system:network) and writes it into network_event_outbox in the transaction that makes the change; payload owner, namespace, namespace_owner, schema_version, revision, change (created|updated|deleted), reason (write|delete|owner_delete|subject_removed|subject_merged), keys (changed top-level field names), public (new values of changed public fields only; never a value of a private namespace), merged_into/merged_from. event-relay.js writerFor() enqueues into the running relay's outbox or, when this process relays nothing (OV_EVENTS_INTERNAL_URL unset, or a script), a passive one on the same table, so rows wait there and the relay sends them; the table is created at boot. Revisions only grow per (subject, namespace): user_module_revisions keeps the last one issued, so a delete has a revision and a re-created record continues after it. Owner services get DELETE /internal/modules/:ns/:subject (token only, If-Match optional). Accounts: onSubjectRemoved() deletes a subject's records and revisions with one event each; onSubjectMerged() moves each record to the survivor where it has none and drops it where it has one (updated_by svc:network), events on both sides. Network has no account deletion or merge today, so triggers refuse deleting a users/anon_users row or changing its subject_id while module rows remain; the one merge that exists, POST /api/auth/anon/:token/link, now moves the guest's records to the account. onOwnerRemoved (contract modules.namespace@1): when the owner's service manifest says retired the namespace is read-only (409 modules.namespace_retired, userWritable false), and a daily sweepRetired() empties delete-after-retention namespaces retentionDays after Network first saw the retirement (user_module_retirements). chat.preferences: OWNER_HANDOFFS makes Chat its owner while the installed manifest (0.30.x) still names live ("moves to OpenVibe.Chat in Wave 6"); Chat gets network.modules.read/write on chat.preferences, Live keeps reading it and its default write grant narrows to chat.tts_defaults and live.profile at boot (only a row still as seeded). The registry lists network.module.updated as an observed Network topic. test/module-events.test.js covers all of it plus the relay publishing rows written while it was off; test/developer-defaults.test.js now checks that nothing is queued while the relay is off (the table exists from boot). README: User modules section and tables.OpenVibers · 23 Sept 2026
ea29f8e8 -
Analytics comes from openvibe-shared/analytics (v1.4.0; retires C-80): server/analytics/ keeps only network.js, the service specifics (SERVICE, PARAM_PREFIXES, PATH_RULES, and PATH_OPTS = { paramPrefixes, pathRules }); openAnalytics keeps its own connection to network.db and returns the package's AnalyticsTracker with retention: false and those path options, so the NetworkAnalyticsTracker subclass, preReducePath and prescrub are gone (the package applies pathRules in the tracker and in the scrub); schedulePrune is retention.schedulePrune. The hand-copied index/privacy/retention/schema/tracker files are deleted. scripts/analytics-prune.js is a wrapper over openvibe-shared/analytics/prune-cli with Network's path options, repo-root-relative paths, the defaultDbPath export and the VACUUM warning in its help. test/analytics-privacy.test.js tests the package with Network's options, checks every written row against analytics/event.v1, and sends a Sec-GPC and a DNT request through Network's routers that leave nothing. New with v1.4.0: a request with Sec-GPC: 1 or DNT: 1 is not recorded at all (no raw row, visitor hash, session id or rate counter); README notes itOpenVibers · 23 Sept 2026
9bbd90f7 -
Registry completeness: /api/v1/registry/topics lists every event type from the manifests' eventsProduced/eventsConsumed and the v0.30 payload contracts (producers, consumers with the Events-syntax pattern that matched, payload contract with its $id and status; filters service/producer/consumer/prefix, plus /topics/:topic). Live and Media list no eventsProduced in contracts 0.30.1, so server/registry/topics.js OBSERVED declares what their code publishes (live.stream.started/ended from stream-events.js; media.vod/clip ready|failed, media.object.uploaded, media.storage.alert|recovered from Media server/events.js), marked observed on the service row, and Network's consumed topics come from its own Events consumer TOPICS. New /releases (each running service's /release.json from the loopback health poll, now keeping contracts_version and openvibe-* package versions, with drift against the libraries' current releases), /health and /search?q=. Payload schemas are served at their $id (/contracts/events/payloads/<type>.v1.json) and are CORS-public. scripts/contracts-drift.js warns (::warning:: in Actions, exit 0 unless --strict) about services pinning an older openvibe-contracts/sdk/shared than the latest tag or an unpublished tag, from GitHub, local checkouts (--dir) or the running registry (--registry); CI runs it as a continue-on-error step and weekly. test/registry-topics.test.jsOpenVibers · 23 Sept 2026
5ad26eca -
openvibe-contracts v0.28.0 -> v0.30.1: realtime is the only placeholder manifest left (AI, SDK, Shared and Examples are alpha), so the exposure overlay's comment says how each exists instead of correcting a placeholder label, the contracts library row reads v0.30.1, and AI is polled on its manifest's own /api/health and /api/ready (the READY_PATHS/HEALTH_PATHS stand-ins are gone). Footer site copy reads the answering model from run.provenance.model (ai.run@1; run.route is { key, version }, there is no run.model), and test/chrome.test.js answers with the contract's shape and checks the stored modelOpenVibers · 23 Sept 2026
692c7751 -
Notifications from Events: POST /internal/events turns deals.watch.matched (payload.recipient) and trade.alert.triggered (subject user) into inbox notifications (DEAL_WATCH_MATCH / TRADE_ALERT, category service, so the person's mute and email choices apply). openvibe-sdk v0.4.0 parseDelivery with requireV2 (v1-only, stale or forged deliveries are refused), exactly once per event_id through the SDK inbox (network_event_inbox), unknown types acknowledged and ignored, links only to sites whose domain serves the service. Inert until NETWORK_EVENTS_SECRET is set and scripts/subscribe-events.js has created the two subscriptions (consumer network, endpoint http://127.0.0.1:4000/internal/events). Coupons publishes no watch event yet, so there is nothing of it to consumeOpenVibers · 23 Sept 2026
07cd98c7