openvibers/openvibe.contracts Commits

v0.44.0: live, media and community index_document.upserted|deleted events (channels; public playable VODs and clips; public threads and pastes) for OpenVibe.Search, with fixtures (WS-O task 10)

OP OpenVibers committed 25 Sept 2026 · 9abe9add60 · 27 files, +579 −5


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 137a6c4b..5001a1df 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -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,
the notes were in the tag and commit messages (`git tag -n1`).
++## 0.44.0 — 2026-09-25
++
++Search documents from three more owners (roadmap WS-O task 10): **`live.index_document.upserted|deleted`** (a streamer's channel page, type `channel`), **`media.index_document.upserted|deleted`** (public, playable VODs and clips, types `vod` and `clip`) and **`community.index_document.upserted|deleted`** (public forum threads and public pastes, types `thread` and `paste`). They use the same shape as the Wiki, Blog, News and other owners' index events: the `search.index-document@1` document, or a tombstone `{ type, id, revision }`. OpenVibe.Search consumes them through `*.index_document.*`. The live, media and community manifests list them. Fixtures cover the Live payloads. Additive.
++
## 0.43.0 — 2026-09-25
**`network.user.updated`** (roadmap WS-B task 2). A person's whole current profile after any change that other services may know about: username, display name, picture, colour, role or ban. The payload carries a `revision` and the list of what `changed` (`created` for a new account). Consumers keep a projection by writing the newest over what they have: roles apply in both directions, and a ban arrives even for someone who never comes back. Network produces it and Live consumes it (Live's `subject_projection`, replacing the `/internal/user-role` push). Fixtures cover valid and invalid payloads. Additive.
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex 3fe5c99a..673971ef 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -387,6 +387,60 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "live.index_document.upserted",
++ "version": "1.0.0",
++ "owner": "live",
++ "schema": "events/payloads/live.index_document.upserted.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "live.index_document.deleted",
++ "version": "1.0.0",
++ "owner": "live",
++ "schema": "events/payloads/live.index_document.deleted.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "media.index_document.upserted",
++ "version": "1.0.0",
++ "owner": "media",
++ "schema": "events/payloads/media.index_document.upserted.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "media.index_document.deleted",
++ "version": "1.0.0",
++ "owner": "media",
++ "schema": "events/payloads/media.index_document.deleted.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "community.index_document.upserted",
++ "version": "1.0.0",
++ "owner": "community",
++ "schema": "events/payloads/community.index_document.upserted.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "community.index_document.deleted",
++ "version": "1.0.0",
++ "owner": "community",
++ "schema": "events/payloads/community.index_document.deleted.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "blog.post.created",
"version": "1.0.0",
ddiff --git a/contracts/events/payloads/community.index_document.deleted.v1.json b/contracts/events/payloads/community.index_document.deleted.v1.json
nnew file mode 100644
iindex 00000000..3cd39be0
---- /dev/null
++++ b/contracts/events/payloads/community.index_document.deleted.v1.json
@@@ -0,0 +1,31 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/community.index_document.deleted.v1.json",
++ "title": "CommunityIndexDocumentDeletedPayload",
++ "description": "community.index_document.deleted v1 (OpenVibe.Community; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:community.",
++ "type": "object",
++ "required": [
++ "type",
++ "id",
++ "revision"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "type": {
++ "enum": [
++ "thread",
++ "paste"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[A-Za-z0-9_-]{1,80}$"
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 9007199254740991,
++ "description": "Index revision of the tombstone; wins over any document at the same or an older revision."
++ }
++ }
++}
ddiff --git a/contracts/events/payloads/community.index_document.upserted.v1.json b/contracts/events/payloads/community.index_document.upserted.v1.json
nnew file mode 100644
iindex 00000000..3313683b
---- /dev/null
++++ b/contracts/events/payloads/community.index_document.upserted.v1.json
@@@ -0,0 +1,37 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/community.index_document.upserted.v1.json",
++ "title": "CommunityIndexDocumentUpsertedPayload",
++ "description": "community.index_document.upserted v1 (OpenVibe.Community; roadmap WS-O task 10). The OpenVibe.Search document of A public forum thread (in a public, open space) or a public paste on openvibe.community. Sent whenever what Search should hold changed; a thread or paste that is deleted, made private or members-only, or burns after reading gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:community.",
++ "allOf": [
++ {
++ "$ref": "../../search/index-document.v1.json"
++ },
++ {
++ "type": "object",
++ "required": [
++ "owner",
++ "type",
++ "deleted"
++ ],
++ "properties": {
++ "owner": {
++ "const": "community"
++ },
++ "type": {
++ "enum": [
++ "thread",
++ "paste"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[A-Za-z0-9_-]{1,80}$"
++ },
++ "deleted": {
++ "const": false
++ }
++ }
++ }
++ ]
++}
ddiff --git a/contracts/events/payloads/live.index_document.deleted.v1.json b/contracts/events/payloads/live.index_document.deleted.v1.json
nnew file mode 100644
iindex 00000000..ada5b7af
---- /dev/null
++++ b/contracts/events/payloads/live.index_document.deleted.v1.json
@@@ -0,0 +1,28 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/live.index_document.deleted.v1.json",
++ "title": "LiveIndexDocumentDeletedPayload",
++ "description": "live.index_document.deleted v1 (OpenVibe.Live server/events/search-documents.js; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:live.",
++ "type": "object",
++ "required": [
++ "type",
++ "id",
++ "revision"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "type": {
++ "const": "channel"
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 9007199254740991,
++ "description": "Index revision of the tombstone; wins over any document at the same or an older revision."
++ }
++ }
++}
ddiff --git a/contracts/events/payloads/live.index_document.upserted.v1.json b/contracts/events/payloads/live.index_document.upserted.v1.json
nnew file mode 100644
iindex 00000000..6befb2a0
---- /dev/null
++++ b/contracts/events/payloads/live.index_document.upserted.v1.json
@@@ -0,0 +1,34 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/live.index_document.upserted.v1.json",
++ "title": "LiveIndexDocumentUpsertedPayload",
++ "description": "live.index_document.upserted v1 (OpenVibe.Live server/events/search-documents.js; roadmap WS-O task 10). The OpenVibe.Search document of A streamer's channel page (openvibe.live/@username): its name, bio, what it streams and whether it is live. Sent whenever what Search should hold changed; a banned channel, or one that stopped streaming for good, gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:live.",
++ "allOf": [
++ {
++ "$ref": "../../search/index-document.v1.json"
++ },
++ {
++ "type": "object",
++ "required": [
++ "owner",
++ "type",
++ "deleted"
++ ],
++ "properties": {
++ "owner": {
++ "const": "live"
++ },
++ "type": {
++ "const": "channel"
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "deleted": {
++ "const": false
++ }
++ }
++ }
++ ]
++}
ddiff --git a/contracts/events/payloads/media.index_document.deleted.v1.json b/contracts/events/payloads/media.index_document.deleted.v1.json
nnew file mode 100644
iindex 00000000..576250db
---- /dev/null
++++ b/contracts/events/payloads/media.index_document.deleted.v1.json
@@@ -0,0 +1,31 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/media.index_document.deleted.v1.json",
++ "title": "MediaIndexDocumentDeletedPayload",
++ "description": "media.index_document.deleted v1 (OpenVibe.Media; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:media.",
++ "type": "object",
++ "required": [
++ "type",
++ "id",
++ "revision"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "type": {
++ "enum": [
++ "vod",
++ "clip"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 9007199254740991,
++ "description": "Index revision of the tombstone; wins over any document at the same or an older revision."
++ }
++ }
++}
ddiff --git a/contracts/events/payloads/media.index_document.upserted.v1.json b/contracts/events/payloads/media.index_document.upserted.v1.json
nnew file mode 100644
iindex 00000000..a07b4d4f
---- /dev/null
++++ b/contracts/events/payloads/media.index_document.upserted.v1.json
@@@ -0,0 +1,37 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/media.index_document.upserted.v1.json",
++ "title": "MediaIndexDocumentUpsertedPayload",
++ "description": "media.index_document.upserted v1 (OpenVibe.Media; roadmap WS-O task 10). The OpenVibe.Search document of A public, playable VOD or clip page on openvibe.media (readiness playable, visibility public). Sent whenever what Search should hold changed; a VOD or clip that is deleted, made private or stops being playable gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:media.",
++ "allOf": [
++ {
++ "$ref": "../../search/index-document.v1.json"
++ },
++ {
++ "type": "object",
++ "required": [
++ "owner",
++ "type",
++ "deleted"
++ ],
++ "properties": {
++ "owner": {
++ "const": "media"
++ },
++ "type": {
++ "enum": [
++ "vod",
++ "clip"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "deleted": {
++ "const": false
++ }
++ }
++ }
++ ]
++}
ddiff --git a/fixtures/community.index_document.deleted/invalid/extra-field.json b/fixtures/community.index_document.deleted/invalid/extra-field.json
nnew file mode 100644
iindex 00000000..2df0f633
---- /dev/null
++++ b/fixtures/community.index_document.deleted/invalid/extra-field.json
@@@ -0,0 +1 @@
++{ "type": "paste", "id": "snip-12", "revision": 2, "reason": "deleted" }
ddiff --git a/fixtures/community.index_document.deleted/valid/paste.json b/fixtures/community.index_document.deleted/valid/paste.json
nnew file mode 100644
iindex 00000000..1680864f
---- /dev/null
++++ b/fixtures/community.index_document.deleted/valid/paste.json
@@@ -0,0 +1 @@
++{ "type": "paste", "id": "snip-12", "revision": 2 }
ddiff --git a/fixtures/community.index_document.upserted/invalid/bad-id.json b/fixtures/community.index_document.upserted/invalid/bad-id.json
nnew file mode 100644
iindex 00000000..97e944ac
---- /dev/null
++++ b/fixtures/community.index_document.upserted/invalid/bad-id.json
@@@ -0,0 +1 @@
++{ "owner": "community", "type": "paste", "id": "no spaces allowed", "revision": 1, "deleted": false, "visibility": "public", "title": "x", "publication_state": "published", "indexability": { "decision": "index" } }
ddiff --git a/fixtures/community.index_document.upserted/valid/thread.json b/fixtures/community.index_document.upserted/valid/thread.json
nnew file mode 100644
iindex 00000000..e4d7f99a
---- /dev/null
++++ b/fixtures/community.index_document.upserted/valid/thread.json
@@@ -0,0 +1 @@
++{ "owner": "community", "type": "thread", "id": "12", "revision": 1, "deleted": false, "visibility": "public", "canonical_url": "https://openvibe.community/s/general/t/welcome", "title": "Welcome", "summary": "Say hi.", "facets": { "space": "general" }, "authorship": "human", "publication_state": "published", "indexability": { "decision": "index" } }
ddiff --git a/fixtures/live.index_document.deleted/invalid/no-revision.json b/fixtures/live.index_document.deleted/invalid/no-revision.json
nnew file mode 100644
iindex 00000000..e7e3ae88
---- /dev/null
++++ b/fixtures/live.index_document.deleted/invalid/no-revision.json
@@@ -0,0 +1 @@
++{ "type": "channel", "id": "42" }
ddiff --git a/fixtures/live.index_document.deleted/valid/tombstone.json b/fixtures/live.index_document.deleted/valid/tombstone.json
nnew file mode 100644
iindex 00000000..115628f0
---- /dev/null
++++ b/fixtures/live.index_document.deleted/valid/tombstone.json
@@@ -0,0 +1 @@
++{ "type": "channel", "id": "42", "revision": 4 }
ddiff --git a/fixtures/live.index_document.upserted/invalid/wrong-type.json b/fixtures/live.index_document.upserted/invalid/wrong-type.json
nnew file mode 100644
iindex 00000000..138b78ec
---- /dev/null
++++ b/fixtures/live.index_document.upserted/invalid/wrong-type.json
@@@ -0,0 +1 @@
++{ "owner": "live", "type": "vod", "id": "42", "revision": 3, "deleted": false, "visibility": "public", "title": "x", "publication_state": "published", "indexability": { "decision": "index" } }
ddiff --git a/fixtures/live.index_document.upserted/valid/channel.json b/fixtures/live.index_document.upserted/valid/channel.json
nnew file mode 100644
iindex 00000000..33d52d6a
---- /dev/null
++++ b/fixtures/live.index_document.upserted/valid/channel.json
@@@ -0,0 +1 @@
++{ "owner": "live", "type": "channel", "id": "42", "revision": 3, "deleted": false, "visibility": "public", "canonical_url": "https://openvibe.live/@alex", "title": "Alex (@alex)", "summary": "Streams builds and games.", "body": "Streams builds and games.\nLast stream: Building a forum", "facets": { "category": "tech", "live": false, "followers": 12 }, "language": "en", "authorship": "human", "publication_state": "published", "published_at": "2026-09-01T10:00:00.000Z", "updated_at": "2026-09-25T19:00:00.000Z", "indexability": { "decision": "index" } }
ddiff --git a/fixtures/media.index_document.deleted/invalid/bad-type.json b/fixtures/media.index_document.deleted/invalid/bad-type.json
nnew file mode 100644
iindex 00000000..7104f9fd
---- /dev/null
++++ b/fixtures/media.index_document.deleted/invalid/bad-type.json
@@@ -0,0 +1 @@
++{ "type": "channel", "id": "396", "revision": 5 }
ddiff --git a/fixtures/media.index_document.deleted/valid/clip.json b/fixtures/media.index_document.deleted/valid/clip.json
nnew file mode 100644
iindex 00000000..416ad59e
---- /dev/null
++++ b/fixtures/media.index_document.deleted/valid/clip.json
@@@ -0,0 +1 @@
++{ "type": "clip", "id": "396", "revision": 5 }
ddiff --git a/fixtures/media.index_document.upserted/invalid/wrong-owner.json b/fixtures/media.index_document.upserted/invalid/wrong-owner.json
nnew file mode 100644
iindex 00000000..1a853448
---- /dev/null
++++ b/fixtures/media.index_document.upserted/invalid/wrong-owner.json
@@@ -0,0 +1 @@
++{ "owner": "live", "type": "vod", "id": "5628", "revision": 2, "deleted": false, "visibility": "public", "title": "x", "publication_state": "published", "indexability": { "decision": "index" } }
ddiff --git a/fixtures/media.index_document.upserted/valid/vod.json b/fixtures/media.index_document.upserted/valid/vod.json
nnew file mode 100644
iindex 00000000..060b7ace
---- /dev/null
++++ b/fixtures/media.index_document.upserted/valid/vod.json
@@@ -0,0 +1 @@
++{ "owner": "media", "type": "vod", "id": "5628", "revision": 2, "deleted": false, "visibility": "public", "canonical_url": "https://openvibe.media/v/5628", "title": "Late night build stream", "summary": "A VOD from alex's channel.", "facets": { "channel": "alex", "duration_seconds": 3600 }, "authorship": "human", "publication_state": "published", "published_at": "2026-09-25T02:00:00.000Z", "indexability": { "decision": "index" } }
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex 8a42a96b..cca82969 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -4187,6 +4187,234 @@
}
}
},
++ "live.index_document.upserted": {
++ "version": "1.0.0",
++ "owner": "live",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/live.index_document.upserted.v1.json",
++ "title": "LiveIndexDocumentUpsertedPayload",
++ "description": "live.index_document.upserted v1 (OpenVibe.Live server/events/search-documents.js; roadmap WS-O task 10). The OpenVibe.Search document of A streamer's channel page (openvibe.live/@username): its name, bio, what it streams and whether it is live. Sent whenever what Search should hold changed; a banned channel, or one that stopped streaming for good, gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:live.",
++ "allOf": [
++ {
++ "$ref": "../../search/index-document.v1.json"
++ },
++ {
++ "type": "object",
++ "required": [
++ "owner",
++ "type",
++ "deleted"
++ ],
++ "properties": {
++ "owner": {
++ "const": "live"
++ },
++ "type": {
++ "const": "channel"
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "deleted": {
++ "const": false
++ }
++ }
++ }
++ ]
++ }
++ },
++ "live.index_document.deleted": {
++ "version": "1.0.0",
++ "owner": "live",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/live.index_document.deleted.v1.json",
++ "title": "LiveIndexDocumentDeletedPayload",
++ "description": "live.index_document.deleted v1 (OpenVibe.Live server/events/search-documents.js; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:live.",
++ "type": "object",
++ "required": [
++ "type",
++ "id",
++ "revision"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "type": {
++ "const": "channel"
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 9007199254740991,
++ "description": "Index revision of the tombstone; wins over any document at the same or an older revision."
++ }
++ }
++ }
++ },
++ "media.index_document.upserted": {
++ "version": "1.0.0",
++ "owner": "media",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/media.index_document.upserted.v1.json",
++ "title": "MediaIndexDocumentUpsertedPayload",
++ "description": "media.index_document.upserted v1 (OpenVibe.Media; roadmap WS-O task 10). The OpenVibe.Search document of A public, playable VOD or clip page on openvibe.media (readiness playable, visibility public). Sent whenever what Search should hold changed; a VOD or clip that is deleted, made private or stops being playable gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:media.",
++ "allOf": [
++ {
++ "$ref": "../../search/index-document.v1.json"
++ },
++ {
++ "type": "object",
++ "required": [
++ "owner",
++ "type",
++ "deleted"
++ ],
++ "properties": {
++ "owner": {
++ "const": "media"
++ },
++ "type": {
++ "enum": [
++ "vod",
++ "clip"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "deleted": {
++ "const": false
++ }
++ }
++ }
++ ]
++ }
++ },
++ "media.index_document.deleted": {
++ "version": "1.0.0",
++ "owner": "media",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/media.index_document.deleted.v1.json",
++ "title": "MediaIndexDocumentDeletedPayload",
++ "description": "media.index_document.deleted v1 (OpenVibe.Media; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:media.",
++ "type": "object",
++ "required": [
++ "type",
++ "id",
++ "revision"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "type": {
++ "enum": [
++ "vod",
++ "clip"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[0-9]{1,15}$"
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 9007199254740991,
++ "description": "Index revision of the tombstone; wins over any document at the same or an older revision."
++ }
++ }
++ }
++ },
++ "community.index_document.upserted": {
++ "version": "1.0.0",
++ "owner": "community",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/community.index_document.upserted.v1.json",
++ "title": "CommunityIndexDocumentUpsertedPayload",
++ "description": "community.index_document.upserted v1 (OpenVibe.Community; roadmap WS-O task 10). The OpenVibe.Search document of A public forum thread (in a public, open space) or a public paste on openvibe.community. Sent whenever what Search should hold changed; a thread or paste that is deleted, made private or members-only, or burns after reading gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:community.",
++ "allOf": [
++ {
++ "$ref": "../../search/index-document.v1.json"
++ },
++ {
++ "type": "object",
++ "required": [
++ "owner",
++ "type",
++ "deleted"
++ ],
++ "properties": {
++ "owner": {
++ "const": "community"
++ },
++ "type": {
++ "enum": [
++ "thread",
++ "paste"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[A-Za-z0-9_-]{1,80}$"
++ },
++ "deleted": {
++ "const": false
++ }
++ }
++ }
++ ]
++ }
++ },
++ "community.index_document.deleted": {
++ "version": "1.0.0",
++ "owner": "community",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/community.index_document.deleted.v1.json",
++ "title": "CommunityIndexDocumentDeletedPayload",
++ "description": "community.index_document.deleted v1 (OpenVibe.Community; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:community.",
++ "type": "object",
++ "required": [
++ "type",
++ "id",
++ "revision"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "type": {
++ "enum": [
++ "thread",
++ "paste"
++ ]
++ },
++ "id": {
++ "type": "string",
++ "pattern": "^[A-Za-z0-9_-]{1,80}$"
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 9007199254740991,
++ "description": "Index revision of the tombstone; wins over any document at the same or an older revision."
++ }
++ }
++ }
++ },
"blog.post.created": {
"version": "1.0.0",
"owner": "blog",
ddiff --git a/generated/typescript/index.d.ts b/generated/typescript/index.d.ts
iindex 880878c2..51c224e1 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -6699,6 +6699,78 @@ export interface WikiIndexDocumentDeletedPayload {
revision: number;
}
++/** [email protected] (owner: live) */
++/**
++ * live.index_document.upserted v1 (OpenVibe.Live server/events/search-documents.js; roadmap WS-O task 10). The OpenVibe.Search document of A streamer's channel page (openvibe.live/@username): its name, bio, what it streams and whether it is live. Sent whenever what Search should hold changed; a banned channel, or one that stopped streaming for good, gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:live.
++ */
++export type LiveIndexDocumentUpsertedPayload = IndexDocument & {
++ owner: "live";
++ type: "channel";
++ id?: string;
++ deleted: false;
++};
++
++/** [email protected] (owner: live) */
++/**
++ * live.index_document.deleted v1 (OpenVibe.Live server/events/search-documents.js; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:live.
++ */
++export interface LiveIndexDocumentDeletedPayload {
++ type: "channel";
++ id: string;
++ /**
++ * Index revision of the tombstone; wins over any document at the same or an older revision.
++ */
++ revision: number;
++}
++
++/** [email protected] (owner: media) */
++/**
++ * media.index_document.upserted v1 (OpenVibe.Media; roadmap WS-O task 10). The OpenVibe.Search document of A public, playable VOD or clip page on openvibe.media (readiness playable, visibility public). Sent whenever what Search should hold changed; a VOD or clip that is deleted, made private or stops being playable gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:media.
++ */
++export type MediaIndexDocumentUpsertedPayload = IndexDocument & {
++ owner: "media";
++ type: "vod" | "clip";
++ id?: string;
++ deleted: false;
++};
++
++/** [email protected] (owner: media) */
++/**
++ * media.index_document.deleted v1 (OpenVibe.Media; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:media.
++ */
++export interface MediaIndexDocumentDeletedPayload {
++ type: "vod" | "clip";
++ id: string;
++ /**
++ * Index revision of the tombstone; wins over any document at the same or an older revision.
++ */
++ revision: number;
++}
++
++/** [email protected] (owner: community) */
++/**
++ * community.index_document.upserted v1 (OpenVibe.Community; roadmap WS-O task 10). The OpenVibe.Search document of A public forum thread (in a public, open space) or a public paste on openvibe.community. Sent whenever what Search should hold changed; a thread or paste that is deleted, made private or members-only, or burns after reading gets a tombstone. The revision grows with every change. Consumed by OpenVibe.Search ('*.index_document.*'). Envelope: subject { type, id, revision: <document revision> }, visibility internal, actor service:community.
++ */
++export type CommunityIndexDocumentUpsertedPayload = IndexDocument & {
++ owner: "community";
++ type: "thread" | "paste";
++ id?: string;
++ deleted: false;
++};
++
++/** [email protected] (owner: community) */
++/**
++ * community.index_document.deleted v1 (OpenVibe.Community; roadmap WS-O task 10). A Search tombstone: Search drops the document at this revision or older. Only sent for a document Search was sent before. Envelope: subject { type, id, revision }, visibility internal, actor service:community.
++ */
++export interface CommunityIndexDocumentDeletedPayload {
++ type: "thread" | "paste";
++ id: string;
++ /**
++ * Index revision of the tombstone; wins over any document at the same or an older revision.
++ */
++ revision: number;
++}
++
/** [email protected] (owner: blog) */
/**
* blog.post.created v1 (OpenVibe.Blog server/domain/posts.js create). A post exists as a draft (its first revision). Envelope: subject { type: post, id: pst_…, revision: 1 }, visibility internal, priority low, actor the person or the calling service.
ddiff --git a/manifests/services/community.json b/manifests/services/community.json
iindex ae60d1ba..a2ff532d 100644
---- a/manifests/services/community.json
++++ b/manifests/services/community.json
@@@ -28,6 +28,8 @@
],
"eventsProduced": [
"community.comment.created",
++ "community.index_document.deleted",
++ "community.index_document.upserted",
"community.moderation.action",
"community.paste.created",
"community.paste.deleted",
ddiff --git a/manifests/services/live.json b/manifests/services/live.json
iindex 36030977..7f78ac9d 100644
---- a/manifests/services/live.json
++++ b/manifests/services/live.json
@@@ -40,9 +40,11 @@
"live.owner.resolve"
],
"eventsProduced": [
-- "live.stream.started",
++ "live.index_document.deleted",
++ "live.index_document.upserted",
++ "live.release.deployed",
"live.stream.ended",
-- "live.release.deployed"
++ "live.stream.started"
],
"eventsConsumed": [
"media.clip.*",
ddiff --git a/manifests/services/media.json b/manifests/services/media.json
iindex 26460a57..96c98a9c 100644
---- a/manifests/services/media.json
++++ b/manifests/services/media.json
@@@ -38,6 +38,8 @@
"eventsProduced": [
"media.clip.failed",
"media.clip.ready",
++ "media.index_document.deleted",
++ "media.index_document.upserted",
"media.job.cancelled",
"media.job.failed",
"media.job.proposed",
ddiff --git a/package-lock.json b/package-lock.json
iindex f7fd8b2a..30f0876b 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-contracts",
-- "version": "0.43.0",
++ "version": "0.44.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-contracts",
-- "version": "0.43.0",
++ "version": "0.44.0",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 9840ee77..03ec5f37 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.43.0",
++ "version": "0.44.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",