openvibers/openvibe.trade Commits
README and STATUS.json are current (roadmap WS-U task 3): a Capabilities section lists the twelve capabilities Trade implements and the grants it uses at Events and Sources; Deploy says production deploys with sudo ovhost deploy trade (unit, port, env file, rollback) and keeps the first-install steps; Security points to SECURITY.md; Depends on names the current pins (contracts v0.49.0, publishing v0.4.0, shared v1.22.0, sdk v0.12.0). STATUS.json gains contracts, features, the current package list and updated 2026-09-28.
Changes
@@@ -194,12 +194,24 @@ webhook, as a wake-up for the cursor sync (the webhook is not durable truth; the3. The revision is an AI-generated **draft**: labelled, noindex, not shown to readers until a personon the editor list approves it at `/editor/i/:symbol`.++## Capabilities++++Implemented here (the service manifest's `capabilities`, audience `openvibe.trade`, one per route; the++route table is under [API](#api-apiv1-problemjson-errors)): `trade.instrument.resolve`,++`trade.instrument.manage`, `trade.observation.write`, `trade.context.read`, `trade.context.propose`,++`trade.watchlist.read`, `.create`, `.update`, `.delete`, and `trade.alert.read`, `.create`, `.delete`.++None of them moves, holds or orders anything (ADR-025; `test/route-inventory.test.js`).++++Called elsewhere, as the service principal `trade`: `events.event.publish` (Events) and++`sources.item.read` and `sources.source.read` (Sources). The list with audiences, and the grants other++services need to call Trade, is under [Grants the Network must hold](#grants-the-network-must-hold).++## Depends on--- **Packages** (pinned by release tarball): `openvibe-contracts` v0.33.0, `openvibe-publishing`-- v0.2.1 (revisions, authorship, seo, index-hooks, ssr), `openvibe-shared` v1.5.1 (chrome, app icon,-- footer, legal, release, metrics, ready), `openvibe-sdk` v0.5.0 (events outbox and inbox, webhook-- signatures v2, service tokens).++- **Packages** (pinned by release tarball): `openvibe-contracts` v0.49.0, `openvibe-publishing`++ v0.4.0 (revisions, authorship, seo, index-hooks, ssr), `openvibe-shared` v1.22.0 (chrome, app icon,++ footer, legal, release, metrics, ready), `openvibe-sdk` v0.12.0 (events outbox and inbox, webhook++ signatures v2, service tokens, per-actor limits).- **OpenVibe.Network:** SSO (OAuth client `trade`, redirect `https://openvibe.trade/auth/callback`),JWKS, client-credentials tokens.- **OpenVibe.Sources:** `sources.item.read` and `sources.source.read` (category `trade`).@@@ -262,6 +274,8 @@ registry, atomically. A placeholder never counts as an implemented service.## Security and threat review++Reporting a vulnerability: [SECURITY.md](SECURITY.md).++- **Scope (ADR-025):** nothing moves or holds value. The route-inventory test is in CI; context thatreads as advice is refused; the disclaimer is on every page.- **Identity:** only verified Network JWTs (offline RS256 against JWKS) and service tokens for@@@ -326,6 +340,15 @@ fnm exec --using=22.22.1 npm run dev # http://localhost:4860 (set OV_OAUTH## Deploy (for the lead)++Production deploys with `sudo ovhost deploy trade` on the host (strategy `git-checkout`: fetch,++fast-forward `/opt/openvibe.trade`, install on a lockfile change, restart, wait for `/api/ready`).++The unit is `openvibe-trade.service` on `127.0.0.1:4860`, the env file `/etc/openvibe/trade.env`.++Rollback: ovhost puts the previous sha back by itself when `/api/ready` does not answer 2xx after the++restart; afterwards `sudo ovhost rollback trade --to <sha>`. Nothing blocks a rollback: the schema++code only adds tables and columns.++++First install (done once; kept for a rebuild):++1. **Code and config:** code at `/opt/openvibe.trade`, `npm ci --omit=dev` on Node 22.Create `/etc/openvibe/trade.env` (0600) from `.env.example` with `OV_OAUTH_CLIENT_SECRET`,`TRADE_EDITORS`, `TRADE_FORM_SECRET`, `EVENTS_URL=http://127.0.0.1:4300`,@@@ -8,12 +8,8 @@"port": 4860,"domain": "openvibe.trade","scope": "informational only (ADR-025): no custody, no order execution, no escrow, no listings between users, no personalised advice",-- "packages": [-- "openvibe-contracts v0.33.0",-- "openvibe-publishing v0.2.1",-- "openvibe-shared v1.5.1",-- "openvibe-sdk v0.5.0"-- ],++ "contracts": "openvibe-contracts v0.49.0",++ "packages": ["openvibe-contracts v0.49.0", "openvibe-publishing v0.4.0", "openvibe-shared v1.22.0", "openvibe-sdk v0.12.0"],"capabilities": ["trade.instrument.resolve","trade.instrument.manage",@@@ -33,7 +29,21 @@"marketDataFeeds": "none configured: the only seeded trade source in OpenVibe.Sources (SEC EDGAR XBRL filings RSS) is disabled there, and it carries filings, not prices; no observation exists until a source states one","seed": "none (tests create their own instruments; production holds 0 instruments and 0 observations)","deployed": true,-- "deployment": "openvibe-ovh, unit openvibe-trade, 127.0.0.1:4860 loopback only (release 9a55644); /api/ready 200 with status degraded [freshness], which is honest: no feed is configured; Network OAuth client trade and its grants exist; no Events subscription; production database holds 0 instruments and 0 observations. Deployed internally, not launched: openvibe.trade still serves the OpenVibe.Sites placeholder until a person verifies the SEC XBRL terms and enables sec-xbrl-filings in Sources, a licensed market data feed exists, and editors add instruments",++ "deployment": "Deployed with `sudo ovhost deploy trade`: unit openvibe-trade, 127.0.0.1:4860 loopback only; on 2026-09-23 /api/ready answered 200 with status degraded [freshness], which is honest: no feed is configured; Network OAuth client trade and its grants exist; no Events subscription; production database held 0 instruments and 0 observations. Deployed internally, not launched: openvibe.trade still serves the OpenVibe.Sites placeholder until a person verifies the SEC XBRL terms and enables sec-xbrl-filings in Sources, a licensed market data feed exists, and editors add instruments","placeholderInSites": true,-- "updated": "2026-09-23"++ "updated": "2026-09-28",++ "features": [++ "informational only: a route-inventory test refuses any execution, custody or advice endpoint",++ "instruments with exact, deterministic resolution (CIK, ticker, name)",++ "observations with required timestamps; no observation, no number",++ "per-source freshness with stale badges and transition events",++ "SEC EDGAR filings from Sources matched to instruments",++ "private watchlists",++ "threshold, filing-type and new-document alerts (trade.alert.triggered)",++ "cited editor context; AI drafts need approval; advice refused",++ "server-rendered pages useful without JavaScript",++ "/api/v1 by capability",++ "SDK outbox events and Search index documents",++ "per-actor limits (openvibe-sdk/limits)"++ ]}
@@ -194,12 +194,24 @@ webhook, as a wake-up for the cursor sync (the webhook is not durable truth; the
@@ -194,12 +194,24 @@ webhook, as a wake-up for the cursor sync (the webhook is not durable truth; the
3. The revision is an AI-generated **draft**: labelled, noindex, not shown to readers until a person
3. The revision is an AI-generated **draft**: labelled, noindex, not shown to readers until a person
on the editor list approves it at `/editor/i/:symbol`.
on the editor list approves it at `/editor/i/:symbol`.
+## Capabilities
+
+Implemented here (the service manifest's `capabilities`, audience `openvibe.trade`, one per route; the
+route table is under [API](#api-apiv1-problemjson-errors)): `trade.instrument.resolve`,
+`trade.instrument.manage`, `trade.observation.write`, `trade.context.read`, `trade.context.propose`,
+`trade.watchlist.read`, `.create`, `.update`, `.delete`, and `trade.alert.read`, `.create`, `.delete`.
+None of them moves, holds or orders anything (ADR-025; `test/route-inventory.test.js`).
+
+Called elsewhere, as the service principal `trade`: `events.event.publish` (Events) and
+`sources.item.read` and `sources.source.read` (Sources). The list with audiences, and the grants other
+services need to call Trade, is under [Grants the Network must hold](#grants-the-network-must-hold).
+
## Depends on
## Depends on
-- **Packages** (pinned by release tarball): `openvibe-contracts` v0.33.0, `openvibe-publishing`
- v0.2.1 (revisions, authorship, seo, index-hooks, ssr), `openvibe-shared` v1.5.1 (chrome, app icon,
- footer, legal, release, metrics, ready), `openvibe-sdk` v0.5.0 (events outbox and inbox, webhook
- signatures v2, service tokens).
+- **Packages** (pinned by release tarball): `openvibe-contracts` v0.49.0, `openvibe-publishing`
+ v0.4.0 (revisions, authorship, seo, index-hooks, ssr), `openvibe-shared` v1.22.0 (chrome, app icon,
+ footer, legal, release, metrics, ready), `openvibe-sdk` v0.12.0 (events outbox and inbox, webhook
+ signatures v2, service tokens, per-actor limits).
- **OpenVibe.Network:** SSO (OAuth client `trade`, redirect `https://openvibe.trade/auth/callback`),
- **OpenVibe.Network:** SSO (OAuth client `trade`, redirect `https://openvibe.trade/auth/callback`),
JWKS, client-credentials tokens.
JWKS, client-credentials tokens.
- **OpenVibe.Sources:** `sources.item.read` and `sources.source.read` (category `trade`).
- **OpenVibe.Sources:** `sources.item.read` and `sources.source.read` (category `trade`).
@@ -262,6 +274,8 @@ registry, atomically. A placeholder never counts as an implemented service.
@@ -262,6 +274,8 @@ registry, atomically. A placeholder never counts as an implemented service.
## Security and threat review
## Security and threat review
+Reporting a vulnerability: [SECURITY.md](SECURITY.md).
+
- **Scope (ADR-025):** nothing moves or holds value. The route-inventory test is in CI; context that
- **Scope (ADR-025):** nothing moves or holds value. The route-inventory test is in CI; context that
reads as advice is refused; the disclaimer is on every page.
reads as advice is refused; the disclaimer is on every page.
- **Identity:** only verified Network JWTs (offline RS256 against JWKS) and service tokens for
- **Identity:** only verified Network JWTs (offline RS256 against JWKS) and service tokens for
@@ -326,6 +340,15 @@ fnm exec --using=22.22.1 npm run dev # http://localhost:4860 (set OV_OAUTH
@@ -326,6 +340,15 @@ fnm exec --using=22.22.1 npm run dev # http://localhost:4860 (set OV_OAUTH
## Deploy (for the lead)
## Deploy (for the lead)
+Production deploys with `sudo ovhost deploy trade` on the host (strategy `git-checkout`: fetch,
+fast-forward `/opt/openvibe.trade`, install on a lockfile change, restart, wait for `/api/ready`).
+The unit is `openvibe-trade.service` on `127.0.0.1:4860`, the env file `/etc/openvibe/trade.env`.
+Rollback: ovhost puts the previous sha back by itself when `/api/ready` does not answer 2xx after the
+restart; afterwards `sudo ovhost rollback trade --to <sha>`. Nothing blocks a rollback: the schema
+code only adds tables and columns.
+
+First install (done once; kept for a rebuild):
+
1. **Code and config:** code at `/opt/openvibe.trade`, `npm ci --omit=dev` on Node 22.
1. **Code and config:** code at `/opt/openvibe.trade`, `npm ci --omit=dev` on Node 22.
Create `/etc/openvibe/trade.env` (0600) from `.env.example` with `OV_OAUTH_CLIENT_SECRET`,
Create `/etc/openvibe/trade.env` (0600) from `.env.example` with `OV_OAUTH_CLIENT_SECRET`,
`TRADE_EDITORS`, `TRADE_FORM_SECRET`, `EVENTS_URL=http://127.0.0.1:4300`,
`TRADE_EDITORS`, `TRADE_FORM_SECRET`, `EVENTS_URL=http://127.0.0.1:4300`,
@@ -8,12 +8,8 @@
@@ -8,12 +8,8 @@
"port": 4860,
"port": 4860,
"domain": "openvibe.trade",
"domain": "openvibe.trade",
"scope": "informational only (ADR-025): no custody, no order execution, no escrow, no listings between users, no personalised advice",
"scope": "informational only (ADR-025): no custody, no order execution, no escrow, no listings between users, no personalised advice",
- "packages": [
- "openvibe-contracts v0.33.0",
- "openvibe-publishing v0.2.1",
- "openvibe-shared v1.5.1",
- "openvibe-sdk v0.5.0"
- ],
+ "contracts": "openvibe-contracts v0.49.0",
+ "packages": ["openvibe-contracts v0.49.0", "openvibe-publishing v0.4.0", "openvibe-shared v1.22.0", "openvibe-sdk v0.12.0"],
"capabilities": [
"capabilities": [
"trade.instrument.resolve",
"trade.instrument.resolve",
"trade.instrument.manage",
"trade.instrument.manage",
@@ -33,7 +29,21 @@
@@ -33,7 +29,21 @@
"marketDataFeeds": "none configured: the only seeded trade source in OpenVibe.Sources (SEC EDGAR XBRL filings RSS) is disabled there, and it carries filings, not prices; no observation exists until a source states one",
"marketDataFeeds": "none configured: the only seeded trade source in OpenVibe.Sources (SEC EDGAR XBRL filings RSS) is disabled there, and it carries filings, not prices; no observation exists until a source states one",
"seed": "none (tests create their own instruments; production holds 0 instruments and 0 observations)",
"seed": "none (tests create their own instruments; production holds 0 instruments and 0 observations)",
"deployed": true,
"deployed": true,
- "deployment": "openvibe-ovh, unit openvibe-trade, 127.0.0.1:4860 loopback only (release 9a55644); /api/ready 200 with status degraded [freshness], which is honest: no feed is configured; Network OAuth client trade and its grants exist; no Events subscription; production database holds 0 instruments and 0 observations. Deployed internally, not launched: openvibe.trade still serves the OpenVibe.Sites placeholder until a person verifies the SEC XBRL terms and enables sec-xbrl-filings in Sources, a licensed market data feed exists, and editors add instruments",
+ "deployment": "Deployed with `sudo ovhost deploy trade`: unit openvibe-trade, 127.0.0.1:4860 loopback only; on 2026-09-23 /api/ready answered 200 with status degraded [freshness], which is honest: no feed is configured; Network OAuth client trade and its grants exist; no Events subscription; production database held 0 instruments and 0 observations. Deployed internally, not launched: openvibe.trade still serves the OpenVibe.Sites placeholder until a person verifies the SEC XBRL terms and enables sec-xbrl-filings in Sources, a licensed market data feed exists, and editors add instruments",
"placeholderInSites": true,
"placeholderInSites": true,
- "updated": "2026-09-23"
+ "updated": "2026-09-28",
+ "features": [
+ "informational only: a route-inventory test refuses any execution, custody or advice endpoint",
+ "instruments with exact, deterministic resolution (CIK, ticker, name)",
+ "observations with required timestamps; no observation, no number",
+ "per-source freshness with stale badges and transition events",
+ "SEC EDGAR filings from Sources matched to instruments",
+ "private watchlists",
+ "threshold, filing-type and new-document alerts (trade.alert.triggered)",
+ "cited editor context; AI drafts need approval; advice refused",
+ "server-rendered pages useful without JavaScript",
+ "/api/v1 by capability",
+ "SDK outbox events and Search index documents",
+ "per-actor limits (openvibe-sdk/limits)"
+ ]
}
}