IndexDocument search.index-document@1

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

Version
1.0.0
Owner
search
Visibility
first-party
Status
active
Compatibility
backward
Decision
ADR-018
Schema
https://openvibe.network/contracts/search/index-document.v1.json

What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.

Fields

FieldTypeRequiredDescriptionConstraints
ownerstringyesOwning service id (wiki, blog, news, community, sources…). Only that service may write the document.
  • pattern ^[a-z][a-z0-9-]{1,39}$
typestringyesResource type inside the owner (page, post, story, entity, offer, coupon, instrument, item…).
  • pattern ^[a-z][a-z0-9_]{1,39}$
idstringyesResource id inside owner+type. Stable across revisions.
  • pattern ^[A-Za-z0-9][A-Za-z0-9._:~-]{0,127}$
revisionintegeryesOwner's monotonic revision of the resource. An older revision never overwrites a newer one; at equal revision a deletion wins.
  • minimum 0
  • maximum 9007199254740991
deletedbooleanDeletion marker. true = tombstone; every other content field is ignored.
  • default false
visibilityenumpublic: anyone. unlisted: never listed except to ACL matches; fetchable by exact id by a signed-in subject. members: subjects, groups or entitlements in acl. private: subjects in acl.subjects only. draft: never served.
  • one of "public", "unlisted", "members", "private", "draft"
aclobjectWho may see a non-public document. Ignored for public documents. Empty means nobody (for members/private) or direct-id only (for unlisted).
  • no other fields
acl.subjectsarray of string
  • maxItems 200
  • unique items
  • items: pattern ^(usr|gst)_[0-9A-HJKMNP-TV-Z]{26}$
acl.groupsarray of stringOpaque group keys owned by some service, e.g. role:admin (Network role), wiki.space:spc_…:member.
  • maxItems 100
  • unique items
  • items: pattern ^[a-z][a-z0-9_.:-]{0,127}$
acl.entitlementsarray of stringEntitlement keys (VIP/Billing), e.g. vip.plan:pln_…. Only a first-party service that just resolved them may present them for a viewer.
  • maxItems 100
  • unique items
  • items: pattern ^[a-z][a-z0-9_.:-]{0,127}$
canonical_urlstring
  • pattern ^https?://
  • format uri
  • maxLength 2048
titlestring
  • maxLength 500
summarystring
  • maxLength 4000
bodystringPlain text for full-text search (no HTML). Keep it under the Events payload limit when publishing through Events.
  • maxLength 48000
facetsobjectFilterable values (category, tags, space, author subject, currency…). Filter with facet.<key>=<value>.
languagestringBCP 47 tag.
  • pattern ^[a-zA-Z]{2,3}(-[A-Za-z0-9]{2,8})*$
authorshipenum
  • one of "human", "ai_assisted", "ai_generated", "imported"
provenancearray of objectWhere the content came from: typed references to source records (Sources items, citations, Media objects).
  • maxItems 50
  • items: no other fields
provenance[].servicestringyes
  • pattern ^[a-z][a-z0-9-]{1,39}$
provenance[].typestringyes
  • pattern ^[a-z][a-z0-9_]{1,39}$
provenance[].idstringyes
  • minLength 1
  • maxLength 128
provenance[].revisioninteger
  • minimum 0
provenance[].labelstring
  • maxLength 200
provenance[].urlstring
  • pattern ^https?://
  • format uri
  • maxLength 2048
provenance[].retrieved_atstring
  • format date-time
provenance[].stubbooleantrue when the reference came from a stub provider; the document is then never indexable.
publication_stateenumOnly published documents are ever served.
  • one of "draft", "scheduled", "published", "unpublished", "retracted", "archived"
published_atstring | null
  • format date-time
updated_atstring | null
  • format date-time
indexabilityobjectThe owner's deterministic indexability decision (publishing packages, roadmap §32.3). Search can only make it stricter.
  • no other fields
indexability.decisionenumyes
  • one of "index", "noindex"
indexability.reasonsarray of stringKnown reasons: draft, private, members_only, unlisted, not_published, deleted, thin_content, duplicate_without_canonical, unsupported_claims, unsourced, stub_provider, sensitive_unreviewed, ai_unreviewed, missing_canonical_url, third_party_content, owner_decision.
  • maxItems 20
  • unique items
  • items: pattern ^[a-z][a-z0-9_]{1,63}$

Examples

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

Valid: tombstone
{
  "owner": "blog",
  "type": "post",
  "id": "post-42",
  "revision": 7,
  "deleted": true
}
Valid: wiki-page
{
  "owner": "wiki",
  "type": "page",
  "id": "pg_01J0000000000000000000000Z",
  "revision": 3,
  "visibility": "public",
  "canonical_url": "https://openvibe.wiki/w/example",
  "title": "Example page",
  "summary": "A short summary.",
  "body": "Plain text body.",
  "facets": {
    "space": "general",
    "tags": [
      "example"
    ]
  },
  "language": "en",
  "authorship": "human",
  "publication_state": "published",
  "published_at": "2026-09-22T12:00:00Z",
  "indexability": {
    "decision": "index",
    "reasons": []
  },
  "provenance": [
    {
      "service": "sources",
      "type": "item",
      "id": "itm_01J0000000000000000000000Z"
    }
  ]
}
Rejected: bad-visibility
{
  "owner": "wiki",
  "type": "page",
  "id": "x",
  "revision": 1,
  "visibility": "everyone"
}
Rejected: no-revision
{
  "owner": "wiki",
  "type": "page",
  "id": "x"
}

Validate

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