openvibers/openvibe.contracts Commits
Manifests: every service names its PostgreSQL database (no SQLite left) (#92)
Changes
@@@ -28,7 +28,7 @@ service id); **Runtime** is `STATUS.json.runtime`; **Database** is inferred from| OpenVibe.Extensions | — | — | node >=22.0.0 | — | — | — | not deployed | — | W18 || OpenVibe.Games | Games | games.* | node 22 | PostgreSQL | openvibe.games, play.openvibe.games | contracts v0.78.0, sdk v0.23.1, shared v2.6.0 | deployed | live | — || OpenVibe.Host | Host | host.* | node 22 | PostgreSQL | openvibe.host | contracts v0.83.0, sdk v0.26.0, shared v2.10.1 | loopback only, not launched | live | W21 Stage A + Stage B |--| OpenVibe.Live | Live | live.* | node 22 | SQLite | openvibe.live, ingest.openvibe.live | contracts v0.83.0, sdk v0.26.0, shared v2.5.0 | deployed | live | — |++| OpenVibe.Live | Live | live.* | node 22 | PostgreSQL (ov_live) | openvibe.live, ingest.openvibe.live | contracts v0.83.0, sdk v0.26.0, shared v2.5.0 | deployed | live | — || OpenVibe.Media | Media | media.* | node 22 | PostgreSQL | openvibe.media | contracts v0.79.0, sdk v0.32.0, shared v2.10.0 | deployed | live | — || OpenVibe.Network | Network | identity.*, network.*, theme.*, notification.* | node 22 | PostgreSQL | openvibe.network, auth.openvibe.network, api.openvibe.network, admin.openvibe.network, my.openvibe.network, themes.openvibe.network | contracts v0.106.0, sdk v0.28.0, shared v2.10.1 | deployed | live | — || OpenVibe.News | News | news.* | node 22 | PostgreSQL | openvibe.news | contracts v0.97.0, sdk v0.26.0, shared v2.9.0, publishing v1.3.0 | deployed | internal | W17 |@@@ -6,7 +6,7 @@"stage": "stable","version": "1.0.0","runtime": "node 22",-- "database": "SQLite",++ "database": "PostgreSQL (ov_live)","migrations": 1,"authority": ["live.*"@@@ -93,7 +93,7 @@"claims": [{"what": "a stored provider event (provider_events row) while it is applied",-- "holder": "the connection that takes the SQLite write lock (IMMEDIATE transaction)",++ "holder": "the connection that locks the provider_events row in an ov_billing PostgreSQL transaction","expires": "at commit or rollback of that transaction","fencing": "processed_at is re-read inside the transaction, so a second process or connection that waited applies nothing; ledger postings carry idempotency keys"}@@@ -114,5 +114,5 @@]}},-- "notes": "Port 4810. Owns blogs, blog_memberships, blog_posts, blog_post_revisions, blog_series, blog_taxonomy, blog_post_terms, blog_schedules, blog_redirects, blog_feed_settings in its own SQLite (openvibe-publishing packages, prefix blog). Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Community (community.comment.write, community.comment.moderate), OpenVibe.Media (media.object.read, namespace blog) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads blog.index_document.* from Events."++ "notes": "Port 4810. Owns blogs, blog_memberships, blog_posts, blog_post_revisions, blog_series, blog_taxonomy, blog_post_terms, blog_schedules, blog_redirects, blog_feed_settings in its own PostgreSQL database ov_blog (openvibe-publishing packages, prefix blog). Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Community (community.comment.write, community.comment.moderate), OpenVibe.Media (media.object.read, namespace blog) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads blog.index_document.* from Events."}@@@ -67,7 +67,7 @@"range": ">=0.26.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns codes.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_codes PostgreSQL database; writes are transactions there"}},"notes": "Port 4900, unit openvibe-codes.service. The open coding-agent harness (owner 2026-10-08): the harness catalog and router (GET /api/v1/harnesses, POST /api/v1/harnesses/route), the way to improve OpenVibe (contributing, code of conduct, the contributor ladder) and permanent redirects from the former developer-portal paths to openvibe.services, where the portal moved (manifests, releases, trust, playgrounds, docs, OAuth and webhook tools)."@@@ -73,7 +73,7 @@"Pulse subscription retries, the community.profile scan and the search-document scans stopped","stops taking connections; idle keep-alive connections closed (kept 65 s otherwise); requests in flight answered with Connection: close and allowed to finish (4 s at most, then cut)","the profile scan in progress (it stops between people), the Discord relay's drain and the events outbox's send awaited; unsent rows stay in their tables",-- "community.db closed, exit 0"++ "the ov_community PostgreSQL database closed, exit 0"],"note": "server/graceful.js; a stop that passes 5 s exits 1. Only the in-memory rate-limit sweeps end with the process. The unit sets no TimeoutStopSec (systemd's 90 s default applies)"},@@@ -107,7 +107,7 @@"range": ">=0.5.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns community.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_community PostgreSQL database; writes are transactions there"}},"notes": "Community serves the forum (spaces, threads, posts, votes, categories, moderation and the Discord relay), pastes, comments, Pulse and submissions. The forum returned to Community from OpenVibe.Space (owner decision 2026-10-08): the community.* forum capabilities, contracts and events are active again, the community.space.*/thread.read/post.create routes and the /s pages and feeds serve production, and Space no longer serves a forum."@@@ -127,8 +127,8 @@"range": ">=0.19.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns coupons.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_coupons PostgreSQL database; writes are transactions there"}},-- "notes": "Port 4850. Owns coupon_merchants, coupon_merchant_domains, coupons, coupon_sources, coupon_restrictions, coupon_validation_reports, coupon_status_history, coupon_application_hints, coupon_watches in its own SQLite, plus extension_installs (cpx_ browser-helper tokens, scopes coupons.lookup and coupons.report, hashed, revocable). Consumes OpenVibe.Network (SSO, JWKS) and OpenVibe.Sources (sources.item.read, category coupons); publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads coupons.index_document.* from Events. The browser helper lives in OpenVibers/OpenVibe.Extensions (ADR-023)."++ "notes": "Port 4850. Owns coupon_merchants, coupon_merchant_domains, coupons, coupon_sources, coupon_restrictions, coupon_validation_reports, coupon_status_history, coupon_application_hints, coupon_watches in its own PostgreSQL database (ov_coupons), plus extension_installs (cpx_ browser-helper tokens, scopes coupons.lookup and coupons.report, hashed, revocable). Consumes OpenVibe.Network (SSO, JWKS) and OpenVibe.Sources (sources.item.read, category coupons); publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads coupons.index_document.* from Events. The browser helper lives in OpenVibers/OpenVibe.Extensions (ADR-023)."}@@@ -142,8 +142,8 @@"range": ">=0.19.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns deals.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_deals PostgreSQL database; writes are transactions there"}},-- "notes": "Port 4840. Owns deal_products, deal_product_aliases, deal_offers, deal_offer_sources, deal_votes, deal_hotness_snapshots, deal_watches, deal_price_observations, deal_flags (+ deal_stores) in its own SQLite. Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Sources (sources.item.read; sources.item.* events only wake the pull), OpenVibe.Community (community.comment.write, community.comment.moderate) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads deals.index_document.* from Events; OpenVibe.Network turns deals.watch.matched into notifications (server/notifications/events-consumer.js)."++ "notes": "Port 4840. Owns deal_products, deal_product_aliases, deal_offers, deal_offer_sources, deal_votes, deal_hotness_snapshots, deal_watches, deal_price_observations, deal_flags (+ deal_stores) in its own PostgreSQL database (ov_deals). Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Sources (sources.item.read; sources.item.* events only wake the pull), OpenVibe.Community (community.comment.write, community.comment.moderate) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads deals.index_document.* from Events; OpenVibe.Network turns deals.watch.matched into notifications (server/notifications/events-consumer.js)."}@@@ -76,7 +76,7 @@"range": ">=0.5.1 <1.0.0"},"leases": {-- "none": "no claims: one process owns events.db (better-sqlite3, single writer); one delivery per subscription is in flight at a time, tracked in memory"++ "none": "no claims: one process owns the ov_events PostgreSQL database; writes are transactions there; one delivery per subscription is in flight at a time, tracked in memory"}},"notes": "Durable events, subscriptions, signed delivery with retry, dead letters and replay; SSE realtime gateway at /realtime/stream (ADR-005); browsers on any OpenVibe site authenticate a stream with a two-minute, single-use realtime ticket from Network (?ticket=, identity.realtime-ticket-claims@1; ADR-005 amendment 2).",@@@ -58,7 +58,7 @@"lifecycle": {"liveness": {"endpoint": "/healthz",-- "means": "the process is up and answers HTTP; liveness only (world.db and the simulation tick are what /api/ready checks)"++ "means": "the process is up and answers HTTP; liveness only (the ov_games PostgreSQL database and the simulation tick are what /api/ready checks)"},"shutdown": {"signal": "SIGTERM",@@@ -71,7 +71,7 @@"world saved: every session marked dirty and flushed (game.shutdown)","requests in flight finish (5 s at most, then cut)","the media mirror's pass in progress (2 s at most), the progress-summary writes (1 s) and the outbox's last send (2 s) awaited; unsent rows stay in the outbox",-- "world.db closed, physics disposed, exit 0"++ "the ov_games PostgreSQL database closed, physics disposed, exit 0"],"note": "clients reconnect on their own after 1012; the whole stop is bounded at 10 s (exit 1 past it), inside the unit's TimeoutStopSec=30"},@@@ -79,7 +79,7 @@"resumes": [{"kind": "state",-- "what": "the world is restored from world.db before the network opens (schema migrated forward first)"++ "what": "the world is restored from the ov_games PostgreSQL database before the network opens (schema migrated forward first)"},{"kind": "outbox",@@@ -100,16 +100,16 @@"automatic: ovhost deploy games (strategy pnpm-build) restores the previous sha, rebuilds and restarts when the ready URL does not answer 2xx after the restart","manual: sudo ovhost rollback games --to <sha> (rebuilds the workspace)"],-- "window": "as long as world.db has not been migrated past the older build's SCHEMA_VERSION",++ "window": "as long as the ov_games PostgreSQL database has not been migrated past the older build's SCHEMA_VERSION","blockers": [-- "a build refuses a world.db whose meta.schema_version is newer than its own (SCHEMA_VERSION 13 today, forward-only migrations): going back past a schema bump fails at boot"++ "a build refuses the ov_games PostgreSQL database whose meta.schema_version is newer than its own (SCHEMA_VERSION 13 today, forward-only migrations): going back past a schema bump fails at boot"]},"contracts": {"range": ">=0.8.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns world.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_games PostgreSQL database; writes are transactions there"}},"notes": "Scraplandia (browser runtime). Players are keyed by canonical Network subjects (ADR-0006 in the repo). Calls Events (events.event.publish), Media (media.object.upload, namespace games: map-editor assets) and Network identity (identity.subject.resolve, batch legacy adoption) with the games client-credentials principal. Mods: games-content@1 declarative packs only; executable mods wait for OpenVibe.Host Stage C. No achievement system exists, so there are no games.achievement.* events."@@@ -124,7 +124,7 @@"maintenance timers (notifications, email queue, retired-module sweep, session cleanup), the analytics prune, the ecosystem, deploy-drift and library-tag pollers, the frame refreshes and the profile-event and grant-expiry timers stopped","stops taking connections; idle keep-alive connections closed; requests in flight answered with Connection: close and allowed to finish (8 s at most, then cut)","the developer, profile and grant event relay's send in progress awaited (unsent rows stay in the outbox)",-- "analytics flushed and closed; network.db closed; exit 0"++ "analytics flushed and closed; the ov_network PostgreSQL database closed; exit 0"],"note": "openvibe-sdk/service; a stop that passes 10 s exits 1. Only the Discord link's in-memory state sweep ends with the process; the email queue and the outboxes resume from the database on the next start"},@@@ -163,7 +163,7 @@"range": ">=0.2.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns network.db (better-sqlite3, single writer); a stream-live announcement is claimed per streamer with a cooldown and a daily cap in the same database"++ "none": "no claims: one process owns the ov_network PostgreSQL database; Network's live.stream.started consumer claims a stream-live announcement per streamer with a cooldown and a daily cap in one transaction there"}}}@@@ -140,8 +140,8 @@"range": ">=0.19.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns news.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_news PostgreSQL database; writes are transactions there"}},-- "notes": "Port 4820. Owns news_topics, news_source_items, news_story_clusters, news_stories, news_story_revisions, news_story_sources, news_perspectives, news_timeline_entries, news_editorial_flags in its own SQLite (openvibe-publishing packages, prefixes news_story and news). Consumes OpenVibe.Sources (sources.item.read, optionally sources.source.read) through an Events subscription (sources.item.*, sources.fetch.failed; events.subscription.manage) and a cursor pull; OpenVibe.Network (SSO, identity.subject.resolve); optionally OpenVibe.AI (ai.run.create, namespace news) for news.summarize_story and news.compare_perspectives drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads news.index_document.* from Events."++ "notes": "Port 4820. Owns news_topics, news_source_items, news_story_clusters, news_stories, news_story_revisions, news_story_sources, news_perspectives, news_timeline_entries, news_editorial_flags in its own PostgreSQL database ov_news (openvibe-publishing packages, prefixes news_story and news). Consumes OpenVibe.Sources (sources.item.read, optionally sources.source.read) through an Events subscription (sources.item.*, sources.fetch.failed; events.subscription.manage) and a cursor pull; OpenVibe.Network (SSO, identity.subject.resolve); optionally OpenVibe.AI (ai.run.create, namespace news) for news.summarize_story and news.compare_perspectives drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads news.index_document.* from Events."}@@@ -138,7 +138,7 @@"range": ">=0.19.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns reviews.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_reviews PostgreSQL database; writes are transactions there"}},"notes": "Entities with aliases and typed links; resolution of OpenVibe.Sources review items by deterministic rules (source binding, URL, GTIN/SKU/MPN) with editor confirmation for name-only and conflicting matches; merges that rewrite nothing and splits that restore attribution exactly, both audited; typed signals with provenance (source item, item revision, retrieval time, licence note) and trust metadata; aggregates computed only from signals present (method reviews-aggregate@1, inputs and exclusions exposed, absent without qualifying signals, a new revision on every change); editor-written or AI-drafted-and-approved summaries whose points cite signals and never carry a rating; source removal withdraws signals, flags citing summaries and prepares a pending revision; corrections queue; Community discussion referenced, not copied. Server-rendered pages useful without JavaScript; AggregateRating/Product/Review JSON-LD only when signals back it; sitemaps, feeds and Search index events from the openvibe-publishing v0.2.0 gate. Deployed internally (loopback only), not launched publicly: openvibe.reviews serves the OpenVibe.Sites placeholder until the launch rule holds."@@@ -80,10 +80,10 @@"range": ">=0.7.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns search.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_search PostgreSQL database; writes are transactions there"}},-- "notes": "Canonical index document (search.index-document@1), event-fed and direct indexing with revision ordering and tombstones, permission-aware query over SQLite FTS5 (docs/adr-engine.md). Anonymous queries need no token.",++ "notes": "Canonical index document (search.index-document@1), event-fed and direct indexing with revision ordering and tombstones, permission-aware query over PostgreSQL full-text search in ov_search (docs/adr-engine.md). Anonymous queries need no token.","site": {"name": "Search","icon": "search",@@@ -76,7 +76,7 @@"range": ">=0.7.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns sources.db (better-sqlite3, single writer); a second run of a source already in flight is refused in memory"++ "none": "no claims: one process owns the ov_sources PostgreSQL database; writes are transactions there; a second run of a source already in flight is refused in memory"}},"notes": "Source registry and ingestion workers (RSS/Atom, sitemaps, JSON-LD, mapped official APIs, manual). Every item carries provenance; every fetch is a recorded run with an explicit state; failures never create or modify items."@@@ -153,7 +153,7 @@"range": ">=0.11.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns tips.db (better-sqlite3, single writer); an effect moves with a compare-and-set on its state"++ "none": "no claims: one process owns the ov_tips PostgreSQL database; an effect moves with a compare-and-set on its state in one transaction"}},"notes": "Creator support (roadmap Wave 9): tip interactions whose payment state mirrors OpenVibe.Billing (keyed by Billing transaction id) and whose delivery state is Tips' own; goals derived from settled interactions; paid messages, TTS and media requests created on settlement; scoped revocable overlay tokens with SSE overlays; simulation mode. Tips never moves money (ADR-012). Alpha: deployed internally (loopback only), not launched publicly: openvibe.tips serves the OpenVibe.Sites placeholder until the launch rule in README.md holds."@@@ -61,7 +61,7 @@"timers, pollers and job workers stopped: the gateway's catalog, services and satellite pollers and search indexer; the retention timers and job workers of img, audio and docs (open job event streams end); yt's download cleanup","stops taking connections; idle keep-alive connections closed; requests in flight answered with Connection: close and allowed to finish (4 s at most, then cut); open event streams closed (EventSource reconnects)","recent-tool usage flushed to Network (1 s at most)",-- "analytics flushed and closed; jobs store and worker pools closed (running jobs stay running in jobs.db for the next boot); guard closed; the gateway's cutoff store closed",++ "analytics flushed and closed; jobs store and worker pools closed (running jobs stay running in the ov_tools PostgreSQL database for the next boot); guard closed; the gateway's cutoff store closed","exit 0"],"note": "every Tools process (the gateway, openvibe-tools.service, and the seven satellites) stops through apps/_shared/graceful.js; a stop that passes 5 s exits 1. The units set no TimeoutStopSec (systemd's 90 s default applies)"@@@ -70,7 +70,7 @@"resumes": [{"kind": "jobs",-- "what": "jobs left running in img, audio and docs jobs.db are re-queued while attempts remain (onRestart requeue), else failed as retryable"++ "what": "jobs left running in the ov_tools PostgreSQL database for img, audio and docs are re-queued while attempts remain (onRestart requeue), else failed as retryable"},{"kind": "outbox",@@@ -96,8 +96,8 @@"range": ">=0.7.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns each app's jobs.db (better-sqlite3, single writer); a job is taken with a compare-and-set (queued \u2192 running)"++ "none": "no claims: each app's process uses the ov_tools PostgreSQL database; a job is taken with a compare-and-set (queued \u2192 running) in one transaction"}},-- "notes": "Public at openvibe.tools: 169 tools in 9 families on the gateway (port 4001) and its satellites, catalogue at GET /api/catalog.json (re-served by Network). Asynchronous jobs (Wave 11) run on the img, audio and docs satellites only (POST /api/v1/jobs, GET/DELETE /api/v1/jobs/:id, POST /api/v1/jobs/:id/retry, PUT|DELETE /api/v1/jobs/:id/references/:ref, SSE events, result files); the gateway has no /api/v1/jobs yet. Job results are stored as private Media objects (TOOLS_JOB_RESULTS=media: Tools holds media.object.upload and media.object.read, namespace tools) and job lifecycle events tools.job.created|started|succeeded|failed are published to OpenVibe.Events through an outbox in each satellite's jobs.db (EVENTS_URL set; events.event.publish). The tool registry (ADR-027, tools.tool.read) is served: GET /api/v1/tools[/:id[/schema]] on the gateway, for all 169 tools, and on the img, audio, docs, text, yt, maps and food satellites for their own. Planned (ADR-027): the uniform run API POST /api/v1/tools/:id/run (tools.tool.run; network probes need tools.net.probe), a jobs facade on the gateway, tiered quotas and a pseudonymous abuse log; the legacy /api/process, /api/net/* and /api/dev/* routes keep working with Deprecation and Sunset (2026-12-31) headers. GET /api/ready is truthful on the gateway (it checks every satellite) and on each satellite."++ "notes": "Public at openvibe.tools: 169 tools in 9 families on the gateway (port 4001) and its satellites, catalogue at GET /api/catalog.json (re-served by Network). Asynchronous jobs (Wave 11) run on the img, audio and docs satellites only (POST /api/v1/jobs, GET/DELETE /api/v1/jobs/:id, POST /api/v1/jobs/:id/retry, PUT|DELETE /api/v1/jobs/:id/references/:ref, SSE events, result files); the gateway has no /api/v1/jobs yet. Job results are stored as private Media objects (TOOLS_JOB_RESULTS=media: Tools holds media.object.upload and media.object.read, namespace tools) and job lifecycle events tools.job.created|started|succeeded|failed are published to OpenVibe.Events through an outbox in the ov_tools PostgreSQL database (EVENTS_URL set; events.event.publish). The tool registry (ADR-027, tools.tool.read) is served: GET /api/v1/tools[/:id[/schema]] on the gateway, for all 169 tools, and on the img, audio, docs, text, yt, maps and food satellites for their own. Planned (ADR-027): the uniform run API POST /api/v1/tools/:id/run (tools.tool.run; network probes need tools.net.probe), a jobs facade on the gateway, tiered quotas and a pseudonymous abuse log; the legacy /api/process, /api/net/* and /api/dev/* routes keep working with Deprecation and Sunset (2026-12-31) headers. GET /api/ready is truthful on the gateway (it checks every satellite) and on each satellite."}@@@ -146,8 +146,8 @@"range": ">=0.19.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns trade.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_trade PostgreSQL database; writes are transactions there"}},-- "notes": "Port 4860. Informational only (ADR-025): no custody, order execution, escrow, listings between users or personalised advice. Owns trade_instruments, trade_instrument_aliases, trade_watchlists, trade_watchlist_items, trade_market_observations, trade_source_documents, trade_alert_rules, trade_alert_deliveries, trade_context_revisions in its own SQLite. Reads OpenVibe.Sources (sources.item.read, sources.source.read, category trade) by cursor and wakes on signed sources.* webhook deliveries; consumes OpenVibe.AI trade.summarize_market_context output as reviewed drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads trade.index_document.* from Events."++ "notes": "Port 4860. Informational only (ADR-025): no custody, order execution, escrow, listings between users or personalised advice. Owns trade_instruments, trade_instrument_aliases, trade_watchlists, trade_watchlist_items, trade_market_observations, trade_source_documents, trade_alert_rules, trade_alert_deliveries, trade_context_revisions in its own PostgreSQL database (ov_trade). Reads OpenVibe.Sources (sources.item.read, sources.source.read, category trade) by cursor and wakes on signed sources.* webhook deliveries; consumes OpenVibe.AI trade.summarize_market_context output as reviewed drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads trade.index_document.* from Events."}@@@ -138,7 +138,7 @@"range": ">=0.14.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns vip.db (better-sqlite3, single writer)"++ "none": "no claims: one process owns the ov_vip PostgreSQL database; writes are transactions there"}},"notes": "Memberships (ADR-012): plans, immutable versioned plan terms, perks, product bindings, member preferences and gated-resource policy. OpenVibe.Billing holds subscriptions, charges, renewals, refunds and the canonical entitlements; VIP keeps a short-lived projection of them (valid_until, authoritative fallback, 'unknown' never authorizes). Alpha: deployed internally (loopback only), not launched publicly: openvibe.vip serves the OpenVibe.Sites placeholder until the launch rule holds."
@@ -28,7 +28,7 @@ service id); **Runtime** is `STATUS.json.runtime`; **Database** is inferred from
@@ -28,7 +28,7 @@ service id); **Runtime** is `STATUS.json.runtime`; **Database** is inferred from
| OpenVibe.Extensions | — | — | node >=22.0.0 | — | — | — | not deployed | — | W18 |
| OpenVibe.Extensions | — | — | node >=22.0.0 | — | — | — | not deployed | — | W18 |
| OpenVibe.Games | Games | games.* | node 22 | PostgreSQL | openvibe.games, play.openvibe.games | contracts v0.78.0, sdk v0.23.1, shared v2.6.0 | deployed | live | — |
| OpenVibe.Games | Games | games.* | node 22 | PostgreSQL | openvibe.games, play.openvibe.games | contracts v0.78.0, sdk v0.23.1, shared v2.6.0 | deployed | live | — |
| OpenVibe.Host | Host | host.* | node 22 | PostgreSQL | openvibe.host | contracts v0.83.0, sdk v0.26.0, shared v2.10.1 | loopback only, not launched | live | W21 Stage A + Stage B |
| OpenVibe.Host | Host | host.* | node 22 | PostgreSQL | openvibe.host | contracts v0.83.0, sdk v0.26.0, shared v2.10.1 | loopback only, not launched | live | W21 Stage A + Stage B |
-| OpenVibe.Live | Live | live.* | node 22 | SQLite | openvibe.live, ingest.openvibe.live | contracts v0.83.0, sdk v0.26.0, shared v2.5.0 | deployed | live | — |
+| OpenVibe.Live | Live | live.* | node 22 | PostgreSQL (ov_live) | openvibe.live, ingest.openvibe.live | contracts v0.83.0, sdk v0.26.0, shared v2.5.0 | deployed | live | — |
| OpenVibe.Media | Media | media.* | node 22 | PostgreSQL | openvibe.media | contracts v0.79.0, sdk v0.32.0, shared v2.10.0 | deployed | live | — |
| OpenVibe.Media | Media | media.* | node 22 | PostgreSQL | openvibe.media | contracts v0.79.0, sdk v0.32.0, shared v2.10.0 | deployed | live | — |
| OpenVibe.Network | Network | identity.*, network.*, theme.*, notification.* | node 22 | PostgreSQL | openvibe.network, auth.openvibe.network, api.openvibe.network, admin.openvibe.network, my.openvibe.network, themes.openvibe.network | contracts v0.106.0, sdk v0.28.0, shared v2.10.1 | deployed | live | — |
| OpenVibe.Network | Network | identity.*, network.*, theme.*, notification.* | node 22 | PostgreSQL | openvibe.network, auth.openvibe.network, api.openvibe.network, admin.openvibe.network, my.openvibe.network, themes.openvibe.network | contracts v0.106.0, sdk v0.28.0, shared v2.10.1 | deployed | live | — |
| OpenVibe.News | News | news.* | node 22 | PostgreSQL | openvibe.news | contracts v0.97.0, sdk v0.26.0, shared v2.9.0, publishing v1.3.0 | deployed | internal | W17 |
| OpenVibe.News | News | news.* | node 22 | PostgreSQL | openvibe.news | contracts v0.97.0, sdk v0.26.0, shared v2.9.0, publishing v1.3.0 | deployed | internal | W17 |
@@ -6,7 +6,7 @@
@@ -6,7 +6,7 @@
"stage": "stable",
"stage": "stable",
"version": "1.0.0",
"version": "1.0.0",
"runtime": "node 22",
"runtime": "node 22",
- "database": "SQLite",
+ "database": "PostgreSQL (ov_live)",
"migrations": 1,
"migrations": 1,
"authority": [
"authority": [
"live.*"
"live.*"
@@ -93,7 +93,7 @@
@@ -93,7 +93,7 @@
"claims": [
"claims": [
{
{
"what": "a stored provider event (provider_events row) while it is applied",
"what": "a stored provider event (provider_events row) while it is applied",
- "holder": "the connection that takes the SQLite write lock (IMMEDIATE transaction)",
+ "holder": "the connection that locks the provider_events row in an ov_billing PostgreSQL transaction",
"expires": "at commit or rollback of that transaction",
"expires": "at commit or rollback of that transaction",
"fencing": "processed_at is re-read inside the transaction, so a second process or connection that waited applies nothing; ledger postings carry idempotency keys"
"fencing": "processed_at is re-read inside the transaction, so a second process or connection that waited applies nothing; ledger postings carry idempotency keys"
}
}
@@ -114,5 +114,5 @@
@@ -114,5 +114,5 @@
]
]
}
}
},
},
- "notes": "Port 4810. Owns blogs, blog_memberships, blog_posts, blog_post_revisions, blog_series, blog_taxonomy, blog_post_terms, blog_schedules, blog_redirects, blog_feed_settings in its own SQLite (openvibe-publishing packages, prefix blog). Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Community (community.comment.write, community.comment.moderate), OpenVibe.Media (media.object.read, namespace blog) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads blog.index_document.* from Events."
+ "notes": "Port 4810. Owns blogs, blog_memberships, blog_posts, blog_post_revisions, blog_series, blog_taxonomy, blog_post_terms, blog_schedules, blog_redirects, blog_feed_settings in its own PostgreSQL database ov_blog (openvibe-publishing packages, prefix blog). Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Community (community.comment.write, community.comment.moderate), OpenVibe.Media (media.object.read, namespace blog) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads blog.index_document.* from Events."
}
}
@@ -67,7 +67,7 @@
@@ -67,7 +67,7 @@
"range": ">=0.26.0 <1.0.0"
"range": ">=0.26.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns codes.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_codes PostgreSQL database; writes are transactions there"
}
}
},
},
"notes": "Port 4900, unit openvibe-codes.service. The open coding-agent harness (owner 2026-10-08): the harness catalog and router (GET /api/v1/harnesses, POST /api/v1/harnesses/route), the way to improve OpenVibe (contributing, code of conduct, the contributor ladder) and permanent redirects from the former developer-portal paths to openvibe.services, where the portal moved (manifests, releases, trust, playgrounds, docs, OAuth and webhook tools)."
"notes": "Port 4900, unit openvibe-codes.service. The open coding-agent harness (owner 2026-10-08): the harness catalog and router (GET /api/v1/harnesses, POST /api/v1/harnesses/route), the way to improve OpenVibe (contributing, code of conduct, the contributor ladder) and permanent redirects from the former developer-portal paths to openvibe.services, where the portal moved (manifests, releases, trust, playgrounds, docs, OAuth and webhook tools)."
@@ -73,7 +73,7 @@
@@ -73,7 +73,7 @@
"Pulse subscription retries, the community.profile scan and the search-document scans stopped",
"Pulse subscription retries, the community.profile scan and the search-document scans stopped",
"stops taking connections; idle keep-alive connections closed (kept 65 s otherwise); requests in flight answered with Connection: close and allowed to finish (4 s at most, then cut)",
"stops taking connections; idle keep-alive connections closed (kept 65 s otherwise); requests in flight answered with Connection: close and allowed to finish (4 s at most, then cut)",
"the profile scan in progress (it stops between people), the Discord relay's drain and the events outbox's send awaited; unsent rows stay in their tables",
"the profile scan in progress (it stops between people), the Discord relay's drain and the events outbox's send awaited; unsent rows stay in their tables",
- "community.db closed, exit 0"
+ "the ov_community PostgreSQL database closed, exit 0"
],
],
"note": "server/graceful.js; a stop that passes 5 s exits 1. Only the in-memory rate-limit sweeps end with the process. The unit sets no TimeoutStopSec (systemd's 90 s default applies)"
"note": "server/graceful.js; a stop that passes 5 s exits 1. Only the in-memory rate-limit sweeps end with the process. The unit sets no TimeoutStopSec (systemd's 90 s default applies)"
},
},
@@ -107,7 +107,7 @@
@@ -107,7 +107,7 @@
"range": ">=0.5.0 <1.0.0"
"range": ">=0.5.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns community.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_community PostgreSQL database; writes are transactions there"
}
}
},
},
"notes": "Community serves the forum (spaces, threads, posts, votes, categories, moderation and the Discord relay), pastes, comments, Pulse and submissions. The forum returned to Community from OpenVibe.Space (owner decision 2026-10-08): the community.* forum capabilities, contracts and events are active again, the community.space.*/thread.read/post.create routes and the /s pages and feeds serve production, and Space no longer serves a forum."
"notes": "Community serves the forum (spaces, threads, posts, votes, categories, moderation and the Discord relay), pastes, comments, Pulse and submissions. The forum returned to Community from OpenVibe.Space (owner decision 2026-10-08): the community.* forum capabilities, contracts and events are active again, the community.space.*/thread.read/post.create routes and the /s pages and feeds serve production, and Space no longer serves a forum."
@@ -127,8 +127,8 @@
@@ -127,8 +127,8 @@
"range": ">=0.19.0 <1.0.0"
"range": ">=0.19.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns coupons.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_coupons PostgreSQL database; writes are transactions there"
}
}
},
},
- "notes": "Port 4850. Owns coupon_merchants, coupon_merchant_domains, coupons, coupon_sources, coupon_restrictions, coupon_validation_reports, coupon_status_history, coupon_application_hints, coupon_watches in its own SQLite, plus extension_installs (cpx_ browser-helper tokens, scopes coupons.lookup and coupons.report, hashed, revocable). Consumes OpenVibe.Network (SSO, JWKS) and OpenVibe.Sources (sources.item.read, category coupons); publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads coupons.index_document.* from Events. The browser helper lives in OpenVibers/OpenVibe.Extensions (ADR-023)."
+ "notes": "Port 4850. Owns coupon_merchants, coupon_merchant_domains, coupons, coupon_sources, coupon_restrictions, coupon_validation_reports, coupon_status_history, coupon_application_hints, coupon_watches in its own PostgreSQL database (ov_coupons), plus extension_installs (cpx_ browser-helper tokens, scopes coupons.lookup and coupons.report, hashed, revocable). Consumes OpenVibe.Network (SSO, JWKS) and OpenVibe.Sources (sources.item.read, category coupons); publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads coupons.index_document.* from Events. The browser helper lives in OpenVibers/OpenVibe.Extensions (ADR-023)."
}
}
@@ -142,8 +142,8 @@
@@ -142,8 +142,8 @@
"range": ">=0.19.0 <1.0.0"
"range": ">=0.19.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns deals.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_deals PostgreSQL database; writes are transactions there"
}
}
},
},
- "notes": "Port 4840. Owns deal_products, deal_product_aliases, deal_offers, deal_offer_sources, deal_votes, deal_hotness_snapshots, deal_watches, deal_price_observations, deal_flags (+ deal_stores) in its own SQLite. Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Sources (sources.item.read; sources.item.* events only wake the pull), OpenVibe.Community (community.comment.write, community.comment.moderate) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads deals.index_document.* from Events; OpenVibe.Network turns deals.watch.matched into notifications (server/notifications/events-consumer.js)."
+ "notes": "Port 4840. Owns deal_products, deal_product_aliases, deal_offers, deal_offer_sources, deal_votes, deal_hotness_snapshots, deal_watches, deal_price_observations, deal_flags (+ deal_stores) in its own PostgreSQL database (ov_deals). Consumes OpenVibe.Network (SSO, identity.subject.resolve), OpenVibe.Sources (sources.item.read; sources.item.* events only wake the pull), OpenVibe.Community (community.comment.write, community.comment.moderate) and publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads deals.index_document.* from Events; OpenVibe.Network turns deals.watch.matched into notifications (server/notifications/events-consumer.js)."
}
}
@@ -76,7 +76,7 @@
@@ -76,7 +76,7 @@
"range": ">=0.5.1 <1.0.0"
"range": ">=0.5.1 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns events.db (better-sqlite3, single writer); one delivery per subscription is in flight at a time, tracked in memory"
+ "none": "no claims: one process owns the ov_events PostgreSQL database; writes are transactions there; one delivery per subscription is in flight at a time, tracked in memory"
}
}
},
},
"notes": "Durable events, subscriptions, signed delivery with retry, dead letters and replay; SSE realtime gateway at /realtime/stream (ADR-005); browsers on any OpenVibe site authenticate a stream with a two-minute, single-use realtime ticket from Network (?ticket=, identity.realtime-ticket-claims@1; ADR-005 amendment 2).",
"notes": "Durable events, subscriptions, signed delivery with retry, dead letters and replay; SSE realtime gateway at /realtime/stream (ADR-005); browsers on any OpenVibe site authenticate a stream with a two-minute, single-use realtime ticket from Network (?ticket=, identity.realtime-ticket-claims@1; ADR-005 amendment 2).",
@@ -58,7 +58,7 @@
@@ -58,7 +58,7 @@
"lifecycle": {
"lifecycle": {
"liveness": {
"liveness": {
"endpoint": "/healthz",
"endpoint": "/healthz",
- "means": "the process is up and answers HTTP; liveness only (world.db and the simulation tick are what /api/ready checks)"
+ "means": "the process is up and answers HTTP; liveness only (the ov_games PostgreSQL database and the simulation tick are what /api/ready checks)"
},
},
"shutdown": {
"shutdown": {
"signal": "SIGTERM",
"signal": "SIGTERM",
@@ -71,7 +71,7 @@
@@ -71,7 +71,7 @@
"world saved: every session marked dirty and flushed (game.shutdown)",
"world saved: every session marked dirty and flushed (game.shutdown)",
"requests in flight finish (5 s at most, then cut)",
"requests in flight finish (5 s at most, then cut)",
"the media mirror's pass in progress (2 s at most), the progress-summary writes (1 s) and the outbox's last send (2 s) awaited; unsent rows stay in the outbox",
"the media mirror's pass in progress (2 s at most), the progress-summary writes (1 s) and the outbox's last send (2 s) awaited; unsent rows stay in the outbox",
- "world.db closed, physics disposed, exit 0"
+ "the ov_games PostgreSQL database closed, physics disposed, exit 0"
],
],
"note": "clients reconnect on their own after 1012; the whole stop is bounded at 10 s (exit 1 past it), inside the unit's TimeoutStopSec=30"
"note": "clients reconnect on their own after 1012; the whole stop is bounded at 10 s (exit 1 past it), inside the unit's TimeoutStopSec=30"
},
},
@@ -79,7 +79,7 @@
@@ -79,7 +79,7 @@
"resumes": [
"resumes": [
{
{
"kind": "state",
"kind": "state",
- "what": "the world is restored from world.db before the network opens (schema migrated forward first)"
+ "what": "the world is restored from the ov_games PostgreSQL database before the network opens (schema migrated forward first)"
},
},
{
{
"kind": "outbox",
"kind": "outbox",
@@ -100,16 +100,16 @@
@@ -100,16 +100,16 @@
"automatic: ovhost deploy games (strategy pnpm-build) restores the previous sha, rebuilds and restarts when the ready URL does not answer 2xx after the restart",
"automatic: ovhost deploy games (strategy pnpm-build) restores the previous sha, rebuilds and restarts when the ready URL does not answer 2xx after the restart",
"manual: sudo ovhost rollback games --to <sha> (rebuilds the workspace)"
"manual: sudo ovhost rollback games --to <sha> (rebuilds the workspace)"
],
],
- "window": "as long as world.db has not been migrated past the older build's SCHEMA_VERSION",
+ "window": "as long as the ov_games PostgreSQL database has not been migrated past the older build's SCHEMA_VERSION",
"blockers": [
"blockers": [
- "a build refuses a world.db whose meta.schema_version is newer than its own (SCHEMA_VERSION 13 today, forward-only migrations): going back past a schema bump fails at boot"
+ "a build refuses the ov_games PostgreSQL database whose meta.schema_version is newer than its own (SCHEMA_VERSION 13 today, forward-only migrations): going back past a schema bump fails at boot"
]
]
},
},
"contracts": {
"contracts": {
"range": ">=0.8.0 <1.0.0"
"range": ">=0.8.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns world.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_games PostgreSQL database; writes are transactions there"
}
}
},
},
"notes": "Scraplandia (browser runtime). Players are keyed by canonical Network subjects (ADR-0006 in the repo). Calls Events (events.event.publish), Media (media.object.upload, namespace games: map-editor assets) and Network identity (identity.subject.resolve, batch legacy adoption) with the games client-credentials principal. Mods: games-content@1 declarative packs only; executable mods wait for OpenVibe.Host Stage C. No achievement system exists, so there are no games.achievement.* events."
"notes": "Scraplandia (browser runtime). Players are keyed by canonical Network subjects (ADR-0006 in the repo). Calls Events (events.event.publish), Media (media.object.upload, namespace games: map-editor assets) and Network identity (identity.subject.resolve, batch legacy adoption) with the games client-credentials principal. Mods: games-content@1 declarative packs only; executable mods wait for OpenVibe.Host Stage C. No achievement system exists, so there are no games.achievement.* events."
@@ -124,7 +124,7 @@
@@ -124,7 +124,7 @@
"maintenance timers (notifications, email queue, retired-module sweep, session cleanup), the analytics prune, the ecosystem, deploy-drift and library-tag pollers, the frame refreshes and the profile-event and grant-expiry timers stopped",
"maintenance timers (notifications, email queue, retired-module sweep, session cleanup), the analytics prune, the ecosystem, deploy-drift and library-tag pollers, the frame refreshes and the profile-event and grant-expiry timers stopped",
"stops taking connections; idle keep-alive connections closed; requests in flight answered with Connection: close and allowed to finish (8 s at most, then cut)",
"stops taking connections; idle keep-alive connections closed; requests in flight answered with Connection: close and allowed to finish (8 s at most, then cut)",
"the developer, profile and grant event relay's send in progress awaited (unsent rows stay in the outbox)",
"the developer, profile and grant event relay's send in progress awaited (unsent rows stay in the outbox)",
- "analytics flushed and closed; network.db closed; exit 0"
+ "analytics flushed and closed; the ov_network PostgreSQL database closed; exit 0"
],
],
"note": "openvibe-sdk/service; a stop that passes 10 s exits 1. Only the Discord link's in-memory state sweep ends with the process; the email queue and the outboxes resume from the database on the next start"
"note": "openvibe-sdk/service; a stop that passes 10 s exits 1. Only the Discord link's in-memory state sweep ends with the process; the email queue and the outboxes resume from the database on the next start"
},
},
@@ -163,7 +163,7 @@
@@ -163,7 +163,7 @@
"range": ">=0.2.0 <1.0.0"
"range": ">=0.2.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns network.db (better-sqlite3, single writer); a stream-live announcement is claimed per streamer with a cooldown and a daily cap in the same database"
+ "none": "no claims: one process owns the ov_network PostgreSQL database; Network's live.stream.started consumer claims a stream-live announcement per streamer with a cooldown and a daily cap in one transaction there"
}
}
}
}
}
}
@@ -140,8 +140,8 @@
@@ -140,8 +140,8 @@
"range": ">=0.19.0 <1.0.0"
"range": ">=0.19.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns news.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_news PostgreSQL database; writes are transactions there"
}
}
},
},
- "notes": "Port 4820. Owns news_topics, news_source_items, news_story_clusters, news_stories, news_story_revisions, news_story_sources, news_perspectives, news_timeline_entries, news_editorial_flags in its own SQLite (openvibe-publishing packages, prefixes news_story and news). Consumes OpenVibe.Sources (sources.item.read, optionally sources.source.read) through an Events subscription (sources.item.*, sources.fetch.failed; events.subscription.manage) and a cursor pull; OpenVibe.Network (SSO, identity.subject.resolve); optionally OpenVibe.AI (ai.run.create, namespace news) for news.summarize_story and news.compare_perspectives drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads news.index_document.* from Events."
+ "notes": "Port 4820. Owns news_topics, news_source_items, news_story_clusters, news_stories, news_story_revisions, news_story_sources, news_perspectives, news_timeline_entries, news_editorial_flags in its own PostgreSQL database ov_news (openvibe-publishing packages, prefixes news_story and news). Consumes OpenVibe.Sources (sources.item.read, optionally sources.source.read) through an Events subscription (sources.item.*, sources.fetch.failed; events.subscription.manage) and a cursor pull; OpenVibe.Network (SSO, identity.subject.resolve); optionally OpenVibe.AI (ai.run.create, namespace news) for news.summarize_story and news.compare_perspectives drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads news.index_document.* from Events."
}
}
@@ -138,7 +138,7 @@
@@ -138,7 +138,7 @@
"range": ">=0.19.0 <1.0.0"
"range": ">=0.19.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns reviews.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_reviews PostgreSQL database; writes are transactions there"
}
}
},
},
"notes": "Entities with aliases and typed links; resolution of OpenVibe.Sources review items by deterministic rules (source binding, URL, GTIN/SKU/MPN) with editor confirmation for name-only and conflicting matches; merges that rewrite nothing and splits that restore attribution exactly, both audited; typed signals with provenance (source item, item revision, retrieval time, licence note) and trust metadata; aggregates computed only from signals present (method reviews-aggregate@1, inputs and exclusions exposed, absent without qualifying signals, a new revision on every change); editor-written or AI-drafted-and-approved summaries whose points cite signals and never carry a rating; source removal withdraws signals, flags citing summaries and prepares a pending revision; corrections queue; Community discussion referenced, not copied. Server-rendered pages useful without JavaScript; AggregateRating/Product/Review JSON-LD only when signals back it; sitemaps, feeds and Search index events from the openvibe-publishing v0.2.0 gate. Deployed internally (loopback only), not launched publicly: openvibe.reviews serves the OpenVibe.Sites placeholder until the launch rule holds."
"notes": "Entities with aliases and typed links; resolution of OpenVibe.Sources review items by deterministic rules (source binding, URL, GTIN/SKU/MPN) with editor confirmation for name-only and conflicting matches; merges that rewrite nothing and splits that restore attribution exactly, both audited; typed signals with provenance (source item, item revision, retrieval time, licence note) and trust metadata; aggregates computed only from signals present (method reviews-aggregate@1, inputs and exclusions exposed, absent without qualifying signals, a new revision on every change); editor-written or AI-drafted-and-approved summaries whose points cite signals and never carry a rating; source removal withdraws signals, flags citing summaries and prepares a pending revision; corrections queue; Community discussion referenced, not copied. Server-rendered pages useful without JavaScript; AggregateRating/Product/Review JSON-LD only when signals back it; sitemaps, feeds and Search index events from the openvibe-publishing v0.2.0 gate. Deployed internally (loopback only), not launched publicly: openvibe.reviews serves the OpenVibe.Sites placeholder until the launch rule holds."
@@ -80,10 +80,10 @@
@@ -80,10 +80,10 @@
"range": ">=0.7.0 <1.0.0"
"range": ">=0.7.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns search.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_search PostgreSQL database; writes are transactions there"
}
}
},
},
- "notes": "Canonical index document (search.index-document@1), event-fed and direct indexing with revision ordering and tombstones, permission-aware query over SQLite FTS5 (docs/adr-engine.md). Anonymous queries need no token.",
+ "notes": "Canonical index document (search.index-document@1), event-fed and direct indexing with revision ordering and tombstones, permission-aware query over PostgreSQL full-text search in ov_search (docs/adr-engine.md). Anonymous queries need no token.",
"site": {
"site": {
"name": "Search",
"name": "Search",
"icon": "search",
"icon": "search",
@@ -76,7 +76,7 @@
@@ -76,7 +76,7 @@
"range": ">=0.7.0 <1.0.0"
"range": ">=0.7.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns sources.db (better-sqlite3, single writer); a second run of a source already in flight is refused in memory"
+ "none": "no claims: one process owns the ov_sources PostgreSQL database; writes are transactions there; a second run of a source already in flight is refused in memory"
}
}
},
},
"notes": "Source registry and ingestion workers (RSS/Atom, sitemaps, JSON-LD, mapped official APIs, manual). Every item carries provenance; every fetch is a recorded run with an explicit state; failures never create or modify items."
"notes": "Source registry and ingestion workers (RSS/Atom, sitemaps, JSON-LD, mapped official APIs, manual). Every item carries provenance; every fetch is a recorded run with an explicit state; failures never create or modify items."
@@ -153,7 +153,7 @@
@@ -153,7 +153,7 @@
"range": ">=0.11.0 <1.0.0"
"range": ">=0.11.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns tips.db (better-sqlite3, single writer); an effect moves with a compare-and-set on its state"
+ "none": "no claims: one process owns the ov_tips PostgreSQL database; an effect moves with a compare-and-set on its state in one transaction"
}
}
},
},
"notes": "Creator support (roadmap Wave 9): tip interactions whose payment state mirrors OpenVibe.Billing (keyed by Billing transaction id) and whose delivery state is Tips' own; goals derived from settled interactions; paid messages, TTS and media requests created on settlement; scoped revocable overlay tokens with SSE overlays; simulation mode. Tips never moves money (ADR-012). Alpha: deployed internally (loopback only), not launched publicly: openvibe.tips serves the OpenVibe.Sites placeholder until the launch rule in README.md holds."
"notes": "Creator support (roadmap Wave 9): tip interactions whose payment state mirrors OpenVibe.Billing (keyed by Billing transaction id) and whose delivery state is Tips' own; goals derived from settled interactions; paid messages, TTS and media requests created on settlement; scoped revocable overlay tokens with SSE overlays; simulation mode. Tips never moves money (ADR-012). Alpha: deployed internally (loopback only), not launched publicly: openvibe.tips serves the OpenVibe.Sites placeholder until the launch rule in README.md holds."
@@ -61,7 +61,7 @@
@@ -61,7 +61,7 @@
"timers, pollers and job workers stopped: the gateway's catalog, services and satellite pollers and search indexer; the retention timers and job workers of img, audio and docs (open job event streams end); yt's download cleanup",
"timers, pollers and job workers stopped: the gateway's catalog, services and satellite pollers and search indexer; the retention timers and job workers of img, audio and docs (open job event streams end); yt's download cleanup",
"stops taking connections; idle keep-alive connections closed; requests in flight answered with Connection: close and allowed to finish (4 s at most, then cut); open event streams closed (EventSource reconnects)",
"stops taking connections; idle keep-alive connections closed; requests in flight answered with Connection: close and allowed to finish (4 s at most, then cut); open event streams closed (EventSource reconnects)",
"recent-tool usage flushed to Network (1 s at most)",
"recent-tool usage flushed to Network (1 s at most)",
- "analytics flushed and closed; jobs store and worker pools closed (running jobs stay running in jobs.db for the next boot); guard closed; the gateway's cutoff store closed",
+ "analytics flushed and closed; jobs store and worker pools closed (running jobs stay running in the ov_tools PostgreSQL database for the next boot); guard closed; the gateway's cutoff store closed",
"exit 0"
"exit 0"
],
],
"note": "every Tools process (the gateway, openvibe-tools.service, and the seven satellites) stops through apps/_shared/graceful.js; a stop that passes 5 s exits 1. The units set no TimeoutStopSec (systemd's 90 s default applies)"
"note": "every Tools process (the gateway, openvibe-tools.service, and the seven satellites) stops through apps/_shared/graceful.js; a stop that passes 5 s exits 1. The units set no TimeoutStopSec (systemd's 90 s default applies)"
@@ -70,7 +70,7 @@
@@ -70,7 +70,7 @@
"resumes": [
"resumes": [
{
{
"kind": "jobs",
"kind": "jobs",
- "what": "jobs left running in img, audio and docs jobs.db are re-queued while attempts remain (onRestart requeue), else failed as retryable"
+ "what": "jobs left running in the ov_tools PostgreSQL database for img, audio and docs are re-queued while attempts remain (onRestart requeue), else failed as retryable"
},
},
{
{
"kind": "outbox",
"kind": "outbox",
@@ -96,8 +96,8 @@
@@ -96,8 +96,8 @@
"range": ">=0.7.0 <1.0.0"
"range": ">=0.7.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns each app's jobs.db (better-sqlite3, single writer); a job is taken with a compare-and-set (queued \u2192 running)"
+ "none": "no claims: each app's process uses the ov_tools PostgreSQL database; a job is taken with a compare-and-set (queued \u2192 running) in one transaction"
}
}
},
},
- "notes": "Public at openvibe.tools: 169 tools in 9 families on the gateway (port 4001) and its satellites, catalogue at GET /api/catalog.json (re-served by Network). Asynchronous jobs (Wave 11) run on the img, audio and docs satellites only (POST /api/v1/jobs, GET/DELETE /api/v1/jobs/:id, POST /api/v1/jobs/:id/retry, PUT|DELETE /api/v1/jobs/:id/references/:ref, SSE events, result files); the gateway has no /api/v1/jobs yet. Job results are stored as private Media objects (TOOLS_JOB_RESULTS=media: Tools holds media.object.upload and media.object.read, namespace tools) and job lifecycle events tools.job.created|started|succeeded|failed are published to OpenVibe.Events through an outbox in each satellite's jobs.db (EVENTS_URL set; events.event.publish). The tool registry (ADR-027, tools.tool.read) is served: GET /api/v1/tools[/:id[/schema]] on the gateway, for all 169 tools, and on the img, audio, docs, text, yt, maps and food satellites for their own. Planned (ADR-027): the uniform run API POST /api/v1/tools/:id/run (tools.tool.run; network probes need tools.net.probe), a jobs facade on the gateway, tiered quotas and a pseudonymous abuse log; the legacy /api/process, /api/net/* and /api/dev/* routes keep working with Deprecation and Sunset (2026-12-31) headers. GET /api/ready is truthful on the gateway (it checks every satellite) and on each satellite."
+ "notes": "Public at openvibe.tools: 169 tools in 9 families on the gateway (port 4001) and its satellites, catalogue at GET /api/catalog.json (re-served by Network). Asynchronous jobs (Wave 11) run on the img, audio and docs satellites only (POST /api/v1/jobs, GET/DELETE /api/v1/jobs/:id, POST /api/v1/jobs/:id/retry, PUT|DELETE /api/v1/jobs/:id/references/:ref, SSE events, result files); the gateway has no /api/v1/jobs yet. Job results are stored as private Media objects (TOOLS_JOB_RESULTS=media: Tools holds media.object.upload and media.object.read, namespace tools) and job lifecycle events tools.job.created|started|succeeded|failed are published to OpenVibe.Events through an outbox in the ov_tools PostgreSQL database (EVENTS_URL set; events.event.publish). The tool registry (ADR-027, tools.tool.read) is served: GET /api/v1/tools[/:id[/schema]] on the gateway, for all 169 tools, and on the img, audio, docs, text, yt, maps and food satellites for their own. Planned (ADR-027): the uniform run API POST /api/v1/tools/:id/run (tools.tool.run; network probes need tools.net.probe), a jobs facade on the gateway, tiered quotas and a pseudonymous abuse log; the legacy /api/process, /api/net/* and /api/dev/* routes keep working with Deprecation and Sunset (2026-12-31) headers. GET /api/ready is truthful on the gateway (it checks every satellite) and on each satellite."
}
}
@@ -146,8 +146,8 @@
@@ -146,8 +146,8 @@
"range": ">=0.19.0 <1.0.0"
"range": ">=0.19.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns trade.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_trade PostgreSQL database; writes are transactions there"
}
}
},
},
- "notes": "Port 4860. Informational only (ADR-025): no custody, order execution, escrow, listings between users or personalised advice. Owns trade_instruments, trade_instrument_aliases, trade_watchlists, trade_watchlist_items, trade_market_observations, trade_source_documents, trade_alert_rules, trade_alert_deliveries, trade_context_revisions in its own SQLite. Reads OpenVibe.Sources (sources.item.read, sources.source.read, category trade) by cursor and wakes on signed sources.* webhook deliveries; consumes OpenVibe.AI trade.summarize_market_context output as reviewed drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads trade.index_document.* from Events."
+ "notes": "Port 4860. Informational only (ADR-025): no custody, order execution, escrow, listings between users or personalised advice. Owns trade_instruments, trade_instrument_aliases, trade_watchlists, trade_watchlist_items, trade_market_observations, trade_source_documents, trade_alert_rules, trade_alert_deliveries, trade_context_revisions in its own PostgreSQL database (ov_trade). Reads OpenVibe.Sources (sources.item.read, sources.source.read, category trade) by cursor and wakes on signed sources.* webhook deliveries; consumes OpenVibe.AI trade.summarize_market_context output as reviewed drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads trade.index_document.* from Events."
}
}
@@ -138,7 +138,7 @@
@@ -138,7 +138,7 @@
"range": ">=0.14.0 <1.0.0"
"range": ">=0.14.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns vip.db (better-sqlite3, single writer)"
+ "none": "no claims: one process owns the ov_vip PostgreSQL database; writes are transactions there"
}
}
},
},
"notes": "Memberships (ADR-012): plans, immutable versioned plan terms, perks, product bindings, member preferences and gated-resource policy. OpenVibe.Billing holds subscriptions, charges, renewals, refunds and the canonical entitlements; VIP keeps a short-lived projection of them (valid_until, authoritative fallback, 'unknown' never authorizes). Alpha: deployed internally (loopback only), not launched publicly: openvibe.vip serves the OpenVibe.Sites placeholder until the launch rule holds."
"notes": "Memberships (ADR-012): plans, immutable versioned plan terms, perks, product bindings, member preferences and gated-resource policy. OpenVibe.Billing holds subscriptions, charges, renewals, refunds and the canonical entitlements; VIP keeps a short-lived projection of them (valid_until, authoritative fallback, 'unknown' never authorizes). Alpha: deployed internally (loopback only), not launched publicly: openvibe.vip serves the OpenVibe.Sites placeholder until the launch rule holds."