ReviewsSignalAddedPayload reviews.signal.added@1

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

Version
1.0.0
Owner
reviews
Visibility
first-party
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/events/payloads/reviews.signal.added.v1.json

reviews.signal.added v1 (OpenVibe.Reviews server/reviews/service.js createSignal → signalEvent). A typed signal was recorded from one revision of an OpenVibe.Sources review item resolved to an entity (an import through POST /api/v1/signals/import or the Sources sync, a sources.item.created|updated event, or an editor resolving a queued item), in the transaction that stored it. Values and provenance are exactly what the source stated and never change afterwards. When the item already had an active signal (a newer item revision, or an editor reattributing the item), `replaces` names it and the reviews.signal.removed for it is written just before this event. Value fields depend on type: recommended (recommendation), positive_count and total_count (recommendation_tally), rating_value, rating_best, rating_worst and rating_count (rating, rating_aggregate); a scale the source did not state is null, never defaulted. Review text, the signal's trust metadata and the resulting aggregate are left out. Envelope: subject { type: signal, id: <signal_id> }, visibility public, priority important, actor the caller (the importing service, e.g. service:sources-sync, or the editor, user usr_…) or service:reviews for the Sources event consumer and sync worker.

Fields

FieldTypeRequiredDescriptionConstraints
signal_idstringyes
  • pattern ^sig_[0-9A-HJKMNP-TV-Z]{26}$
entity_idstringyesThe entity the signal is attributed to (never rewritten by a merge).
  • pattern ^ent_[0-9A-HJKMNP-TV-Z]{26}$
canonical_entity_idstringyesThe entity it currently counts under: entity_id, or the entity it is merged into.
  • pattern ^ent_[0-9A-HJKMNP-TV-Z]{26}$
typeenumyes
  • one of "recommendation", "recommendation_tally", "rating", "rating_aggregate"
source_keystringyesOpenVibe.Sources source key.
  • pattern ^[a-z0-9][a-z0-9-]{1,63}$
source_item_idstringyes
  • pattern ^itm_[0-9A-HJKMNP-TV-Z]{26}$
item_revisionintegeryesThe Sources item revision the signal was read from.
  • minimum 1
observed_atstringyesWhen Sources retrieved that item revision (provenance.retrieved_at).
  • format date-time
source_published_atstring | nullyesThe item's published_at as Sources gave it; null when it gave none.
canonical_urlstring | nullyesThe item's canonical URL as Sources gave it; null when it has none.
license_notestring | nullyesLicence note recorded for the item in Sources; null when none.
recommendedbooleanrecommendation only: whether the reviewer recommends it.
positive_countintegerrecommendation_tally only: positive reviews the source counts.
  • minimum 0
total_countintegerrecommendation_tally only: all reviews the source counts (≥ positive_count).
  • minimum 0
rating_valuenumberrating and rating_aggregate only: the value as stated.
rating_bestnumber | nullrating and rating_aggregate only: top of the stated scale; null when the source states none.
rating_worstnumber | nullrating and rating_aggregate only: bottom of the stated scale; null when the source states none.
rating_countintegerrating and rating_aggregate only: ratings behind the value (1 for a single review).
  • minimum 1
replacesstringPresent when this signal replaced the item's previous active signal (see reviews.signal.removed).
  • pattern ^sig_[0-9A-HJKMNP-TV-Z]{26}$

Examples

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

