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
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
signal_id | string | yes |
| |
entity_id | string | yes | The entity the signal is attributed to (never rewritten by a merge). |
|
canonical_entity_id | string | yes | The entity it currently counts under: entity_id, or the entity it is merged into. |
|
type | enum | yes |
| |
source_key | string | yes | OpenVibe.Sources source key. |
|
source_item_id | string | yes |
| |
item_revision | integer | yes | The Sources item revision the signal was read from. |
|
observed_at | string | yes | When Sources retrieved that item revision (provenance.retrieved_at). |
|
source_published_at | string | null | yes | The item's published_at as Sources gave it; null when it gave none. | |
canonical_url | string | null | yes | The item's canonical URL as Sources gave it; null when it has none. | |
license_note | string | null | yes | Licence note recorded for the item in Sources; null when none. | |
recommended | boolean | recommendation only: whether the reviewer recommends it. | ||
positive_count | integer | recommendation_tally only: positive reviews the source counts. |
| |
total_count | integer | recommendation_tally only: all reviews the source counts (≥ positive_count). |
| |
rating_value | number | rating and rating_aggregate only: the value as stated. | ||
rating_best | number | null | rating and rating_aggregate only: top of the stated scale; null when the source states none. | ||
rating_worst | number | null | rating and rating_aggregate only: bottom of the stated scale; null when the source states none. | ||
rating_count | integer | rating and rating_aggregate only: ratings behind the value (1 for a single review). |
| |
replaces | string | Present when this signal replaced the item's previous active signal (see reviews.signal.removed). |
|
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 }] }