VipPlanPublishedPayload vip.plan.published@1

Generated at from openvibe-contracts v0.33.0 and openvibe-sdk v0.5.0.

Version
1.0.0
Owner
vip
Visibility
public
Status
active
Compatibility
backward
Decision
ADR-012
Schema
https://openvibe.network/contracts/events/payloads/vip.plan.published.v1.json

vip.plan.published v1 (OpenVibe.VIP server/domain/plans.js emitPublished). A plan version became what new members buy: the plan was published, or a published plan was edited (a new immutable version). Carries the version's full terms, never a price (Billing prices and charges). Envelope: subject { type: plan, id: vpl_…, revision: <version> }, visibility public, priority important, actor service:vip.

Fields

FieldTypeRequiredDescriptionConstraints
plan_idstringyes
  • pattern ^vpl_[0-9A-HJKMNP-TV-Z]{26}$
slugstringyes
  • pattern ^[a-z0-9][a-z0-9-]{0,47}$
versionintegeryes
  • minimum 1
version_idstringyes
  • pattern ^vpv_[0-9A-HJKMNP-TV-Z]{26}$
creatorobjectyes
  • no other fields
creator.idstringyesvcr_… or network.
creator.kindenumyes
  • one of "creator", "network"
creator.subjectone ofyesnull for the network creator.
creator.usernamestring | nullyes
creator.display_namestring | nullyes
creator.biostring | nullyes
creator.statusenumyes
  • one of "active", "suspended"
billing_kindenumyesThe Billing product that sells it; null for a plan Billing does not sell (network plans).
  • one of "channel_subscription", null
termsobjectyes
  • no other fields
terms.namestringyes
terms.descriptionstring | nullyes
terms.benefitsarray | nullyes
  • maxItems 20
terms.perksarray of objectyes
  • items: no other fields
terms.perks[].keystringyes
terms.perks[].namestringyes
terms.perks[].kindenumyes
  • one of "badge", "emote", "gated_content", "room", "role", "other"
terms.perks[].scopeenumyes
  • one of "creator", "network"
terms.billing_kindenumyes
  • one of "channel_subscription", null
terms.pricestring | nullyesNever an amount: a note that Billing sets and charges the price, or null.
terms.digeststringyessha256 prefix of name, description, benefits, perks and billing_kind.
  • pattern ^[0-9a-f]{16}$
published_atstringyes
  • format date-time

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: channel-plan
{
  "plan_id": "vpl_01JAB3C4D5E6F7G8H9J0K1MNPV",
  "slug": "supporters",
  "version": 2,
  "version_id": "vpv_01JAB3C4D5E6F7G8H9J0K1MNPW",
  "creator": {
    "id": "vcr_01JAB3C4D5E6F7G8H9J0K1MNPX",
    "kind": "creator",
    "subject": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    },
    "username": "japaneseoldguy",
    "display_name": "JapaneseOldGuy",
    "bio": null,
    "status": "active"
  },
  "billing_kind": "channel_subscription",
  "terms": {
    "name": "Supporters",
    "description": "Back the channel.",
    "benefits": [
      "Sub badge",
      "Emote-only chat"
    ],
    "perks": [
      {
        "key": "badge",
        "name": "Sub badge",
        "kind": "badge",
        "scope": "creator"
      }
    ],
    "billing_kind": "channel_subscription",
    "price": "set and charged by OpenVibe.Billing",
    "digest": "3f9a0c1d2e4b5a67"
  },
  "published_at": "2026-09-23T10:00:00.000Z"
}
Valid: network-plan
{
  "plan_id": "vpl_01JAB3C4D5E6F7G8H9J0K1MNPV",
  "slug": "supporters",
  "version": 2,
  "version_id": "vpv_01JAB3C4D5E6F7G8H9J0K1MNPW",
  "creator": {
    "id": "network",
    "kind": "network",
    "subject": null,
    "username": null,
    "display_name": "OpenVibe",
    "bio": null,
    "status": "active"
  },
  "billing_kind": null,
  "terms": {
    "name": "Supporters",
    "description": "Back the channel.",
    "benefits": null,
    "perks": [],
    "billing_kind": null,
    "price": null,
    "digest": "3f9a0c1d2e4b5a67"
  },
  "published_at": "2026-09-23T10:00:00.000Z"
}
Rejected: price-in-terms
{
  "plan_id": "vpl_01JAB3C4D5E6F7G8H9J0K1MNPV",
  "slug": "supporters",
  "version": 2,
  "version_id": "vpv_01JAB3C4D5E6F7G8H9J0K1MNPW",
  "creator": {
    "id": "vcr_01JAB3C4D5E6F7G8H9J0K1MNPX",
    "kind": "creator",
    "subject": {
      "type": "user",
      "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
    },
    "username": "japaneseoldguy",
    "display_name": "JapaneseOldGuy",
    "bio": null,
    "status": "active"
  },
  "billing_kind": "channel_subscription",
  "terms": {
    "name": "Supporters",
    "description": "Back the channel.",
    "benefits": [
      "Sub badge",
      "Emote-only chat"
    ],
    "perks": [
      {
        "key": "badge",
        "name": "Sub badge",
        "kind": "badge",
        "scope": "creator"
      }
    ],
    "billing_kind": "channel_subscription",
    "price": "set and charged by OpenVibe.Billing",
    "digest": "3f9a0c1d2e4b5a67",
    "price_cents": 499
  },
  "published_at": "2026-09-23T10:00:00.000Z"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('vip.plan.published@1', value);   // { valid, errors: [{ path, message }] }