Valid: rating-aggregate
{
  "signal_id": "sig_01M38GW33AG2JGY97E8YACRG2G",
  "entity_id": "ent_01M38GW32MMJWAVC9KPYXC759Y",
  "canonical_entity_id": "ent_01M38GW32MMJWAVC9KPYXC759Y",
  "type": "rating_aggregate",
  "source_key": "shop-example",
  "source_item_id": "itm_01M2ZB05BG9JCWV5MRXRD4ZTBG",
  "item_revision": 1,
  "observed_at": "2026-09-20T12:00:06.000Z",
  "source_published_at": null,
  "canonical_url": "https://shop.example/p/widget",
  "license_note": "Product data as published by shop.example",
  "rating_value": 4.2,
  "rating_best": 5,
  "rating_worst": null,
  "rating_count": 120
}
Valid: recommendation
{
  "signal_id": "sig_01M38GW2W9GCC5P6WKXXFVXBQY",
  "entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "canonical_entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "type": "recommendation",
  "source_key": "steam-reviews-portal-2",
  "source_item_id": "itm_01M2ZB00F8E73MN708E0S8WFM0",
  "item_revision": 1,
  "observed_at": "2026-09-20T12:00:01.000Z",
  "source_published_at": "2026-09-01T00:00:00.000Z",
  "canonical_url": null,
  "license_note": null,
  "recommended": true
}
Valid: tally-replaces
{
  "signal_id": "sig_01M38GW33Q3WGNNV0RVRERXSA3",
  "entity_id": "ent_01M38GW372A3PM7110AHHTYM7C",
  "canonical_entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "type": "recommendation_tally",
  "source_key": "steam-reviews-portal-2",
  "source_item_id": "itm_01M2ZB04C8N9TB7GZ9266TR9EY",
  "item_revision": 2,
  "observed_at": "2026-09-20T13:00:05.000Z",
  "source_published_at": "2026-09-01T00:00:00.000Z",
  "canonical_url": null,
  "license_note": null,
  "positive_count": 812,
  "total_count": 1000,
  "replaces": "sig_01M38GW31D8P3PQ89VKPPRBT9T"
}
Rejected: rating-without-value
{
  "signal_id": "sig_01M38GW33AG2JGY97E8YACRG2G",
  "entity_id": "ent_01M38GW32MMJWAVC9KPYXC759Y",
  "canonical_entity_id": "ent_01M38GW32MMJWAVC9KPYXC759Y",
  "type": "rating",
  "source_key": "shop-example",
  "source_item_id": "itm_01M2ZB05BG9JCWV5MRXRD4ZTBG",
  "item_revision": 1,
  "observed_at": "2026-09-20T12:00:06.000Z",
  "source_published_at": null,
  "canonical_url": null,
  "license_note": null,
  "rating_best": 5,
  "rating_worst": 1,
  "rating_count": 1
}
Rejected: recommended-as-integer
{
  "signal_id": "sig_01M38GW2W9GCC5P6WKXXFVXBQY",
  "entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "canonical_entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "type": "recommendation",
  "source_key": "steam-reviews-portal-2",
  "source_item_id": "itm_01M2ZB00F8E73MN708E0S8WFM0",
  "item_revision": 1,
  "observed_at": "2026-09-20T12:00:01.000Z",
  "source_published_at": null,
  "canonical_url": null,
  "license_note": null,
  "recommended": 1
}
Rejected: review-text
{
  "signal_id": "sig_01M38GW2W9GCC5P6WKXXFVXBQY",
  "entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "canonical_entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "type": "recommendation",
  "source_key": "steam-reviews-portal-2",
  "source_item_id": "itm_01M2ZB00F8E73MN708E0S8WFM0",
  "item_revision": 1,
  "observed_at": "2026-09-20T12:00:01.000Z",
  "source_published_at": null,
  "canonical_url": null,
  "license_note": null,
  "recommended": true,
  "text": "Loved every puzzle."
}
Rejected: unknown-type
{
  "signal_id": "sig_01M38GW2W9GCC5P6WKXXFVXBQY",
  "entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "canonical_entity_id": "ent_01M38GW2QD088TQ08VN985JTXT",
  "type": "sentiment",
  "source_key": "steam-reviews-portal-2",
  "source_item_id": "itm_01M2ZB00F8E73MN708E0S8WFM0",
  "item_revision": 1,
  "observed_at": "2026-09-20T12:00:01.000Z",
  "source_published_at": null,
  "canonical_url": null,
  "license_note": null
}

Validate

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