openvibers/openvibe.contracts Commits
v0.21.0: OpenVibe.News is alpha (news.* capabilities)
Changes
nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "id": "news.cluster.manage",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Merge clusters, split items into a new cluster, and reverse a merge or split. Every change is audited with exactly which items moved.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [++ "news.cluster.updated"++ ],++ "implementedBy": [++ "POST /api/v1/clusters/:id/merge",++ "POST /api/v1/clusters/:id/split",++ "POST /api/v1/clusters/audit/:auditId/reverse"++ ]++}nnew file mode 100644@@@ -0,0 +1,22 @@++{++ "id": "news.cluster.read",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Read clusters (members, the stored explanation of every membership, merge/split history), source items with their dedupe outcome, and ingestion runs and source health.",++ "permissions": [++ "news:read"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-read",++ "events": [],++ "implementedBy": [++ "GET /api/v1/clusters",++ "GET /api/v1/clusters/:id",++ "GET /api/v1/source-items/:id",++ "GET /api/v1/ingest"++ ]++}nnew file mode 100644@@@ -0,0 +1,21 @@++{++ "id": "news.perspective.update",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Create or remove editor-labelled perspective groupings on a story and assign its sources to them. Labels are written by editors, never generated.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [],++ "implementedBy": [++ "POST /api/v1/stories/:id/perspectives",++ "DELETE /api/v1/stories/:id/perspectives/:pid",++ "PUT /api/v1/stories/:id/sources/:item/perspective"++ ]++}nnew file mode 100644@@@ -0,0 +1,20 @@++{++ "id": "news.source.attach",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Attach a source item to a story's source table (numbered, never renumbered) or detach it.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [],++ "implementedBy": [++ "POST /api/v1/stories/:id/sources",++ "DELETE /api/v1/stories/:id/sources/:item"++ ]++}nnew file mode 100644@@@ -0,0 +1,21 @@++{++ "id": "news.story.create",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Open a story from a cluster (the cluster's live, non-duplicate source items become its first sources). Editors only: the service acts for an editor named in X-OV-Subject.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [++ "news.story.created"++ ],++ "implementedBy": [++ "POST /api/v1/stories"++ ]++}nnew file mode 100644@@@ -0,0 +1,26 @@++{++ "id": "news.story.publish",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Publish a revision (refused while it cites no source, rests on a source removed upstream or detached, or is AI-generated/AI-assisted without a person's approval), or unpublish a story. Publishing resolves the upstream flags the revision answers and publishes pending correction/update notes.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [++ "news.story.published",++ "news.story.updated",++ "news.story.unpublished",++ "news.index_document.upserted",++ "news.index_document.deleted"++ ],++ "implementedBy": [++ "POST /api/v1/stories/:id/publish",++ "POST /api/v1/stories/:id/unpublish"++ ]++}nnew file mode 100644@@@ -0,0 +1,22 @@++{++ "id": "news.story.read",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Read any story, including drafts, revisions, diffs, publishability problems and editorial flags. Published stories need no capability.",++ "permissions": [++ "news:read"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-read",++ "events": [],++ "implementedBy": [++ "GET /api/v1/stories/:id",++ "GET /api/v1/stories/:id/revisions",++ "GET /api/v1/stories/:id/revisions/:n",++ "GET /api/v1/stories/:id/diff"++ ]++}nnew file mode 100644@@@ -0,0 +1,22 @@++{++ "id": "news.story.retract",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Retract a published story with a public note. The story stays at its URL with the retraction notice, becomes noindex and leaves sitemaps and Search. Final.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [++ "news.story.retracted",++ "news.index_document.deleted"++ ],++ "implementedBy": [++ "POST /api/v1/stories/:id/retract"++ ]++}nnew file mode 100644@@@ -0,0 +1,21 @@++{++ "id": "news.story.revise",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Save a new immutable revision (headline and paragraphs that each cite attached sources, with the source table, timeline and perspectives snapshotted), add correction/update notes, or request an OpenVibe.AI draft. With X-OV-Origin: ai the revision is AI-generated and cannot be published until a person approves it.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [],++ "implementedBy": [++ "POST /api/v1/stories/:id/revisions",++ "POST /api/v1/stories/:id/ai-drafts",++ "POST /api/v1/stories/:id/flags"++ ]++}nnew file mode 100644@@@ -0,0 +1,20 @@++{++ "id": "news.timeline.update",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Add or remove a story's timeline entries; each entry has a date the source states and rests on one attached source.",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [],++ "implementedBy": [++ "POST /api/v1/stories/:id/timeline",++ "DELETE /api/v1/stories/:id/timeline/:eid"++ ]++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "id": "news.topic.manage",++ "version": "1.0",++ "owner": "news",++ "status": "active",++ "visibility": "first-party",++ "description": "Add a canonical topic (slug and name).",++ "permissions": [++ "news:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "news-write",++ "events": [],++ "implementedBy": [++ "POST /api/v1/topics"++ ]++}@@@ -1,16 +1,52 @@{"version": "0.1.0","contractRanges": {-- "openvibe-contracts": "^0.1.0"++ "openvibe-contracts": ">=0.19.0 <1.0.0"},"id": "news","name": "OpenVibe.News",-- "status": "placeholder",++ "status": "alpha","repository": "OpenVibers/OpenVibe.News",-- "domains": [],-- "capabilities": [],-- "eventsProduced": [],-- "eventsConsumed": [],-- "namespacesOwned": [],-- "notes": "Source-backed stories: clustered coverage, cited summaries, perspectives and timelines. Charter only; no runtime."++ "domains": [++ "openvibe.news"++ ],++ "publicOrigin": "https://openvibe.news",++ "health": "/api/health",++ "ready": "/api/ready",++ "capabilities": [++ "news.story.create",++ "news.story.read",++ "news.story.revise",++ "news.story.publish",++ "news.story.retract",++ "news.cluster.read",++ "news.cluster.manage",++ "news.source.attach",++ "news.timeline.update",++ "news.perspective.update",++ "news.topic.manage"++ ],++ "eventsProduced": [++ "news.source.ingested",++ "news.source.failed",++ "news.cluster.updated",++ "news.story.created",++ "news.story.flagged",++ "news.story.published",++ "news.story.updated",++ "news.story.unpublished",++ "news.story.retracted",++ "news.index_document.upserted",++ "news.index_document.deleted"++ ],++ "eventsConsumed": [++ "sources.item.created",++ "sources.item.updated",++ "sources.item.removed",++ "sources.fetch.failed"++ ],++ "namespacesOwned": [++ "news.*"++ ],++ "notes": "Port 4820. Owns news_topics, news_source_items, news_story_clusters, news_stories, news_story_revisions, news_story_sources, news_perspectives, news_timeline_entries, news_editorial_flags in its own SQLite (openvibe-publishing packages, prefixes news_story and news). Consumes OpenVibe.Sources (sources.item.read, optionally sources.source.read) through an Events subscription (sources.item.*, sources.fetch.failed; events.subscription.manage) and a cursor pull; OpenVibe.Network (SSO, identity.subject.resolve); optionally OpenVibe.AI (ai.run.create, namespace news) for news.summarize_story and news.compare_perspectives drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads news.index_document.* from Events."}@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.20.0",++ "version": "0.21.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",
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "id": "news.cluster.manage",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Merge clusters, split items into a new cluster, and reverse a merge or split. Every change is audited with exactly which items moved.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [
+ "news.cluster.updated"
+ ],
+ "implementedBy": [
+ "POST /api/v1/clusters/:id/merge",
+ "POST /api/v1/clusters/:id/split",
+ "POST /api/v1/clusters/audit/:auditId/reverse"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
+{
+ "id": "news.cluster.read",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Read clusters (members, the stored explanation of every membership, merge/split history), source items with their dedupe outcome, and ingestion runs and source health.",
+ "permissions": [
+ "news:read"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-read",
+ "events": [],
+ "implementedBy": [
+ "GET /api/v1/clusters",
+ "GET /api/v1/clusters/:id",
+ "GET /api/v1/source-items/:id",
+ "GET /api/v1/ingest"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
+{
+ "id": "news.perspective.update",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Create or remove editor-labelled perspective groupings on a story and assign its sources to them. Labels are written by editors, never generated.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [],
+ "implementedBy": [
+ "POST /api/v1/stories/:id/perspectives",
+ "DELETE /api/v1/stories/:id/perspectives/:pid",
+ "PUT /api/v1/stories/:id/sources/:item/perspective"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
+{
+ "id": "news.source.attach",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Attach a source item to a story's source table (numbered, never renumbered) or detach it.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [],
+ "implementedBy": [
+ "POST /api/v1/stories/:id/sources",
+ "DELETE /api/v1/stories/:id/sources/:item"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
+{
+ "id": "news.story.create",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Open a story from a cluster (the cluster's live, non-duplicate source items become its first sources). Editors only: the service acts for an editor named in X-OV-Subject.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [
+ "news.story.created"
+ ],
+ "implementedBy": [
+ "POST /api/v1/stories"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
+{
+ "id": "news.story.publish",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Publish a revision (refused while it cites no source, rests on a source removed upstream or detached, or is AI-generated/AI-assisted without a person's approval), or unpublish a story. Publishing resolves the upstream flags the revision answers and publishes pending correction/update notes.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [
+ "news.story.published",
+ "news.story.updated",
+ "news.story.unpublished",
+ "news.index_document.upserted",
+ "news.index_document.deleted"
+ ],
+ "implementedBy": [
+ "POST /api/v1/stories/:id/publish",
+ "POST /api/v1/stories/:id/unpublish"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
+{
+ "id": "news.story.read",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Read any story, including drafts, revisions, diffs, publishability problems and editorial flags. Published stories need no capability.",
+ "permissions": [
+ "news:read"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-read",
+ "events": [],
+ "implementedBy": [
+ "GET /api/v1/stories/:id",
+ "GET /api/v1/stories/:id/revisions",
+ "GET /api/v1/stories/:id/revisions/:n",
+ "GET /api/v1/stories/:id/diff"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
+{
+ "id": "news.story.retract",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Retract a published story with a public note. The story stays at its URL with the retraction notice, becomes noindex and leaves sitemaps and Search. Final.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [
+ "news.story.retracted",
+ "news.index_document.deleted"
+ ],
+ "implementedBy": [
+ "POST /api/v1/stories/:id/retract"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
+{
+ "id": "news.story.revise",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Save a new immutable revision (headline and paragraphs that each cite attached sources, with the source table, timeline and perspectives snapshotted), add correction/update notes, or request an OpenVibe.AI draft. With X-OV-Origin: ai the revision is AI-generated and cannot be published until a person approves it.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [],
+ "implementedBy": [
+ "POST /api/v1/stories/:id/revisions",
+ "POST /api/v1/stories/:id/ai-drafts",
+ "POST /api/v1/stories/:id/flags"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
+{
+ "id": "news.timeline.update",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Add or remove a story's timeline entries; each entry has a date the source states and rests on one attached source.",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [],
+ "implementedBy": [
+ "POST /api/v1/stories/:id/timeline",
+ "DELETE /api/v1/stories/:id/timeline/:eid"
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "id": "news.topic.manage",
+ "version": "1.0",
+ "owner": "news",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Add a canonical topic (slug and name).",
+ "permissions": [
+ "news:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "news-write",
+ "events": [],
+ "implementedBy": [
+ "POST /api/v1/topics"
+ ]
+}
@@ -1,16 +1,52 @@
@@ -1,16 +1,52 @@
{
{
"version": "0.1.0",
"version": "0.1.0",
"contractRanges": {
"contractRanges": {
- "openvibe-contracts": "^0.1.0"
+ "openvibe-contracts": ">=0.19.0 <1.0.0"
},
},
"id": "news",
"id": "news",
"name": "OpenVibe.News",
"name": "OpenVibe.News",
- "status": "placeholder",
+ "status": "alpha",
"repository": "OpenVibers/OpenVibe.News",
"repository": "OpenVibers/OpenVibe.News",
- "domains": [],
- "capabilities": [],
- "eventsProduced": [],
- "eventsConsumed": [],
- "namespacesOwned": [],
- "notes": "Source-backed stories: clustered coverage, cited summaries, perspectives and timelines. Charter only; no runtime."
+ "domains": [
+ "openvibe.news"
+ ],
+ "publicOrigin": "https://openvibe.news",
+ "health": "/api/health",
+ "ready": "/api/ready",
+ "capabilities": [
+ "news.story.create",
+ "news.story.read",
+ "news.story.revise",
+ "news.story.publish",
+ "news.story.retract",
+ "news.cluster.read",
+ "news.cluster.manage",
+ "news.source.attach",
+ "news.timeline.update",
+ "news.perspective.update",
+ "news.topic.manage"
+ ],
+ "eventsProduced": [
+ "news.source.ingested",
+ "news.source.failed",
+ "news.cluster.updated",
+ "news.story.created",
+ "news.story.flagged",
+ "news.story.published",
+ "news.story.updated",
+ "news.story.unpublished",
+ "news.story.retracted",
+ "news.index_document.upserted",
+ "news.index_document.deleted"
+ ],
+ "eventsConsumed": [
+ "sources.item.created",
+ "sources.item.updated",
+ "sources.item.removed",
+ "sources.fetch.failed"
+ ],
+ "namespacesOwned": [
+ "news.*"
+ ],
+ "notes": "Port 4820. Owns news_topics, news_source_items, news_story_clusters, news_stories, news_story_revisions, news_story_sources, news_perspectives, news_timeline_entries, news_editorial_flags in its own SQLite (openvibe-publishing packages, prefixes news_story and news). Consumes OpenVibe.Sources (sources.item.read, optionally sources.source.read) through an Events subscription (sources.item.*, sources.fetch.failed; events.subscription.manage) and a cursor pull; OpenVibe.Network (SSO, identity.subject.resolve); optionally OpenVibe.AI (ai.run.create, namespace news) for news.summarize_story and news.compare_perspectives drafts; publishes through OpenVibe.Events (events.event.publish); OpenVibe.Search reads news.index_document.* from Events."
}
}
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.20.0",
+ "version": "0.21.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",