openvibers/openvibe.vip Commits
README and STATUS.json are current (roadmap WS-U task 3): the README gains Capabilities (the 14 vip.* capabilities and the grants VIP uses at Billing, Events and Network) and Deploy (sudo ovhost deploy vip, unit, port, env file, state, vhost, rollback and its index blocker) sections; Security notes point to SECURITY.md; Depends on names the current pins (contracts v0.49.0, sdk v0.12.0, shared v1.22.0) and Wiki as a consumer; the status line and acceptance note no longer say the Live import has not run or that production holds no plans. STATUS.json gains contracts and features and is updated 2026-09-28.
Changes
@@@ -3,8 +3,8 @@> Memberships: plans, perks and benefits recognised across every OpenVibe site.**Status:** alpha — runtime built and tested (roadmap Wave 10). Deployed internally, **not launched**:--it runs on the host since 2026-09-23 on `127.0.0.1:4620` only, with one creator (`network`) and no plans--or memberships, and checkout closed. `openvibe.vip` keeps its++it runs on the host since 2026-09-23 on `127.0.0.1:4620` only, holding the Live import (on 2026-09-24:++44 creators, 43 plans, 0 memberships), with checkout closed. `openvibe.vip` keeps its[OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) placeholder until the launch rulebelow holds.**Domain:** `openvibe.vip` (port 4620, service id `vip`)@@@ -60,12 +60,27 @@ home that is not a cache.- **OpenVibe.Network** — RS256 service and user tokens (JWKS), OAuth sign-in for the pages, identityresolve (importer only).- **OpenVibe.Events** — delivery of Billing's events to `/internal/events`; relay of VIP's outbox.--- **openvibe-contracts** v0.33.0, **openvibe-sdk** v0.5.0 (outbox, inbox, delivery signatures),-- **openvibe-shared** v1.5.1 (chrome, legal pages, release manifest and update metrics, metrics, readiness).++- **openvibe-contracts** v0.49.0, **openvibe-sdk** v0.12.0 (outbox, inbox, delivery signatures, per-actor++ limits), **openvibe-shared** v1.22.0 (chrome, legal pages, release manifest and update metrics, metrics,++ readiness).- Consumers, through the client below: Chat (the member badge), Community (members-only spaces and-- threads) and Blog (members-only posts); Live and Wiki are not wired yet.++ threads), Blog (members-only posts) and Wiki (VIP spaces and pages); Live is not wired yet.- **Not** OpenVibe.Live: VIP works with Live unavailable (nothing here calls Live).++## Capabilities++++Implemented here (the service manifest's `capabilities`, 14 `vip.*` ids, audience `openvibe.vip`):++`vip.plan.create|update|archive|list`, `vip.perk.create|update|list`, `vip.membership.checkout|status`,++`vip.entitlement.check`, `vip.resource.policy.get|set|evaluate` and `vip.creator.members.list`.++++Called elsewhere, as the service principal `vip`:++++| Service | Grant | Why |++|---|---|---|++| OpenVibe.Billing | `billing.intent.create`, `billing.subscription.manage`, `billing.entitlement.check` | checkout, credit-paid periods and cancel, the authoritative check |++| OpenVibe.Events | `events.event.publish`; `events.subscription.manage` once (`scripts/subscribe.js`) | the outbox relay; the three subscriptions for Billing's events |++| OpenVibe.Network | `identity.subject.resolve` | the Live importer's creator mapping |++## Run it```bash@@@ -323,6 +338,8 @@ final import), `scripts/subscribe.js`, then open checkout (`VIP_CHECKOUT_PROVIDE## Security notes++Reporting a vulnerability: [SECURITY.md](SECURITY.md).++- Every API route checks one capability (services) or ownership (users); a presented token is judgedon that token alone. The API never reads cookies.- Billing events: HMAC-SHA256 signature over the raw body (`VIP_EVENTS_SECRET`, rotation by list),@@@ -360,9 +377,22 @@ final import), `scripts/subscribe.js`, then open checkout (`VIP_CHECKOUT_PROVIDE| VIP works with Live unavailable | no code path calls Live; every test runs without a Live stub || a creator's membership card, badge and widget are public-data only, the same for everyone, embeddable and inert | `test/embeds.test.js` (published plans only, no subjects or binding configs, no cookie read or set, CORS, SVG escaping and sandbox, the widget's frame-ancestors and hashed style, the creator's member-count switch, Billing outage keeps the last count or shows none) |--Not yet demonstrated (needs the other services): convergence **across consuming products** (Live,--Chat, Community do not call VIP yet), and a real Billing/Events round trip on the host (Billing is in--shadow and has sent VIP no events). The Live import has not been run on production.++Not yet demonstrated (needs the other services): convergence **across consuming products** end to end++(Chat, Community, Blog and Wiki call VIP in code; Live does not), and a real Billing/Events round trip++on the host (Billing is in shadow and has sent VIP no events). The Live import ran on production on++2026-09-23.++++## Deploy++++Production deploys with `sudo ovhost deploy vip` on the host (strategy `git-checkout`: fetch,++fast-forward `/opt/openvibe.vip`, install on a lockfile change, restart, wait for `/api/ready`).++The unit is `openvibe-vip.service` on `127.0.0.1:4620`, the env file `/etc/openvibe/vip.env`. State lives in++`/var/lib/openvibe-vip`. The vhost [deploy/nginx/openvibe.vip.conf](deploy/nginx/openvibe.vip.conf) waits++for the launch: `openvibe.vip` serves the Sites placeholder.++Rollback: ovhost puts the previous sha back by itself when `/api/ready` does not answer 2xx after the++restart; afterwards `sudo ovhost rollback vip --to <sha>`. One blocker: `idx_vip_rules_resource` (one++active rule per resource) was replaced by a per-creator unique index, and a release from before it++recreates the narrower index, which fails at boot once two creators gate the same resource.## Launch rule@@@ -3,7 +3,8 @@"stage": "alpha","code": true,"deployed": true,-- "deployment": "Deployed internally, not launched: openvibe-ovh /opt/openvibe.vip (release a675577, openvibe-contracts 0.33.0, openvibe-sdk 0.5.0, openvibe-shared 1.5.1), unit openvibe-vip, 127.0.0.1:4620 loopback only; https://openvibe.vip still serves the OpenVibe.Sites placeholder. Principal vip; three Events subscriptions for Billing's events (secret rotated 2026-09-24); checkout closed (VIP_CHECKOUT_PROVIDERS empty). Production holds the Live import: 44 creators, 43 plans (one per creator), 0 memberships while Billing runs in shadow.",++ "deployment": "Deployed internally, not launched: deployed with `sudo ovhost deploy vip`, /opt/openvibe.vip, unit openvibe-vip, 127.0.0.1:4620 loopback only; https://openvibe.vip still serves the OpenVibe.Sites placeholder. Principal vip; three Events subscriptions for Billing's events (secret rotated 2026-09-24); checkout closed (VIP_CHECKOUT_PROVIDERS empty). On 2026-09-24 production held the Live import: 44 creators, 43 plans (one per creator), 0 memberships while Billing runs in shadow.",++ "contracts": "openvibe-contracts v0.49.0","plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)","roadmap": "Wave 10","works": [@@@ -11,15 +12,16 @@"entitlement projection fed by Billing events (signed webhook + openvibe-sdk inbox) with valid_until, grace and a direct Billing fallback; 'unknown' never authorizes","checkout hand-off and cancellation through OpenVibe.Billing; the membership is filed under the plan version chosen","API /api/v1 for service and user tokens; consumer client openvibe-vip/client that fails closed, with createVipCache (the product cache and its convergence bound, test/convergence.test.js)",-- "the product's default gate (evaluate fallback, honouring product bindings such as blog gated_post) and entitlements/check product perks (Chat's badge); Chat, Community and Blog consume them in code (not deployed, grants pending)",++ "the product's default gate (evaluate fallback, honouring product bindings such as blog gated_post) and entitlements/check product perks (Chat's badge); Chat, Community, Blog and Wiki consume them in code","server-rendered creator plan pages, terms history, member status and creator dashboard with the shared chrome","outbox events vip.plan.published and vip.membership.changed (openvibe-sdk)","import of Live's subscription offering, memberships from Billing entitlements",-- "14 vip.* capabilities, the service manifest and its events registered in openvibe-contracts v0.19.0","deployed on the host (loopback only) with truthful /api/ready and /metrics; restore drill passed on the host 2026-09-23 05:23 UTC","reusable membership card (GET /embed/:username/card.json, GET /api/v1/creators/:ref/card), badge (/embed/:username/badge.svg) and embeddable widget (/embed/:username/widget): public data only, no cookies, the widget's CSP frame-ancestors configurable (VIP_WIDGET_FRAME_ANCESTORS), member count from Billing that the creator can hide (not deployed yet)","the Live subscription import has run: 43 plans and plan versions, 44 creators, 87 migration maps (production, 2026-09-23)",-- "Chat (subscriber badge, vip.entitlement.check), Community (members-only spaces and threads) and Blog (members-only posts) call VIP in production (vip.resource.policy.evaluate grants for Community and Blog)"++ "Chat (subscriber badge, vip.entitlement.check), Community (members-only spaces and threads) and Blog (members-only posts) call VIP in production (vip.resource.policy.evaluate grants for Community and Blog)",++ "14 vip.* capabilities, the service manifest and its events registered in openvibe-contracts v0.19.0 (this repository pins v0.49.0)",++ "per-actor limits on /api/v1 (openvibe-sdk/limits)"],"not_yet": ["not launched: openvibe.vip is still an OpenVibe.Sites placeholder and the service answers on loopback only",@@@ -27,5 +29,17 @@"Billing sells one channel subscription per member and creator: one purchasable plan per creator, no tiers, no network membership product","revocations reach Chat and Community through vip.membership.changed subscriptions (2026-09-24); Blog and Live still converge by the cache TTL (30-60 s)"],-- "updated": "2026-09-24"++ "updated": "2026-09-28",++ "features": [++ "plans with immutable versions, perks and product bindings",++ "entitlement projection from Billing events with valid_until, grace and a Billing fallback; unknown never authorizes",++ "checkout and cancel through OpenVibe.Billing",++ "gated-resource policy evaluation for products (fails closed)",++ "openvibe-vip/client with the product cache and its convergence bound",++ "creator plan pages, terms history, member status and creator dashboard",++ "public membership card, badge and embeddable widget",++ "Live subscription import",++ "SDK outbox events vip.plan.published and vip.membership.changed",++ "per-actor limits (openvibe-sdk/limits)"++ ]}
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
> Memberships: plans, perks and benefits recognised across every OpenVibe site.
> Memberships: plans, perks and benefits recognised across every OpenVibe site.
**Status:** alpha — runtime built and tested (roadmap Wave 10). Deployed internally, **not launched**:
**Status:** alpha — runtime built and tested (roadmap Wave 10). Deployed internally, **not launched**:
-it runs on the host since 2026-09-23 on `127.0.0.1:4620` only, with one creator (`network`) and no plans
-or memberships, and checkout closed. `openvibe.vip` keeps its
+it runs on the host since 2026-09-23 on `127.0.0.1:4620` only, holding the Live import (on 2026-09-24:
+44 creators, 43 plans, 0 memberships), with checkout closed. `openvibe.vip` keeps its
[OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) placeholder until the launch rule
[OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) placeholder until the launch rule
below holds.
below holds.
**Domain:** `openvibe.vip` (port 4620, service id `vip`)
**Domain:** `openvibe.vip` (port 4620, service id `vip`)
@@ -60,12 +60,27 @@ home that is not a cache.
@@ -60,12 +60,27 @@ home that is not a cache.
- **OpenVibe.Network** — RS256 service and user tokens (JWKS), OAuth sign-in for the pages, identity
- **OpenVibe.Network** — RS256 service and user tokens (JWKS), OAuth sign-in for the pages, identity
resolve (importer only).
resolve (importer only).
- **OpenVibe.Events** — delivery of Billing's events to `/internal/events`; relay of VIP's outbox.
- **OpenVibe.Events** — delivery of Billing's events to `/internal/events`; relay of VIP's outbox.
-- **openvibe-contracts** v0.33.0, **openvibe-sdk** v0.5.0 (outbox, inbox, delivery signatures),
- **openvibe-shared** v1.5.1 (chrome, legal pages, release manifest and update metrics, metrics, readiness).
+- **openvibe-contracts** v0.49.0, **openvibe-sdk** v0.12.0 (outbox, inbox, delivery signatures, per-actor
+ limits), **openvibe-shared** v1.22.0 (chrome, legal pages, release manifest and update metrics, metrics,
+ readiness).
- Consumers, through the client below: Chat (the member badge), Community (members-only spaces and
- Consumers, through the client below: Chat (the member badge), Community (members-only spaces and
- threads) and Blog (members-only posts); Live and Wiki are not wired yet.
+ threads), Blog (members-only posts) and Wiki (VIP spaces and pages); Live is not wired yet.
- **Not** OpenVibe.Live: VIP works with Live unavailable (nothing here calls Live).
- **Not** OpenVibe.Live: VIP works with Live unavailable (nothing here calls Live).
+## Capabilities
+
+Implemented here (the service manifest's `capabilities`, 14 `vip.*` ids, audience `openvibe.vip`):
+`vip.plan.create|update|archive|list`, `vip.perk.create|update|list`, `vip.membership.checkout|status`,
+`vip.entitlement.check`, `vip.resource.policy.get|set|evaluate` and `vip.creator.members.list`.
+
+Called elsewhere, as the service principal `vip`:
+
+| Service | Grant | Why |
+|---|---|---|
+| OpenVibe.Billing | `billing.intent.create`, `billing.subscription.manage`, `billing.entitlement.check` | checkout, credit-paid periods and cancel, the authoritative check |
+| OpenVibe.Events | `events.event.publish`; `events.subscription.manage` once (`scripts/subscribe.js`) | the outbox relay; the three subscriptions for Billing's events |
+| OpenVibe.Network | `identity.subject.resolve` | the Live importer's creator mapping |
+
## Run it
## Run it
```bash
```bash
@@ -323,6 +338,8 @@ final import), `scripts/subscribe.js`, then open checkout (`VIP_CHECKOUT_PROVIDE
@@ -323,6 +338,8 @@ final import), `scripts/subscribe.js`, then open checkout (`VIP_CHECKOUT_PROVIDE
## Security notes
## Security notes
+Reporting a vulnerability: [SECURITY.md](SECURITY.md).
+
- Every API route checks one capability (services) or ownership (users); a presented token is judged
- Every API route checks one capability (services) or ownership (users); a presented token is judged
on that token alone. The API never reads cookies.
on that token alone. The API never reads cookies.
- Billing events: HMAC-SHA256 signature over the raw body (`VIP_EVENTS_SECRET`, rotation by list),
- Billing events: HMAC-SHA256 signature over the raw body (`VIP_EVENTS_SECRET`, rotation by list),
@@ -360,9 +377,22 @@ final import), `scripts/subscribe.js`, then open checkout (`VIP_CHECKOUT_PROVIDE
@@ -360,9 +377,22 @@ final import), `scripts/subscribe.js`, then open checkout (`VIP_CHECKOUT_PROVIDE
| VIP works with Live unavailable | no code path calls Live; every test runs without a Live stub |
| VIP works with Live unavailable | no code path calls Live; every test runs without a Live stub |
| a creator's membership card, badge and widget are public-data only, the same for everyone, embeddable and inert | `test/embeds.test.js` (published plans only, no subjects or binding configs, no cookie read or set, CORS, SVG escaping and sandbox, the widget's frame-ancestors and hashed style, the creator's member-count switch, Billing outage keeps the last count or shows none) |
| a creator's membership card, badge and widget are public-data only, the same for everyone, embeddable and inert | `test/embeds.test.js` (published plans only, no subjects or binding configs, no cookie read or set, CORS, SVG escaping and sandbox, the widget's frame-ancestors and hashed style, the creator's member-count switch, Billing outage keeps the last count or shows none) |
-Not yet demonstrated (needs the other services): convergence **across consuming products** (Live,
-Chat, Community do not call VIP yet), and a real Billing/Events round trip on the host (Billing is in
-shadow and has sent VIP no events). The Live import has not been run on production.
+Not yet demonstrated (needs the other services): convergence **across consuming products** end to end
+(Chat, Community, Blog and Wiki call VIP in code; Live does not), and a real Billing/Events round trip
+on the host (Billing is in shadow and has sent VIP no events). The Live import ran on production on
+2026-09-23.
+
+## Deploy
+
+Production deploys with `sudo ovhost deploy vip` on the host (strategy `git-checkout`: fetch,
+fast-forward `/opt/openvibe.vip`, install on a lockfile change, restart, wait for `/api/ready`).
+The unit is `openvibe-vip.service` on `127.0.0.1:4620`, the env file `/etc/openvibe/vip.env`. State lives in
+`/var/lib/openvibe-vip`. The vhost [deploy/nginx/openvibe.vip.conf](deploy/nginx/openvibe.vip.conf) waits
+for the launch: `openvibe.vip` serves the Sites placeholder.
+Rollback: ovhost puts the previous sha back by itself when `/api/ready` does not answer 2xx after the
+restart; afterwards `sudo ovhost rollback vip --to <sha>`. One blocker: `idx_vip_rules_resource` (one
+active rule per resource) was replaced by a per-creator unique index, and a release from before it
+recreates the narrower index, which fails at boot once two creators gate the same resource.
## Launch rule
## Launch rule
@@ -3,7 +3,8 @@
@@ -3,7 +3,8 @@
"stage": "alpha",
"stage": "alpha",
"code": true,
"code": true,
"deployed": true,
"deployed": true,
- "deployment": "Deployed internally, not launched: openvibe-ovh /opt/openvibe.vip (release a675577, openvibe-contracts 0.33.0, openvibe-sdk 0.5.0, openvibe-shared 1.5.1), unit openvibe-vip, 127.0.0.1:4620 loopback only; https://openvibe.vip still serves the OpenVibe.Sites placeholder. Principal vip; three Events subscriptions for Billing's events (secret rotated 2026-09-24); checkout closed (VIP_CHECKOUT_PROVIDERS empty). Production holds the Live import: 44 creators, 43 plans (one per creator), 0 memberships while Billing runs in shadow.",
+ "deployment": "Deployed internally, not launched: deployed with `sudo ovhost deploy vip`, /opt/openvibe.vip, unit openvibe-vip, 127.0.0.1:4620 loopback only; https://openvibe.vip still serves the OpenVibe.Sites placeholder. Principal vip; three Events subscriptions for Billing's events (secret rotated 2026-09-24); checkout closed (VIP_CHECKOUT_PROVIDERS empty). On 2026-09-24 production held the Live import: 44 creators, 43 plans (one per creator), 0 memberships while Billing runs in shadow.",
+ "contracts": "openvibe-contracts v0.49.0",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"roadmap": "Wave 10",
"roadmap": "Wave 10",
"works": [
"works": [
@@ -11,15 +12,16 @@
@@ -11,15 +12,16 @@
"entitlement projection fed by Billing events (signed webhook + openvibe-sdk inbox) with valid_until, grace and a direct Billing fallback; 'unknown' never authorizes",
"entitlement projection fed by Billing events (signed webhook + openvibe-sdk inbox) with valid_until, grace and a direct Billing fallback; 'unknown' never authorizes",
"checkout hand-off and cancellation through OpenVibe.Billing; the membership is filed under the plan version chosen",
"checkout hand-off and cancellation through OpenVibe.Billing; the membership is filed under the plan version chosen",
"API /api/v1 for service and user tokens; consumer client openvibe-vip/client that fails closed, with createVipCache (the product cache and its convergence bound, test/convergence.test.js)",
"API /api/v1 for service and user tokens; consumer client openvibe-vip/client that fails closed, with createVipCache (the product cache and its convergence bound, test/convergence.test.js)",
- "the product's default gate (evaluate fallback, honouring product bindings such as blog gated_post) and entitlements/check product perks (Chat's badge); Chat, Community and Blog consume them in code (not deployed, grants pending)",
+ "the product's default gate (evaluate fallback, honouring product bindings such as blog gated_post) and entitlements/check product perks (Chat's badge); Chat, Community, Blog and Wiki consume them in code",
"server-rendered creator plan pages, terms history, member status and creator dashboard with the shared chrome",
"server-rendered creator plan pages, terms history, member status and creator dashboard with the shared chrome",
"outbox events vip.plan.published and vip.membership.changed (openvibe-sdk)",
"outbox events vip.plan.published and vip.membership.changed (openvibe-sdk)",
"import of Live's subscription offering, memberships from Billing entitlements",
"import of Live's subscription offering, memberships from Billing entitlements",
- "14 vip.* capabilities, the service manifest and its events registered in openvibe-contracts v0.19.0",
"deployed on the host (loopback only) with truthful /api/ready and /metrics; restore drill passed on the host 2026-09-23 05:23 UTC",
"deployed on the host (loopback only) with truthful /api/ready and /metrics; restore drill passed on the host 2026-09-23 05:23 UTC",
"reusable membership card (GET /embed/:username/card.json, GET /api/v1/creators/:ref/card), badge (/embed/:username/badge.svg) and embeddable widget (/embed/:username/widget): public data only, no cookies, the widget's CSP frame-ancestors configurable (VIP_WIDGET_FRAME_ANCESTORS), member count from Billing that the creator can hide (not deployed yet)",
"reusable membership card (GET /embed/:username/card.json, GET /api/v1/creators/:ref/card), badge (/embed/:username/badge.svg) and embeddable widget (/embed/:username/widget): public data only, no cookies, the widget's CSP frame-ancestors configurable (VIP_WIDGET_FRAME_ANCESTORS), member count from Billing that the creator can hide (not deployed yet)",
"the Live subscription import has run: 43 plans and plan versions, 44 creators, 87 migration maps (production, 2026-09-23)",
"the Live subscription import has run: 43 plans and plan versions, 44 creators, 87 migration maps (production, 2026-09-23)",
- "Chat (subscriber badge, vip.entitlement.check), Community (members-only spaces and threads) and Blog (members-only posts) call VIP in production (vip.resource.policy.evaluate grants for Community and Blog)"
+ "Chat (subscriber badge, vip.entitlement.check), Community (members-only spaces and threads) and Blog (members-only posts) call VIP in production (vip.resource.policy.evaluate grants for Community and Blog)",
+ "14 vip.* capabilities, the service manifest and its events registered in openvibe-contracts v0.19.0 (this repository pins v0.49.0)",
+ "per-actor limits on /api/v1 (openvibe-sdk/limits)"
],
],
"not_yet": [
"not_yet": [
"not launched: openvibe.vip is still an OpenVibe.Sites placeholder and the service answers on loopback only",
"not launched: openvibe.vip is still an OpenVibe.Sites placeholder and the service answers on loopback only",
@@ -27,5 +29,17 @@
@@ -27,5 +29,17 @@
"Billing sells one channel subscription per member and creator: one purchasable plan per creator, no tiers, no network membership product",
"Billing sells one channel subscription per member and creator: one purchasable plan per creator, no tiers, no network membership product",
"revocations reach Chat and Community through vip.membership.changed subscriptions (2026-09-24); Blog and Live still converge by the cache TTL (30-60 s)"
"revocations reach Chat and Community through vip.membership.changed subscriptions (2026-09-24); Blog and Live still converge by the cache TTL (30-60 s)"
],
],
- "updated": "2026-09-24"
+ "updated": "2026-09-28",
+ "features": [
+ "plans with immutable versions, perks and product bindings",
+ "entitlement projection from Billing events with valid_until, grace and a Billing fallback; unknown never authorizes",
+ "checkout and cancel through OpenVibe.Billing",
+ "gated-resource policy evaluation for products (fails closed)",
+ "openvibe-vip/client with the product cache and its convergence bound",
+ "creator plan pages, terms history, member status and creator dashboard",
+ "public membership card, badge and embeddable widget",
+ "Live subscription import",
+ "SDK outbox events vip.plan.published and vip.membership.changed",
+ "per-actor limits (openvibe-sdk/limits)"
+ ]
}
}