openvibers/openvibe.contracts Commits
v0.47.0: network.grant.changed payload (a service grant given, changed, revoked or expired, with actor and reason; WS-D task 3) and the network.staff.read capability (list the network's staff and their staff-map capabilities; WS-D task 4)
Changes
@@@ -4,6 +4,10 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) thfrom `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,the notes were in the tag and commit messages (`git tag -n1`).++## 0.47.0 — 2026-09-25++++**`network.grant.changed`** gets its payload contract (roadmap WS-D task 3): a service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired, with actor and reason. Network writes it beside an audit row in the transaction that changes the grant; the seeded defaults are not announced. New capability **`network.staff.read`** (active, first-party, never grantable to apps): list the network's staff with their roles and staff-map capabilities, `GET /api/v1/staff/moderators` (WS-D task 4). Fixtures for a grant and an expiry. Additive.++## 0.46.0 — 2026-09-25**`live.moderation.action`** (ADR-022, roadmap WS-D task 1): a staff or channel-moderator action taken on OpenVibe.Live outside chat (site, global and IP bans, message deletes and purges from the admin panel, a stream force-ended, relay users hidden, channel moderators added or removed), with the same payload as `chat.moderation.action`. Events requires an event's prefix to match its source, so Live cannot send Chat's event for its own admin actions. OpenVibe.Network consumes it into the moderation audit log. The live manifest produces it and the network manifest consumes it. Fixtures cover a site ban and a force-ended stream. Additive.@@@ -927,6 +927,15 @@"compatibility": "backward","status": "active"},++ {++ "id": "network.grant.changed",++ "version": "1.0.0",++ "owner": "network",++ "schema": "events/payloads/network.grant.changed.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },{"id": "network.user.updated","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/network.grant.changed.v1.json",++ "title": "NetworkGrantChangedPayload",++ "description": "network.grant.changed v1 (OpenVibe.Network server/identity/grants-admin.js; roadmap WS-D task 3). A service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired. The seeded default grants are not announced. Written to Network's outbox in the transaction that changes principal_grants, beside an audit row. A service's next token (at most 5 minutes later) carries the change. Envelope: subject { type: grant, id: <client_id>:<capability>@<audience> }, visibility internal, actor the owner who changed it (or the system for an expiry).",++ "type": "object",++ "required": ["client_id", "capability", "audience", "change"],++ "additionalProperties": false,++ "properties": {++ "client_id": { "type": "string", "pattern": "^[a-z][a-z0-9_-]{0,63}$", "description": "The service principal (oauth client id)." },++ "capability": { "type": "string", "pattern": "^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$" },++ "audience": { "type": "string", "pattern": "^openvibe\\.[a-z][a-z0-9_-]{0,63}$" },++ "change": { "enum": ["granted", "updated", "revoked", "expired"] },++ "namespaces": { "type": "array", "maxItems": 100, "items": { "type": "string", "maxLength": 200 } },++ "expires_at": { "type": ["string", "null"], "format": "date-time" },++ "reason": { "type": ["string", "null"], "maxLength": 500 },++ "actor_subject": { "type": ["string", "null"], "description": "The owner who made the change; null for an expiry." }++ }++}nnew file mode 100644@@@ -0,0 +1 @@++{ "client_id": "live", "capability": "network.modules.write", "audience": "openvibe.network", "change": "deleted" }nnew file mode 100644@@@ -0,0 +1 @@++{ "client_id": "tools", "capability": "media.object.write", "audience": "openvibe.media", "change": "expired", "namespaces": [], "expires_at": "2026-09-25T00:00:00.000Z", "reason": null, "actor_subject": null }nnew file mode 100644@@@ -0,0 +1 @@++{ "client_id": "live", "capability": "network.modules.write", "audience": "openvibe.network", "change": "granted", "namespaces": ["live.profile"], "expires_at": "2026-12-31T00:00:00.000Z", "reason": "profile summaries", "actor_subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ" }@@@ -10334,6 +10334,77 @@}}},++ "network.grant.changed": {++ "version": "1.0.0",++ "owner": "network",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/network.grant.changed.v1.json",++ "title": "NetworkGrantChangedPayload",++ "description": "network.grant.changed v1 (OpenVibe.Network server/identity/grants-admin.js; roadmap WS-D task 3). A service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired. The seeded default grants are not announced. Written to Network's outbox in the transaction that changes principal_grants, beside an audit row. A service's next token (at most 5 minutes later) carries the change. Envelope: subject { type: grant, id: <client_id>:<capability>@<audience> }, visibility internal, actor the owner who changed it (or the system for an expiry).",++ "type": "object",++ "required": [++ "client_id",++ "capability",++ "audience",++ "change"++ ],++ "additionalProperties": false,++ "properties": {++ "client_id": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_-]{0,63}$",++ "description": "The service principal (oauth client id)."++ },++ "capability": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$"++ },++ "audience": {++ "type": "string",++ "pattern": "^openvibe\\.[a-z][a-z0-9_-]{0,63}$"++ },++ "change": {++ "enum": [++ "granted",++ "updated",++ "revoked",++ "expired"++ ]++ },++ "namespaces": {++ "type": "array",++ "maxItems": 100,++ "items": {++ "type": "string",++ "maxLength": 200++ }++ },++ "expires_at": {++ "type": [++ "string",++ "null"++ ],++ "format": "date-time"++ },++ "reason": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 500++ },++ "actor_subject": {++ "type": [++ "string",++ "null"++ ],++ "description": "The owner who made the change; null for an expiry."++ }++ }++ }++ },"network.user.updated": {"version": "1.0.0","owner": "network",@@@ -9467,6 +9467,30 @@ export interface NetworkModuleUpdatedPayload {};}++/** [email protected] (owner: network) */++/**++ * network.grant.changed v1 (OpenVibe.Network server/identity/grants-admin.js; roadmap WS-D task 3). A service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired. The seeded default grants are not announced. Written to Network's outbox in the transaction that changes principal_grants, beside an audit row. A service's next token (at most 5 minutes later) carries the change. Envelope: subject { type: grant, id: <client_id>:<capability>@<audience> }, visibility internal, actor the owner who changed it (or the system for an expiry).++ */++export interface NetworkGrantChangedPayload {++ /**++ * The service principal (oauth client id).++ */++ client_id: string;++ capability: string;++ audience: string;++ change: "granted" | "updated" | "revoked" | "expired";++ /**++ * @maxItems 100++ */++ namespaces?: string[];++ expires_at?: string | null;++ reason?: string | null;++ /**++ * The owner who made the change; null for an expiry.++ */++ actor_subject?: string | null;++}++/** [email protected] (owner: network) *//*** network.user.updated v1 (OpenVibe.Network server/identity/profile-events.js; roadmap WS-B task 2). What other services may know about a person changed: their username, display name, picture, colour, role or ban. The payload is the person's whole current profile, not a diff, so a consumer keeps a projection by writing it over the one it has, and ignores one whose revision is not newer (events can arrive out of order). Emitted in the transaction of the change: a profile edit, a rename, a role grant or removal, a ban or unban. Consumers use it instead of their own copies: roles go both ways (a downgrade too), and a ban arrives even for someone who never comes back. Envelope: subject { type: user, id }, visibility internal, actor the person (their own edit) or the staff member.nnew file mode 100644@@@ -0,0 +1,17 @@++{++ "id": "network.staff.read",++ "version": "1.0",++ "owner": "network",++ "status": "active",++ "visibility": "first-party",++ "description": "List the network's staff (global moderators, admins and the owner) with their roles and staff capabilities from the staff map, as an owning service: to show who moderates, or to route a report. Never grantable to apps.",++ "permissions": [++ "staff:read"++ ],++ "resourceConstraints": [],++ "quotaClass": "staff-read",++ "events": [],++ "implementedBy": [++ "GET /api/v1/staff/moderators"++ ]++}@@@ -42,7 +42,8 @@"network.modules.write","network.notifications.push","network.project.manage",-- "network.project.read"++ "network.project.read",++ "network.staff.read"],"eventsProduced": ["network.app.created",@@@ -1,12 +1,12 @@{"name": "openvibe-contracts",-- "version": "0.46.0",++ "version": "0.47.0","lockfileVersion": 3,"requires": true,"packages": {"": {"name": "openvibe-contracts",-- "version": "0.46.0",++ "version": "0.47.0","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.46.0",++ "version": "0.47.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",
@@ -4,6 +4,10 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
@@ -4,6 +4,10 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
the notes were in the tag and commit messages (`git tag -n1`).
+## 0.47.0 — 2026-09-25
+
+**`network.grant.changed`** gets its payload contract (roadmap WS-D task 3): a service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired, with actor and reason. Network writes it beside an audit row in the transaction that changes the grant; the seeded defaults are not announced. New capability **`network.staff.read`** (active, first-party, never grantable to apps): list the network's staff with their roles and staff-map capabilities, `GET /api/v1/staff/moderators` (WS-D task 4). Fixtures for a grant and an expiry. Additive.
+
## 0.46.0 — 2026-09-25
## 0.46.0 — 2026-09-25
**`live.moderation.action`** (ADR-022, roadmap WS-D task 1): a staff or channel-moderator action taken on OpenVibe.Live outside chat (site, global and IP bans, message deletes and purges from the admin panel, a stream force-ended, relay users hidden, channel moderators added or removed), with the same payload as `chat.moderation.action`. Events requires an event's prefix to match its source, so Live cannot send Chat's event for its own admin actions. OpenVibe.Network consumes it into the moderation audit log. The live manifest produces it and the network manifest consumes it. Fixtures cover a site ban and a force-ended stream. Additive.
**`live.moderation.action`** (ADR-022, roadmap WS-D task 1): a staff or channel-moderator action taken on OpenVibe.Live outside chat (site, global and IP bans, message deletes and purges from the admin panel, a stream force-ended, relay users hidden, channel moderators added or removed), with the same payload as `chat.moderation.action`. Events requires an event's prefix to match its source, so Live cannot send Chat's event for its own admin actions. OpenVibe.Network consumes it into the moderation audit log. The live manifest produces it and the network manifest consumes it. Fixtures cover a site ban and a force-ended stream. Additive.
@@ -927,6 +927,15 @@
@@ -927,6 +927,15 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "network.grant.changed",
+ "version": "1.0.0",
+ "owner": "network",
+ "schema": "events/payloads/network.grant.changed.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
{
{
"id": "network.user.updated",
"id": "network.user.updated",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/network.grant.changed.v1.json",
+ "title": "NetworkGrantChangedPayload",
+ "description": "network.grant.changed v1 (OpenVibe.Network server/identity/grants-admin.js; roadmap WS-D task 3). A service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired. The seeded default grants are not announced. Written to Network's outbox in the transaction that changes principal_grants, beside an audit row. A service's next token (at most 5 minutes later) carries the change. Envelope: subject { type: grant, id: <client_id>:<capability>@<audience> }, visibility internal, actor the owner who changed it (or the system for an expiry).",
+ "type": "object",
+ "required": ["client_id", "capability", "audience", "change"],
+ "additionalProperties": false,
+ "properties": {
+ "client_id": { "type": "string", "pattern": "^[a-z][a-z0-9_-]{0,63}$", "description": "The service principal (oauth client id)." },
+ "capability": { "type": "string", "pattern": "^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$" },
+ "audience": { "type": "string", "pattern": "^openvibe\\.[a-z][a-z0-9_-]{0,63}$" },
+ "change": { "enum": ["granted", "updated", "revoked", "expired"] },
+ "namespaces": { "type": "array", "maxItems": 100, "items": { "type": "string", "maxLength": 200 } },
+ "expires_at": { "type": ["string", "null"], "format": "date-time" },
+ "reason": { "type": ["string", "null"], "maxLength": 500 },
+ "actor_subject": { "type": ["string", "null"], "description": "The owner who made the change; null for an expiry." }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{ "client_id": "live", "capability": "network.modules.write", "audience": "openvibe.network", "change": "deleted" }
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{ "client_id": "tools", "capability": "media.object.write", "audience": "openvibe.media", "change": "expired", "namespaces": [], "expires_at": "2026-09-25T00:00:00.000Z", "reason": null, "actor_subject": null }
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{ "client_id": "live", "capability": "network.modules.write", "audience": "openvibe.network", "change": "granted", "namespaces": ["live.profile"], "expires_at": "2026-12-31T00:00:00.000Z", "reason": "profile summaries", "actor_subject": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ" }
@@ -10334,6 +10334,77 @@
@@ -10334,6 +10334,77 @@
}
}
}
}
},
},
+ "network.grant.changed": {
+ "version": "1.0.0",
+ "owner": "network",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/network.grant.changed.v1.json",
+ "title": "NetworkGrantChangedPayload",
+ "description": "network.grant.changed v1 (OpenVibe.Network server/identity/grants-admin.js; roadmap WS-D task 3). A service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired. The seeded default grants are not announced. Written to Network's outbox in the transaction that changes principal_grants, beside an audit row. A service's next token (at most 5 minutes later) carries the change. Envelope: subject { type: grant, id: <client_id>:<capability>@<audience> }, visibility internal, actor the owner who changed it (or the system for an expiry).",
+ "type": "object",
+ "required": [
+ "client_id",
+ "capability",
+ "audience",
+ "change"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "client_id": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_-]{0,63}$",
+ "description": "The service principal (oauth client id)."
+ },
+ "capability": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*$"
+ },
+ "audience": {
+ "type": "string",
+ "pattern": "^openvibe\\.[a-z][a-z0-9_-]{0,63}$"
+ },
+ "change": {
+ "enum": [
+ "granted",
+ "updated",
+ "revoked",
+ "expired"
+ ]
+ },
+ "namespaces": {
+ "type": "array",
+ "maxItems": 100,
+ "items": {
+ "type": "string",
+ "maxLength": 200
+ }
+ },
+ "expires_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time"
+ },
+ "reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 500
+ },
+ "actor_subject": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The owner who made the change; null for an expiry."
+ }
+ }
+ }
+ },
"network.user.updated": {
"network.user.updated": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "network",
"owner": "network",
@@ -9467,6 +9467,30 @@ export interface NetworkModuleUpdatedPayload {
@@ -9467,6 +9467,30 @@ export interface NetworkModuleUpdatedPayload {
};
};
}
}
+/** [email protected] (owner: network) */
+/**
+ * network.grant.changed v1 (OpenVibe.Network server/identity/grants-admin.js; roadmap WS-D task 3). A service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired. The seeded default grants are not announced. Written to Network's outbox in the transaction that changes principal_grants, beside an audit row. A service's next token (at most 5 minutes later) carries the change. Envelope: subject { type: grant, id: <client_id>:<capability>@<audience> }, visibility internal, actor the owner who changed it (or the system for an expiry).
+ */
+export interface NetworkGrantChangedPayload {
+ /**
+ * The service principal (oauth client id).
+ */
+ client_id: string;
+ capability: string;
+ audience: string;
+ change: "granted" | "updated" | "revoked" | "expired";
+ /**
+ * @maxItems 100
+ */
+ namespaces?: string[];
+ expires_at?: string | null;
+ reason?: string | null;
+ /**
+ * The owner who made the change; null for an expiry.
+ */
+ actor_subject?: string | null;
+}
+
/** [email protected] (owner: network) */
/** [email protected] (owner: network) */
/**
/**
* network.user.updated v1 (OpenVibe.Network server/identity/profile-events.js; roadmap WS-B task 2). What other services may know about a person changed: their username, display name, picture, colour, role or ban. The payload is the person's whole current profile, not a diff, so a consumer keeps a projection by writing it over the one it has, and ignores one whose revision is not newer (events can arrive out of order). Emitted in the transaction of the change: a profile edit, a rename, a role grant or removal, a ban or unban. Consumers use it instead of their own copies: roles go both ways (a downgrade too), and a ban arrives even for someone who never comes back. Envelope: subject { type: user, id }, visibility internal, actor the person (their own edit) or the staff member.
* network.user.updated v1 (OpenVibe.Network server/identity/profile-events.js; roadmap WS-B task 2). What other services may know about a person changed: their username, display name, picture, colour, role or ban. The payload is the person's whole current profile, not a diff, so a consumer keeps a projection by writing it over the one it has, and ignores one whose revision is not newer (events can arrive out of order). Emitted in the transaction of the change: a profile edit, a rename, a role grant or removal, a ban or unban. Consumers use it instead of their own copies: roles go both ways (a downgrade too), and a ban arrives even for someone who never comes back. Envelope: subject { type: user, id }, visibility internal, actor the person (their own edit) or the staff member.
new file mode 100644
new file mode 100644
@@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
+{
+ "id": "network.staff.read",
+ "version": "1.0",
+ "owner": "network",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "List the network's staff (global moderators, admins and the owner) with their roles and staff capabilities from the staff map, as an owning service: to show who moderates, or to route a report. Never grantable to apps.",
+ "permissions": [
+ "staff:read"
+ ],
+ "resourceConstraints": [],
+ "quotaClass": "staff-read",
+ "events": [],
+ "implementedBy": [
+ "GET /api/v1/staff/moderators"
+ ]
+}
@@ -42,7 +42,8 @@
@@ -42,7 +42,8 @@
"network.modules.write",
"network.modules.write",
"network.notifications.push",
"network.notifications.push",
"network.project.manage",
"network.project.manage",
- "network.project.read"
+ "network.project.read",
+ "network.staff.read"
],
],
"eventsProduced": [
"eventsProduced": [
"network.app.created",
"network.app.created",
@@ -1,12 +1,12 @@
@@ -1,12 +1,12 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.46.0",
+ "version": "0.47.0",
"lockfileVersion": 3,
"lockfileVersion": 3,
"requires": true,
"requires": true,
"packages": {
"packages": {
"": {
"": {
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.46.0",
+ "version": "0.47.0",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.46.0",
+ "version": "0.47.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
"types": "generated/typescript/index.d.ts",