openvibers/openvibe.contracts Commits

v0.19.0: OpenVibe.VIP is alpha (vip.* capabilities)

OP OpenVibers committed 23 Sept 2026 · 88cb46b33c · 16 files, +318 −10


Changes

ddiff --git a/manifests/capabilities/vip.creator.members.list.json b/manifests/capabilities/vip.creator.members.list.json
nnew file mode 100644
iindex 00000000..fd043132
---- /dev/null
++++ b/manifests/capabilities/vip.creator.members.list.json
@@@ -0,0 +1,19 @@
++{
++ "id": "vip.creator.members.list",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "A creator's active members with the plan version each joined under: from Billing's subscriptions, or VIP's fresh projection (labelled) when Billing does not answer.",
++ "permissions": [
++ "vip:members"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-read",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/creators/:ref/members"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.entitlement.check.json b/manifests/capabilities/vip.entitlement.check.json
nnew file mode 100644
iindex 00000000..aea34483
---- /dev/null
++++ b/manifests/capabilities/vip.entitlement.check.json
@@@ -0,0 +1,20 @@
++{
++ "id": "vip.entitlement.check",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Is a subject a member of a creator right now? Answered from VIP's short-lived projection of Billing entitlements, with a direct Billing check when the projection is stale (mode auto) or always (mode authoritative). Past valid_until plus grace the answer is \"unknown\", which never authorizes.",
++ "permissions": [
++ "vip:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "vip-read",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/entitlements/check",
++ "POST /api/v1/entitlements/check"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.membership.checkout.json b/manifests/capabilities/vip.membership.checkout.json
nnew file mode 100644
iindex 00000000..1cfadb79
---- /dev/null
++++ b/manifests/capabilities/vip.membership.checkout.json
@@@ -0,0 +1,21 @@
++{
++ "id": "vip.membership.checkout",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Start joining a plan on behalf of a member: VIP records the plan version chosen and hands off to OpenVibe.Billing (payment intent, or a period paid from the member's credit). Billing charges; VIP never does.",
++ "permissions": [
++ "vip:checkout"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-write",
++ "events": [
++ "vip.membership.changed"
++ ],
++ "implementedBy": [
++ "POST /api/v1/checkout"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.membership.status.json b/manifests/capabilities/vip.membership.status.json
nnew file mode 100644
iindex 00000000..d475d60e
---- /dev/null
++++ b/manifests/capabilities/vip.membership.status.json
@@@ -0,0 +1,19 @@
++{
++ "id": "vip.membership.status",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "A member's memberships: the plan version each was bought under, preferences, and the entitlement status (projection, confirmed with Billing when stale).",
++ "permissions": [
++ "vip:read"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-read",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/memberships/:subject"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.perk.create.json b/manifests/capabilities/vip.perk.create.json
nnew file mode 100644
iindex 00000000..76aab1f3
---- /dev/null
++++ b/manifests/capabilities/vip.perk.create.json
@@@ -0,0 +1,19 @@
++{
++ "id": "vip.perk.create",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Define a perk (badge, emote, gated content, room, role) for a creator or the network, with its product bindings.",
++ "permissions": [
++ "vip:perks"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-write",
++ "events": [],
++ "implementedBy": [
++ "POST /api/v1/perks"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.perk.list.json b/manifests/capabilities/vip.perk.list.json
nnew file mode 100644
iindex 00000000..c5b4e98d
---- /dev/null
++++ b/manifests/capabilities/vip.perk.list.json
@@@ -0,0 +1,19 @@
++{
++ "id": "vip.perk.list",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "public",
++ "description": "List a creator's perks (and the network perks) with product bindings. Active perks are public; the grant adds retired ones.",
++ "permissions": [
++ "vip:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "vip-read",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/perks"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.perk.update.json b/manifests/capabilities/vip.perk.update.json
nnew file mode 100644
iindex 00000000..8cb7809d
---- /dev/null
++++ b/manifests/capabilities/vip.perk.update.json
@@@ -0,0 +1,19 @@
++{
++ "id": "vip.perk.update",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Rename, describe, retire a perk or replace its product bindings. Published plan versions keep the perk snapshot they were published with.",
++ "permissions": [
++ "vip:perks"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-write",
++ "events": [],
++ "implementedBy": [
++ "PATCH /api/v1/perks/:id"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.plan.archive.json b/manifests/capabilities/vip.plan.archive.json
nnew file mode 100644
iindex 00000000..5a7e879f
---- /dev/null
++++ b/manifests/capabilities/vip.plan.archive.json
@@@ -0,0 +1,19 @@
++{
++ "id": "vip.plan.archive",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Archive a plan: no new members; existing members keep their terms until Billing ends their membership.",
++ "permissions": [
++ "vip:plans"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-write",
++ "events": [],
++ "implementedBy": [
++ "POST /api/v1/plans/:id/archive"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.plan.create.json b/manifests/capabilities/vip.plan.create.json
nnew file mode 100644
iindex 00000000..aa711390
---- /dev/null
++++ b/manifests/capabilities/vip.plan.create.json
@@@ -0,0 +1,21 @@
++{
++ "id": "vip.plan.create",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Create a membership plan (version 1) for a creator, or for the network (staff). A published plan is sold through OpenVibe.Billing as the creator's channel subscription; Billing sets the price.",
++ "permissions": [
++ "vip:plans"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-write",
++ "events": [
++ "vip.plan.published"
++ ],
++ "implementedBy": [
++ "POST /api/v1/plans"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.plan.list.json b/manifests/capabilities/vip.plan.list.json
nnew file mode 100644
iindex 00000000..0fb0ede6
---- /dev/null
++++ b/manifests/capabilities/vip.plan.list.json
@@@ -0,0 +1,22 @@
++{
++ "id": "vip.plan.list",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "public",
++ "description": "List a creator's plans with their current and draft versions and the full version history. Published plans are public without a grant; the grant adds drafts and archived plans.",
++ "permissions": [
++ "vip:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "vip-read",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/plans",
++ "GET /api/v1/plans/:id",
++ "GET /api/v1/plans/:id/versions",
++ "GET /api/v1/creators/:ref"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.plan.update.json b/manifests/capabilities/vip.plan.update.json
nnew file mode 100644
iindex 00000000..773278a9
---- /dev/null
++++ b/manifests/capabilities/vip.plan.update.json
@@@ -0,0 +1,22 @@
++{
++ "id": "vip.plan.update",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Edit a plan by creating a new immutable version (published at once when the plan is published), or publish a draft. Earlier versions and the terms members joined under are never rewritten.",
++ "permissions": [
++ "vip:plans"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-write",
++ "events": [
++ "vip.plan.published"
++ ],
++ "implementedBy": [
++ "PATCH /api/v1/plans/:id",
++ "POST /api/v1/plans/:id/publish"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.resource.policy.evaluate.json b/manifests/capabilities/vip.resource.policy.evaluate.json
nnew file mode 100644
iindex 00000000..1110be50
---- /dev/null
++++ b/manifests/capabilities/vip.resource.policy.evaluate.json
@@@ -0,0 +1,19 @@
++{
++ "id": "vip.resource.policy.evaluate",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "May subject S see resource R (under rule X)? Fails closed: no rule, a disabled rule, an entitlement VIP cannot confirm, a missing perk or any error is allow: false with the reason.",
++ "permissions": [
++ "vip:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "vip-read",
++ "events": [],
++ "implementedBy": [
++ "POST /api/v1/policies/evaluate"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.resource.policy.get.json b/manifests/capabilities/vip.resource.policy.get.json
nnew file mode 100644
iindex 00000000..11e16367
---- /dev/null
++++ b/manifests/capabilities/vip.resource.policy.get.json
@@@ -0,0 +1,20 @@
++{
++ "id": "vip.resource.policy.get",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Read the gated-resource rule VIP holds for a resource (EntityRef), or a creator's rules.",
++ "permissions": [
++ "vip:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "vip-read",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/policies",
++ "GET /api/v1/policies/:id"
++ ]
++}
ddiff --git a/manifests/capabilities/vip.resource.policy.set.json b/manifests/capabilities/vip.resource.policy.set.json
nnew file mode 100644
iindex 00000000..130c044b
---- /dev/null
++++ b/manifests/capabilities/vip.resource.policy.set.json
@@@ -0,0 +1,20 @@
++{
++ "id": "vip.resource.policy.set",
++ "version": "1.0",
++ "owner": "vip",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Create, replace or remove the rule gating a resource (EntityRef) for a creator: any member, members of one plan, or members whose plan version includes a perk; optionally always checked with Billing (sensitive).",
++ "permissions": [
++ "vip:policies"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "vip-write",
++ "events": [],
++ "implementedBy": [
++ "POST /api/v1/policies",
++ "DELETE /api/v1/policies/:id"
++ ]
++}
ddiff --git a/manifests/services/vip.json b/manifests/services/vip.json
iindex 601dfdc5..c8b5c780 100644
---- a/manifests/services/vip.json
++++ b/manifests/services/vip.json
@@@ -1,16 +1,45 @@
{
-- "version": "0.1.0",
++ "version": "0.2.0",
"contractRanges": {
-- "openvibe-contracts": "^0.1.0"
++ "openvibe-contracts": ">=0.14.0 <1.0.0"
},
"id": "vip",
"name": "OpenVibe.VIP",
-- "status": "placeholder",
++ "status": "alpha",
"repository": "OpenVibers/OpenVibe.VIP",
-- "domains": [],
-- "capabilities": [],
-- "eventsProduced": [],
-- "eventsConsumed": [],
-- "namespacesOwned": [],
-- "notes": "Memberships: plans, perks and benefits recognised across every OpenVibe site. Charter only; no runtime."
++ "domains": [
++ "openvibe.vip"
++ ],
++ "publicOrigin": "https://openvibe.vip",
++ "health": "/api/health",
++ "ready": "/api/ready",
++ "capabilities": [
++ "vip.plan.create",
++ "vip.plan.update",
++ "vip.plan.archive",
++ "vip.plan.list",
++ "vip.perk.create",
++ "vip.perk.update",
++ "vip.perk.list",
++ "vip.membership.checkout",
++ "vip.membership.status",
++ "vip.entitlement.check",
++ "vip.resource.policy.get",
++ "vip.resource.policy.set",
++ "vip.resource.policy.evaluate",
++ "vip.creator.members.list"
++ ],
++ "eventsProduced": [
++ "vip.plan.published",
++ "vip.membership.changed"
++ ],
++ "eventsConsumed": [
++ "billing.entitlement.changed",
++ "billing.subscription.canceled",
++ "billing.transaction.reversed"
++ ],
++ "namespacesOwned": [
++ "vip.*"
++ ],
++ "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: not deployed; openvibe.vip stays on its OpenVibe.Sites placeholder until the launch rule holds."
}
ddiff --git a/package.json b/package.json
iindex 7283ef6d..ab3c9fbe 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.18.0",
++ "version": "0.19.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"types": "generated/typescript/index.d.ts",