openvibers/openvibe.contracts CHANGELOG.md

CHANGELOG.md

main 419.8 KB · 5055 lines · markdown

1# Changelog
2
3## 0.426.0 — 2026-11-13
4
5**A benchmark run that did not measure cost, time or tokens says so** (plan 2026-11-13 §X, "missing stays missing";
6an outside review found Bench's importers and mirror writing 0 for what they never had). `bench.run@2`: `cost_usd`,
7`ms` and `tokens` may be null, on the run and on each task; null means not measured, never 0. Bench #237 already stores
8null; 91 mirrored production runs were corrected from 0 to unknown on 11-13. Fixtures: valid
9`unmeasured-cost-time-tokens`, invalid `negative-cost`.
10
11## 0.425.0 — 2026-11-13
12
13**A feed card says who posted it and what a deal costs** (the owner, 11-13: "it should say who posted it, and it
14should show like … their level … more details of the user … their username effects"; "update the listings for
15deals"). `feed.item@1` 1.1.0, every new field optional:
16
17- `actor.handle` (the username, no @), `actor.level` (null when the person hides it) and `actor.fx` (the name effect
18 they wear, an Inventory token such as `name-fx-rainbow`, looked up by the feed's server so no site needs Inventory in
19 its connect-src; Shared's items.css draws it).
20- `group.items[].price` (`{ amount, currency }`), `was` and `store`: a folded run of deals lists each with its price,
21 its old price and where it is sold.
22- Fixtures: `person-handle-level`, `deal-group-prices`; invalid `level-zero`, `price-currency-lowercase`, `fx-not-a-token`.
23
24## 0.424.0 — 2026-11-13
25
26**Agents have souls** (actor-characters.md; Design rules 175 `actor-is-the-work`, 176 `souls-grow-by-yes`). The owner,
2711-13: "you should have different bots … how you make each character and they each have a soul … your agents are
28created based on your memories and personality".
29
30- **`agents.soul@1`** (`contracts/agents/soul.v1.json`): who an agent is in plain words: `who` (one line), four `dials`
31 (warmth, play, length, edge, each -2 to 2), up to three `quirks`, up to five things it `believes`, how it does
32 `pushback`, what it will `never` do beyond the floor, free `notes` (an imported SOUL.md's body), and how it was
33 `made_from` (words, memories, gallery, twin, soul-md). It shapes the words, never the permissions, and holds no
34 memory of a person: a copy carries the soul, never what was learned.
35- **`agents.blueprint@1`** gains an optional `soul` part (after `face`), by reference. Additive: every blueprint that was
36 valid still is.
37- Fixtures: three valid souls; five invalid (a dial past two, six beliefs, no who, an unknown origin, a permission in
38 the soul).
39
40## 0.423.0 — 2026-11-13
41
42- **Media lists `media.config.manage`** among the capabilities it enforces: Media now serves its settings to the owner's
43 Setup at `/internal/config` (Media #441), so Network's setup and guide read it like every other service (the guide
44 said "OpenVibe.Media did not answer"). The capability itself has existed since the owner settings proxy.
45
46## 0.422.0 — 2026-11-13
47
48**One evaluation loop: entrants, matches, and ratings that separate the model from the harness**
49(compare-arena-ecosystem.md). The owner, 11-13: the Arena "should still use our multi purpose shared universal agentic
50multi harness system", and comparisons should do "harness vs harness and model vs model … better".
51
52- **`bench.entrant@1`:** what competes.
53 - Kinds: a `model` (on the neutral harness), a `harness` (over a fixed model panel), an `agent` (harness + model +
54 settings, a blueprint version), or a `product`.
55 - Stable ids: `model:…`, `harness:…@version`, `agent:harness+model#confighash`, `product:…`.
56- **`bench.match@1`:** one task given to two or more entrants under the same budget.
57 - Each side carries its receipts: cost, tokens, TTFT, TPS, wall time, tool calls, and the length and markdown style
58 covariates.
59 - `shown` records the order the sides were displayed in; `blind` records whether names were hidden.
60 - Judgements come from `human_pairwise`, `audience_poll`, `implicit` (merged, accepted, copied, kept, retried,
61 stopped, edited), `test_suite`, `rubric` and `game_outcome`. A voter is a keyed hash with a quality weight, never
62 an id.
63 - Sources: arena, chat, codes, live, games, exchange, space, bench and check jobs.
64- **`bench.rating@1` 1.1.0** (all optional):
65 - `entrant_kind` and `style_control`;
66 - `factors`: an agent's strength split into model, harness and interaction, each with an interval;
67 - `cost_per_solved_usd`, `tokens_per_task`, `ttft_ms` and `tps` percentiles, `reliability` (pass^k), `matches`,
68 `as_of`.
69- **Event `bench.match.recorded` v1**, produced by Bench.
70- **`agents.play@1` 1.1.0:** `blind` hides the roles' names until the first judgement. This is the race play an Arena
71 round runs on the agent engine.
72- **Fixtures:**
73 - entrants: an agent, a harness, a model;
74 - matches: an Arena vote, and a Codes race judged by its tests and then merged;
75 - a rating with its factors;
76 - invalid: an agent without its harness, a kind nobody has, a one-sided match, an unknown judge.
77
78## 0.421.0 — 2026-11-12
79
80**Every AI call, measured everywhere** (ai-metrics.md).
81
82- **`ai.call.recorded@1` 1.1.0** adds, all optional:
83 - `operation` (chat, completion, embedding, image, image edit, speech, transcription, translation, rerank,
84 moderation, decision, realtime, batch, tool);
85 - `streamed`, and `tps` (the decode speed after the first token);
86 - `queue_ms`;
87 - `task`, `task_id` and `task_ms`, so cost and time add up per task;
88 - `harness`, and `place` (provider, the person's machine, community, a plan, OpenVibe's hosts);
89 - `error_class`, `fallbacks` and `cache_hit` (an exact-cache answer);
90 - `tool_calls` and `region`.
91- **`ai.call-report@1`:** up to 100 calls a product made without OpenVibe.AI (Actor, Codes harness turns, Link's local
92 models through Bot, Vibe). They go to AI's `POST /api/v1/usage/calls`. AI prices any that bring no price, records
93 each once (by system + run or turn id) and publishes `ai.call.recorded@1`. The capability is `ai.usage.report`.
94- **`report.ai-performance@1`:** how calls performed for one group (model, provider, operation, system, task, place,
95 harness):
96 - success, fallback, streamed and cache-hit rates;
97 - TTFT, latency and tokens per second at p50, p90 and p95;
98 - tokens, charged and list cost, and cache savings;
99 - cost and time per task;
100 - the top errors.
101
102 Public answers group by model, provider or operation, with at least 20 calls.
103
104## 0.420.0 — 2026-11-12
105
106**One agent system, measured.** These contracts carry the decisions in `one-system-v2.md`, which come from reading 24
107open agent projects.
108
109- **`agents.blueprint@1` 1.1.0:**
110 - `rules.sandbox` (read-only · workspace-write · full) and `rules.network` (none · public · listed domains): Codex's
111 three axes per run, next to the level that was already there.
112 - `starters`: one-tap first asks, Goose's activities.
113- **`agents.permission-rule@1`:** a permission as data, from Gemini CLI and OpenCode.
114 - It has an action (a tool, or a pattern), a resource, an effect (allow · ask · deny), and `when`: attended,
115 unattended or any.
116 - The last rule that matches wins.
117 - Unattended work never waits on an ask.
118 - The floor asks whatever a rule says.
119- **`agents.job@1`:** one job placed on a machine. Its kinds are check, review, build, eval, improve, desk and model.
120 It carries:
121 - what it needs from the place, and its trust (public code only, or the owner's own machines);
122 - its budget, its placement with the reason, and its attempts;
123 - a result with a named exit and a link to the masked log.
124
125 Secrets never travel in a job.
126- **`agents.run@1` 1.4.0:** `metrics`, with:
127 - the charged cost first (an estimate only where nothing was charged);
128 - tokens with cache reads and writes, latency and steps;
129 - a named exit;
130 - the checkable evidence of success (a test, a schema, a grader, a person, a Decision with its probability).
131- **Fixtures:** a blueprint with sandbox, network and starters; three rules; a check placed on a shared node, and a
132 queued review; a run with metrics; and refusals for each.
133
134## 0.419.1 — 2026-11-12
135
136**`actor.agent.manage` lists the blueprint routes** Actor serves: the person's blueprints and the public gallery, one
137version, the draft, publish, remix, the install screen, install, and an installed agent's version
138(`agents.blueprint@1`, `agents.install@1`).
139
140## 0.419.0 — 2026-11-12
141
142**Make your own agent: `agents.blueprint@1`.** An agent anyone can read, change, share and run anywhere, as one small
143document of ten parts:
144
145- **face** (Design);
146- **brain** (Exchange): auto, a size or one model; the ladder rungs it may use; the most it pays; an advisor;
147 Decisions;
148- **knows:** instructions with `{{inputs}}`, skills, knowledge, and examples for Try it and Bench;
149- **hands:** each tool allowed or ask first, plus tool search. The tools are `ov:` product tools, `tools:` apps,
150 `connect:` apps, the installer's own `mcp:` servers, `machine:` files/shell/desk/browser/screen, `robot:` manifest
151 commands, `harness:` coding harnesses and `agent:` other agents;
152- **places:** none, own, shared, openvibe or sandbox, and what the work needs; never a machine by name;
153- **memory;**
154- **rules:** level, budget, who may ask;
155- **when:** the Source kinds plus `event` and `schedule`;
156- **makes:** answers, an exact shape, and whether it is served to other agents over A2A or as an MCP tool;
157- **team:** a play whose roles are other blueprints at fixed versions.
158
159Inputs and needs sit above the parts. A blueprint carries no secret and grants nothing. A published version never
160changes. Design note: `agent-blueprints.md`.
161
162- **`agents.install@1`:** a person's own agent, made from one blueprint version. It records the inputs they filled,
163 the asks they agreed to (by key) and the machines they chose. It says whether a version that asks for no more is
164 taken without asking, and holds a `pending` version that waits for their yes.
165- **`agents.run-start@1` 1.2.0:** `blueprint` runs a version once without installing it (Try it). Every tool asks
166 first.
167- **`agents.run@1` 1.3.0:** `agent.blueprint`, the version a run's agent was made from.
168- **Fixtures:**
169 - five blueprints: Clip finder, Vibe as `bp_vibe`, a draft with a grader team, a tool for other agents, a robot
170 driver;
171 - ten refusals: full level without a budget, a tool nobody has, a schedule without a time, served as a tool
172 without a shape, a team role without a version, published without a date, a key in the brain, a machine by
173 name, an exact pick without a model, no instructions.
174
175## 0.418.1 — 2026-11-12
176
177**LOOI's manifest, exactly as the P7 list says it, and not frozen until Maticus has checked it.** The head has its own
178delivery window (1–300 ms; 500 ms is its lifetime on the Live tray, head-only profiles use 300), the top-level
179`battery` (0–100, polled) is a reading of its own, and `p7_battery`'s `unverified` is listed as a field that comes only
180with a read at connect or a stale value. `bot.robot-manifest@1` readings take `optional`: the fields that come only
181sometimes. 0.418.0 marked the example frozen before the maker's check; `frozen` is now false until he confirms it.
182
183## 0.418.0 — 2026-11-12
184
185**A robot's own manifest:** `bot.robot-manifest@1` (public, ADR-043) is what a robot's driver says the robot can do,
186written and versioned by the driver's maker, so a new control is a version bump of the manifest instead of an
187OpenVibe release (the plan in Maticus's LOOI thread, 11-10; his P7 command list on 11-12 is its first frozen version).
188
189- **Commands:** kind, class (`motion`, `state`, `action`), the value's fields and ranges, `lifetime_ms`, the
190 `delivery_ms` window Bot gives it, `min_left_ms` on arrival, `rate_per_s`, `release` (`stop`, `hold`, `none`;
191 motion must stop or hold), `latched`, the telemetry key that `confirm`s it, and the `control` the panel draws
192 (stick, slider, toggle, button, pad). An actuator names which one.
193- **Telemetry:** a key, its fields (ranges, `boolean`, `string`, `ms`, `integer`, `number`, or a list of values),
194 unit and range, `source` (`poll`, `push`, `connect`), `fresh_ms`, and its control (meter, readout, badge, list).
195- **`frozen`:** true once the maker and OpenVibe have checked a version against the driver's real command list.
196- **`ui.surface@1` parts say what they send or show:** optional `command` and `reads`, in the manifest's terms, so
197 OpenVibe AI knows a part's ranges, lifetime, release and rate when it arranges a panel or writes a control. They
198 grant nothing: the product's gate still checks every command. A new example is LOOI's panel built from its manifest.
199- Fixtures: LOOI 1.0.0 through the P7 tray (drive 500 ms life, delivery 1–300, release stop; head 500 ms, hold;
200 headlights delivery 1–250, 50 ms left, 2 a second, latched; battery by poll with `at` in ms; who is driving), and
201 three refusals (motion without a release, an actuator without its name, motion that is never released).
202
203## 0.417.0 — 2026-11-12
204
205**The agent engine's next shapes:** who asked, what a run continues, how several agents share one ask, and where the
206money went (agent-engine.md §§3-5, from the code study). Every field is optional and the new contracts are new.
207
208- **`agents.run@1` 1.2.0:**
209 - `mandate`: an ask taken in from the feed, a room, an issue: where, by whom, explicit or inferred, and the scope;
210 - `lineage`: a fork, a hand-off or a regenerated turn, with the run and turn it came from;
211 - `play` and `role`;
212 - `agent.capabilities`;
213 - `cost.by`: the spend on each rung of the ladder (machine, plan, key, allowance, credits).
214- **`agents.step@1` 1.2.0:** `turn`.
215- **`agents.run-start@1` 1.1.0:** `play`, `lineage`, and `mandate` (from intake only).
216- **New `agents.play@1`:** a play as data, made of roles, phases, checks, a stop rule and a budget split. Fixtures:
217 advisor, grader loop, fan-out.
218- **New `agents.source@1`:** one place asks are taken in: who may ask, what counts as an ask, the run it becomes, its
219 budget, and how the run answers. Fixtures: the owner's feed, Vibe in a room.
220- **Stop is a plain control.** On small hobby robots, the panel's Stop is one ordinary, optional control that sends
221 the machine's own halt:
222 - `bot.robot@1`: the description and the old latch field say it is legacy (always false); schemas are unchanged.
223 - `bot.device-message@1`: the old latch frame and the `estop_*` fields are described as legacy names devices may
224 still send, not as a remote latch; Bot's config always sends the latch false.
225 - `bot.command-result@1`, `bot.robot-control-result@1`, `bot.robot-manage-result@1`, `bot.command.refused@1`: the
226 old stop endpoint and refusal code are gone from the descriptions.
227 - `bot.estop.set@1` and `bot.estop.cleared@1` are retired (fixtures and schemas stay for the contract window).
228 - `ui.surface@1`: Stop is not a required part; `ui.action@1` names Stop alone; `ui.trigger@1` adds `stop`.
229 - Manifests and ADRs use Stop; `bot.resource.control` stop sends halt and resume is a calm no-op.
230
231## 0.416.0 — 2026-11-12
232
233One view API for every content kind (the owner, 11-12): a preview in the feed and a watch on a page count the same
234item once, and Report can say how many people watched and how many stayed.
235
236- Add `media.view-request@1`: `POST /api/v1/views` { ref: { service, kind, id }, how: preview | watch | live, seconds,
237 of_seconds?, session } on OpenVibe.Media (batched by `{ events: [ … ] }`, at most 20), with the preview/engaged
238 thresholds and the 30-minute per-viewer window.
239- Add the `media.viewed` and `media.engaged` events: the counted view and the first engagement for an item, with the
240 optional Report dimensions site and creator and no IP, user agent or raw session id.
241- Fixtures for both events and the request, and the generated JSON Schema and TypeScript.
242
243## 0.415.0 — 2026-11-12
244
245One feed for all of OpenVibe: the card OpenVibe.Network serves from /api/v1/feed and /api/frame/feed, and that
246OpenVibe.Community's Pulse reads instead of its own collector.
247
248- Add `feed.item@1`: each card's stable id, kind (post, pic, clip, video, live, stream, rundown, quest, member,
249 chat, event, wiki, update, work, deal, news, report, poll, game, meme, paste, episode, space, avatar, banner,
250 follow, site), link, source site, actor and subject, first picture, counts (views, likes, comments, watchers,
251 people), live_now, a folded group of the same kind, a report trend, starts_at and follower visibility.
252- Fixtures for every kind, plus invalid ones (unknown kind, missing id, a URL without a scheme, a negative count, a
253 subject that is not a usr_ id, private visibility, a one-item group, a trend without a direction), and the
254 generated JSON Schema and TypeScript. Additive and new: no existing contract changes.
255
256## 0.414.0 — 2026-11-12
257
258The whole run (the agent engine, `docs/agents-runs.md`; design `agent-engine.md`). The owner, 11-12, with the menu's
259Chat · Code · Agents switch crossed out: "one new unified agent … the same agentic system, shared across agents, code
260and chat". Everything a person asks an AI to do is one shape: a run, and its thread of steps.
261
262- `agents.run@1` 1.1.0, optional fields only:
263 - `title`, `kind`, `ref` (its address on the Frame), `url`;
264 - `model`, `where`, `target`;
265 - `doing`, `waiting`, `preview`, `counts`, `ended_at`;
266 - `context`, `outputs`, `visibility`;
267 - the agent's face: `agent.glyph`, `agent.hue`, `agent.avatar_url`, `agent.harness`.
268- `agents.step@1` 1.1.0, optional fields only: `from`, `author`, `status`, `title`, `glyph`, `attachments`, `sources`,
269 `ui` (a rich card) and `desk`.
270- Add `agents.run-start@1`: what starts a run on any product and on the Frame. Only `text` is required.
271- Add `agents.event@1`: a run's stream (`run`, `step`, `delta`, `approval`, `end`).
272- Add the event `agents.run.updated` (`@1`): the run's snapshot on OpenVibe.Events when what a list draws changed.
273- A conversation is a run that is `waiting` for a `message`; an approval and a takeover are the same status with
274 another `for`.
275
276## 0.413.0 — 2026-11-12
277
278The composer's Reach (Post · Ask · Do, stage R3; Network R3): what its `/` and `@` menus offer.
279
280- Add `frame.commands@1`: `GET /api/frame/commands?site=<host>&q=` on OpenVibe.Network, the command rows a composer
281 offers on one site — the network's `/ask`, `/do`, `/remind` and `/timer`, the site's own from its Frame manifest,
282 and a signed-in person's saved composer snippets — each with its hint, the text a pick inserts, its kind and whether
283 it needs a signed-in person.
284- Add `frame.mentions@1`: `GET /api/frame/mentions?q=&site=` on OpenVibe.Network, at most eight rows for the `@` menu:
285 public people (with a handle, display name and an OpenVibe.Media avatar only), the person's own agents from the agent
286 directory, open OpenVibe sites and Live's public channels. People first; signed out, public people only; no email or
287 private account field.
288- Fixtures for both (valid and invalid) and the generated JSON Schema and TypeScript.
289
290## 0.412.0 — 2026-11-12
291
292One agent system, stage 2: one run shape for Actor, Codes and Run, and the step event that follows it.
293
294- Add `agents.run@1`: a run's id, owner, agent and product, parent run, budget (USD, tokens, seconds and steps),
295 status (`planning`, `running`, `waiting`, `done`, `failed`, `stopped`), created and updated times, a result summary
296 and what it spent. One shape for OpenVibe.Actor, OpenVibe.Codes and OpenVibe.Run.
297- Add `agents.step@1`: one entry of a run's append-only log (run id, seq, kind `think|tool|message|approval|child|file`,
298 text, the tool call and its input, the result, the step's cost, start and end, and the child run it started).
299- Add `agents.approval@1`: an ask attached to a run's step (what, the options with their labels, who decided and when,
300 and the answer).
301- Add the event `agents.step.appended@1`: the appended step as the payload, on OpenVibe.Events. The `agents` namespace
302 is hyphen-free because an event type cannot carry a hyphen; Actor registers the producer.
303- Add valid and invalid fixtures for all four, the generated JSON Schema, TypeScript and per-service OpenAPI, and
304 `docs/agents-runs.md`: which field of Actor's `tasks`/`task_events` and Codes' `run_tasks`/`codes_session_lines`/
305 `codes_approvals` becomes which field of the new shape, and what does not fit (Actor's `needs_you`, per-step cost,
306 split tool call/result entries, and Codes' attempts as one flat run).
307
308## 0.411.1 — 2026-11-12
309
310- Add the `code` category to `sources.source@1`, `sources.item@1`, `sources.category@1` and `sources.source-write-request@1`: GitHub repositories (trending, top, new and star-gain rankings) enter OpenVibe.Sources under one category, with a 30-day item window. Additive: no existing field changes, and an older reader ignores the new enum value.
311
312## 0.411.0 — 2026-11-12
313
314The composer's Frame (Post · Ask · Do; Network #858): what its Model sheet lists and what an Ask sends.
315
316- Add `frame.choices@1`: `GET /api/frame/choices?task=` on OpenVibe.Network, the models a composer offers for a task in
317 groups (OpenVibe's, the person's keys, computers and plans), each row with its maker, price per million tokens in and
318 out, speed, Report score and its Exchange page, plus the recommended and current choice.
319- Add `frame.ask@1`: the body of `POST /api/frame/ask`, the question, the model (a row id or `{ model, source, machine }`),
320 the sources to search (`web`, `openvibe`, `mine`, `page`), the depth and the files and page context it carries.
321- Fixtures for both (valid and invalid) and the generated JSON Schema and TypeScript.
322
323## 0.410.0 — 2026-11-11
324
325A train of three pull requests: the layouts of make-your-own-controls (#455), Elements stage 1 (#456) and the deep dive
326(#457).
327
328- Add `ui.surface@1` (the catalog of a surface's parts, their minimum sizes, styles, bindings and
329 `never_covers` rules), `ui.layout@1` (a person's arrangement on one device class, with its name, author and
330 sharing), `ui.layout-request@1` (catalog, current layout, words and device for the AI task) and
331 `ui.layout-suggestion@1` (a validated layout with a one-sentence summary, reasons and the model's receipt, or
332 an honest refusal with the validator's reasons).
333- Add `network.layout.changed@1`: the event Network writes in the transaction that sets, saves, renames, deletes,
334 shares, publishes, copies or resets one person's layout. It carries the surface, device, layout id, change and
335 revision, never account data or layout contents.
336- Add `ai.layout.suggest` (first-party, `POST /api/v1/ui/layout/suggest`) and `network.layout.read` (first-party,
337 `GET /api/v1/people/:subject/layouts/:surface`), and list them in the AI and Network manifests.
338- The fixtures cover a bot-controls catalog, a phone layout, a docked overlay, a suggestion and a refusal, a
339 request and the event; the suite checks part ids, theme tokens, never_covers targets and the 44 px minimum. (#455)
340- Add `ui.element@1`: a look from OpenVibe.Design's components and the theme's tokens, a recipe (triggers, conditions,
341 actions), the capabilities the element declares, an optional mod reference (id, version, digest) and its sharing.
342 The store assigns the id and revision; a draft has neither.
343- Add `ui.trigger@1` (press, hold, double-press, key, gamepad, chat command and text, follow, tip, AI Moment, Rundown
344 topic, timer, schedule, robot telemetry and event, stream start and end, viewer count, another element's event) and
345 `ui.action@1` (robot, chat, screen, stream, AI, Actor, webhook and tip-goal actions), each action carrying the product
346 that authorises it. `ui.action@1`'s `$defs.capability` is the one list an element's `capabilities` draws from.
347- Add `ui.element-state@1`: the element's own store (counters, scores, lists), with a revision that grows per accepted
348 change and values that are booleans, numbers, short strings or lists of them, never objects.
349- Add `live.element.pressed@1` and `live.element.state@1`: a press with the presser's public name and the trigger, and
350 the store with its revision, written by Live.
351- Fixtures cover a gallery dance button, a chat counter, a mod element, trigger and action variants, the state, and
352 both events; `test/elements.test.js` holds the capability list to the action catalog, each kind to its product, and
353 the recipe to the element's declared capabilities. (#456)
354- Add `ai.deep-dive@1`: a deep dive run's report as OpenVibe.AI's `design.deep_dive` workflow produces it for
355 OpenVibe.Exchange and OpenVibe.Design — the question and depth, the seven steps, every source, every capture (a
356 private Media object per viewport and theme, with its DOM facts and Expert extras), the per-site analysis, the
357 synthesis, the recommendations checked against OpenVibe's rules, and the receipt. Every claim carries its evidence.
358- Add `ai.deep_dive.updated@1`, the event AI writes on each step transition and at the end, so a page can follow a
359 run without polling and Design can attach a finished report. (#457)
360
361## 0.409.0 — 2026-11-11
362
363- Define machine access requests, grants and signed token claims; the agent directory, A2A tasks and results; five Network events and four registration and relay capabilities.
364
365## 0.408.0 — 2026-11-11
366
367The rest of the 0.407.0 train. v0.407.0 was tagged at #451's merge, before the train merged, so the tag holds #451
368alone; a tag is never moved, so the three pull requests the train carried are released here.
369
370- Add `codes.task-summary@1` (a task as the Dock's Code tab lists it: id, title, status, mode, repo, times, attempts,
371 url, preview and PR links) and `codes.task.updated@1`, the one event Codes writes on every task status change beside
372 the per-state `codes.task.*` events (#425).
373- Add `compare.comparison@1`: things, weighted criteria, finite results with required observation dates and HTTPS
374 sources, method, source list and update date; register the Compare service, repository and product in Read & ask
375 (its group gains an eighth tile) (#428).
376- Add the optional `is_test` to `identity.subject-projection@1` so public surfaces can leave probe and test accounts out
377 while their own signed-in views keep working, and the `{ subjects }` answer of Network's
378 `GET /internal/identity/test-subjects` in `identity.resolve-result@1` (#450).
379
380## 0.407.0 — 2026-11-11
381
382- Add `exchange.search.icons`: a first-party service searches icon references through the Exchange platform API (`POST /v1/search/icons` at `api.openvibe.exchange`, served by OpenVibe.AI) with its own free-search quota and no Exchange key. It reaches the icons route only, never web, image or fetch search, and the receipt names the engine, cost and skipped attempts. OpenVibe.Design holds it for the references shown beside a glyph draft. (#451)
383
384## 0.406.0 — 2026-11-11
385
386The second train of the day, for the five pull requests opened after 0.405.0 (one line each):
387
388- Define `meme.caption.created` for a signed-in person's public caption, with only its id and owner (#444).
389- Add `codes.model-plan@1`: execution modes, role models and effort, bounded samples and budgets, an escalation ladder
390 and required checks; task requests accept a plan or a preset, and task reads can include the resolved plan and
391 per-role usage and outcome (#445).
392- Delivery and retry on computer and browser results: `bot.command-result@1` and `run.session-control-result@1` gain
393 `delivery` (`delivered`, `not_delivered`, `uncertain`) and `retry` (`safe`, `reason`), only `not_delivered` is safe
394 to replay; optional browser `origins` on browser commands, Run session creation and Bot desk lease creation (#446).
395- Add `ai.model-directory-entry@1` and `ai.model-directory-list@1` for public model listings, with provider-listed
396 models routed off, preview and retired models, and sourced pre-list sightings; a spotted entry never implies
397 availability (#447).
398- Keep the exact reply target and its display name in Community comment reads; document the two-reply preview and four
399 Chat-compatible file references on comment writes and reads (#448).
400
401## 0.405.0 — 2026-11-11
402
403This release train carries the contract work that was waiting on the owner's release. One line per carried pull request:
404
405- Add `live.layout@1`, the player layout a person keeps in their account: per stream slot and source, the place as fractions of the frame, mode `dock` or `float`, the tuck side, mute and the time, at most 60 places (#442).
406- Add `chat.command-registration-request@1` and `chat.command-registration-result@1` with the active capability `chat.commands.register`, so a consented app or an Actor agent can register a plain response command for a server its person manages (#441).
407- Catalog OpenVibe.Directory as a live service and site, replacing its parked product metadata, with its public origin, source refresh lifecycle and public-listings-only scope (#440).
408- Add `actor.agent-sheet@1` and `codes.agent-sheet@1`: the owner-scoped agent sheet responses, with current work, daily activity, approvals, computer, schedules and memory where recorded (#439).
409- Extend `community.feed-item@1`, `community.pulse-item@1` and `community.pulse-write-request@1` with activity kinds, followers-only visibility, scheduled starts, previews and links to every item in a folded burst; Community consumes Network profile updates (#438).
410- Add `chat.person-memory-result@1` and `chat.person-memory-preferences-result@1`: the public and private parts of Chat's compacted day, week and month memory, and the erase and opt-out responses (#437).
411- Add `preview_url` (and `preview_webm_url` on media) to `media.vod@1`, `media.clip@1` and the Live stream shapes: the 6 s muted hover preview beside a thumbnail (#436).
412- Add `agent.ui-event@1` with the AG-UI 1.0 event union and OpenVibe `metadata.ov`, `agent.run@1` snapshots, and the `agent-run` chat embed (#434).
413- Add `network.user-card@1` with viewer-aware actions, and `network.user-report@1`, `network.user-report-request@1` and `network.user-report-list-result@1` for a person's reports and the staff queue (#433).
414- Add `community.feed-card@1` and `community.feed-answer@1`, with preview media support (#432).
415- Add `composer.attachment@1`, `composer.prefs@1` and `composer.mention@1`, the shared composer's server-side shapes (#426).
416
417Valid and invalid fixtures cover every new shape, and the generated TypeScript, JSON Schema bundle and per-service OpenAPI files are regenerated at this version.
418
419## 0.404.0 — 2026-11-11
420
421- Add owner-only Run compute configuration capability for Network admin proxy.
422
423
424## 0.403.0 — 2026-11-11
425
426- Extend `actor.task-create-request@1` with conversation, tools, model and optional content tier fields for Actor turns; uncensored content is available only when a task names the person it is for.
427- Deprecate the account-merge contracts after removal of the feature across services; retain the released schemas.
428- Add `chat.embed@1` as the shared address preview shape for chat clients.
429
430## 0.402.0 — 2026-11-11
431
432- Activate `download.file.read` for grant-bound, per-file reads by agents on openvibe.download; the capability alone does not provide drive listing or access without an owner's active grant.
433
434## 0.401.0 — 2026-11-11
435
436- Add the `live.channel_points.read` capability (with `live.channel-points-page@1`): OpenVibe.Network reads one channel's points moves for the person behind a Network account through Live's internal channel-points changes read, for the gain/loss API (ask 273).
437
438## 0.400.0 — 2026-11-10
439
440- Regroup the sites into the owner's eight groups (plan ask 274, 2026-11-10): `site.neighbourhood` is now `watch`, `talk`, `play`, `read`, `shop`, `tools`, `make` or `build`, the same ids and order as OpenVibe.Network `frame/sites.js` GROUPS and OpenVibe.Shared `rooms.js` HOODS. Every site manifest carries its new group; merged sections point at the site that shows them (Media → Video/watch, Bench → Report/read, Play → Games/play).
441
442## 0.399.0 — 2026-11-10
443
444- #408: add `quest.today@1`, the private Quest today response.
445- #412: extend `network.operator-alerts-request@1` with browser-check evidence and release timing details.
446- #415: add the `git.checks.write` capability for reporting commit statuses.
447- #416: add `agent.finding@1` for confirmed findings, leads that need validation and rejected claims.
448
449## 0.398.0 — 2026-11-10
450
451- `codes.task@2`'s outcome state names a goal task's honest end state: `ready` only with an accepted independent verdict, `waiting`, `blocked` at its no-progress limit, `failed`, `dropped` by the person, or `stopped_by_budget`. A task without a goal keeps `done`, `unfinished` and `stopped`.
452
453## 0.397.0 — 2026-11-10
454
455- Add `agent.goal@1`: a task's outcome in words, a typed check (`command`, `url` or `rubric`), optional resource budgets (tokens, turns, active minutes) and a no-progress limit, plus the worker's bounded completion proposal and evidence and the independent verifier's verdict (accepted or rejected, with a reason and the check's own output).
456- `codes.task-start-request@1` takes the optional `goal`; `codes.task@2` carries it back with the worker's proposal, evidence and the verifier's verdict.
457
458## 0.396.0 — 2026-11-10
459
460- Add optional ordered attempts to web and image search receipts, with provider/engine, status, safe reason codes, latency and cost. Existing receipts remain valid.
461
462## 0.395.0 — 2026-11-10
463
464- Add two planned products to the catalog: `manifests/products/openvibe.compare.json` (OpenVibe.Compare: compare anything side by side with its sources and dates, AI models first) and `manifests/products/openvibe.directory.json` (OpenVibe.Directory). Both are `noRepo` with launch notes; the addresses are parked. Compare's "meanwhile" link is OpenVibe.Exchange, where the models and their prices live today.
465
466## 0.394.0 — 2026-11-10
467
468- Add `chat.room-insight-result@1` (`contracts/chat/room-insight-result.v1.json`): the public answer of `GET /api/v1/rooms/:id/insight` on OpenVibe.Chat. One shape for every room: `overview` (the text written for someone arriving now, its topics with message counts, how many people and messages the window held, its from/to times and when it was written), `timeline` (the room's notable moments, newest first, each with `at`, `kind`, `title`, `text` and the `message_id` it came from), and `state` (`ready` / `quiet` / `off`). Quiet is explicit: an old or empty summary carries no text rather than invented news. The overview reads only people who allowed AI use of their messages (`network.consent@1`, purpose `ai.train` on kind `chat`).
469
470## 0.393.0 — 2026-11-10
471
472- `billing.money-reason@1`: declare `donation:received`, the row a creator sees for a tip that arrived ("for a tip from @alice"). The kind list is one list; the sender's `donation` still reads "for a tip to @bob".
473
474## 0.392.0 — 2026-11-10
475
476- Add `billing.money-reason@1` and `lib/money-reasons.js`: one list of the plain words for a movement of OpenCoins, Vibes or Balance. Each kind declares the key it matches (`quest:publish-a-video`, `Media request: <title>`, Billing's type:metadata), its site, what its subject is (a quest, a stream, a tip, a creator, an app, a project, a purchase), the phrase that names it ("for the quest {name}"), and how the subject's own name and address are found. `describe()` answers `{ key, text, subject: { name, url } | null }`, so a page writes "+15 OpenCoins" before the text and links it; an undeclared key reads "for something on <site>" with `known: false` and never shows the key. Fixtures cover a quest, a tip, a reason with no page and an undeclared key.
477
478## 0.391.0 — 2026-11-09
479
480- One Network experience curve, named reasons, level reads and capped service awards.
481
482## 0.390.0 — 2026-11-10
483
484- A service manifest's `site` block takes an optional `strip`: up to three items a site adds to the network's footer strip, read with the rest of it at OpenVibe.Network `GET /api/frame/online?site=<id>`. An item is a plain label, an icon from openvibe-shared's glyph set, an https link on an `openvibe.*` domain, and either a `count` the site reports or a fixed `line` — never both. Live, Community and Games declare one each as the worked examples.
485
486## 0.389.0 — 2026-11-10
487
488- Add `ai.advisor@1`: how a run may ask a stronger model for advice during the run. Off when the request omits it; at most 3 uses and at most 100 words of advice; the advisor may be named, the effort is concrete, and each use is on the run's receipt with its cost. Add `ai.advice@1`: one use on that receipt, naming the advice run, the model, the tokens and the cost. `ai.run-request@1` takes the optional `advisor` field and `ai.run@1`'s explain carries the uses.
489
490## 0.388.0 — 2026-11-10
491
492- Add `git.clone-request@1`: one "Clone to my computer" request from a repository page. Git mints it for the signed-in person, the person's Link reads it over an outbound HTTPS relay, asks for approval on the machine, clones into a folder inside the root the person chose in Link, and reports progress back; the page polls the same document. The request lasts two minutes, only a repository the person may read can be requested, and `clone_url` (with a short-lived read token) is present only in the Link's answer, never in the page's copy.
493- Add `git.machine@1`: a computer published to OpenVibe.Git through Link, read-only. It lists the repositories under the root the person chose in Link, each with its branch, head commit and date, and whether the machine is online ("offline since …" when it is not). Browsing is asked of the machine over the poll it opened; nothing in this contract is a write path.
494- Valid and invalid fixtures cover a pending, cloning and done request, a bad id, a bad state and a traversing repository name, and an online and offline machine, a machine without repositories and a repository name that escapes its root.
495
496## 0.387.0 — 2026-11-09
497
498- Add `ai.creation@1` and `ai.creation-list@1`: the catalogue of everything AI can make on OpenVibe, one entry per creation. An entry names the product it lands in, a plain one-line name, what the person gives it and what comes back, the workflow or registered task behind it, who may use it (guest, signed-in, the 18+ floor), whether it can cost coins, and the URL where a person starts it. `GET /api/v1/creations` on OpenVibe.AI answers the list, built from the registered workflows and tasks so only what is live is listed; the contract is public and its fixtures show a workflow creation and a task creation.
499
500## 0.386.0 — 2026-11-09
501
502- Add `chat.command@1` for registered slash commands and typed options.
503
504## 0.385.0 — 2026-11-09
505
506- Add `ai.file@1` plus typed conversational turn request and result shapes for Media-backed attachments and artifacts.
507
508## 0.384.0 — 2026-11-09
509
510- Agent work fabric: trigger, decision, immutable ticket mandate and budget, six report states, attention, and ordered stage vocabulary. Portable AI effort, concrete task-default effort, and optional effort/ladder receipt metadata.
511
512## 0.383.0 — 2026-11-09
513
514- `ai.provider@1`: measured per provider+model circuit health (status, failure class, plain reason and since when, retry/backoff, notify time); `ai.run-read-result@1`: `requests[].error_class`.
515
516## 0.382.0 — 2026-11-09
517
518- Add `exchange.market@1`: paginated own-page market offers, routing flags and per-field model metadata provenance.
519
520## 0.381.0 — 2026-11-09
521
522- blog.changelog-entry@2: a shipped change with its plain words, kind (new, better, fixed or internal) and one to three areas from Blog's fixed list, with the commit and pull request for the row's fold
523
524## 0.380.0 — 2026-11-09
525
526- Exchange routing controls, owner request presets and generation accounting schemas, with valid and invalid fixtures.
527
528## 0.379.0 — 2026-11-09
529
530- Wiki's rich articles: the page write request and the page read result carry `blocks` (`publishing.block@1`) next to the Markdown, and `wiki.images-suggest-request@1`/`-result@1` and `wiki.article-draft-request@1`/`-result@1` describe the image suggestions (`wiki.article.images`) and the `content.wiki` draft revision that waits for a person.
531
532## 0.378.0 — 2026-11-09
533
534- OpenVibe.Connect and the relay profile describe the Link, not the Node.
535
536## 0.377.0 — 2026-11-09
537
538- community.feed-item@1: live_now on a live stream's row
539
540## 0.376.0 — 2026-11-09
541
542- git.change@1, git.issue@1 and the review events for OpenVibe.Git's changes and issues (G2)
543
544## 0.375.0 — 2026-11-09
545
546- AI tasks and choices: `ai.task@1`, `ai.choice@1`, `ai.task-defaults@1`; a run accepts `task` or `choice` beside `workflow`, and `run.explain.task_choice` says what answered. `ai.me-preferences@1` gains `defaults.search`.
547
548## 0.374.0 — 2026-11-09
549
550- Add the Pics public gallery and picture contracts (`pics.gallery@1`, `pics.picture@1`) with valid and invalid fixtures.
551
552## 0.373.0 — 2026-11-09
553
554- The git service: its manifest, git.repo.read and git.repo.write, git.access-request@1 and git.access-result@1 (OpenVibe.Git)
555
556## 0.372.0 — 2026-11-09
557
558- The machine product Node became OpenVibe Link. The network registry contracts are `network.link@1`,
559 `network.link-report-request@1` and `network.link-list-result@1`, the event is `network.link.revoked`, and the platform
560 carries `platform.link-capabilities@1` and `link.compute@1`. The capabilities `network.node.manage`,
561 `network.node.report` and `network.node.self.manage` are `network.link.manage`, `network.link.report` and
562 `network.link.self.manage`; their internal routes and the manifests follow.
563- A paired machine is a `link` principal: identity.service-token-claims actor_type `node` is `link` with sub `link:lnk_…`,
564 and `ids.principalSub` mints `link:lnk_…` (the old prefix and ids are gone, no alias). The AI provider `node` is `link`
565 in ai.credential-put@1/@2 and ai.credential@1/@2. The old contract ids are deprecated with their Link replacements; the
566 schema corrections are recorded against the current release and the ones before it.
567
568## 0.371.0 — 2026-11-09
569
570- Exchange API platform and search: exchange.key@1, exchange.key-created@1, exchange.usage@1, exchange.deployments@1, exchange.search-result@1, exchange.image-result@1, and the Exchange manifest's routes
571
572## 0.370.0 — 2026-11-09
573
574- design.component@1: one platform-neutral definition per shared interface (the public registry on openvibe.design)
575
576## 0.369.0 — 2026-11-09
577
578- OpenVibe Git: git.repo@1, git.commit@1, git.tree@1 and git.insights@1
579
580## 0.368.0 — 2026-11-09
581
582- The wallet and the reviewed store: billing.wallet@1, inventory.store@1, inventory.store-listing@1, inventory.purchase@1
583
584## 0.367.0 — 2026-11-09
585
586- publishing.block@1: the rich content block of a post or an article body
587
588## 0.366.0 — 2026-11-09
589
590- wiki.page.published@1 and wiki.page.updated@1 carry an optional `title` (the page as readers see it), so the network's Feed names a wiki page by its title, not its slug.
591
592## 0.365.0 — 2026-11-09
593
594- Dock v2: action-item words, ai.run-error@1, skill runs and Vibe conversations
595
596## 0.364.0 — 2026-11-09
597
598- The Feed of everything: community.feed-item@1
599
600## 0.363.0 — 2026-11-09
601
602- npm metadata and CITATION
603
604## 0.362.0 — 2026-11-09
605
606- Your stats: report.me-stats@1 and report.me-stats-publish@1
607
608## 0.361.0 — 2026-11-09
609
610- Reviewed glyph draft service
611
612## 0.360.0 — 2026-11-09
613
614- Meme entry and render contracts
615
616## 0.359.0 — 2026-11-09
617
618- Media multipart uploads in contracts and OpenAPI
619- Define `design.component@1` for web, Android and iOS component anatomy, props, states, tokens, behavior, accessibility and examples.
620
621## 0.358.0 — 2026-11-09
622
623- Chat view preference (bubbles or room)
624
625## 0.357.0 — 2026-11-09
626
627- Cam camera settings (cam.settings@1)
628
629## 0.356.0 — 2026-11-09
630
631- Shoes product contract (shoes.product@1)
632
633## 0.355.0 — 2026-11-09
634
635- Daily quest contracts and step contribution
636
637## 0.354.0 — 2026-11-09
638
639- Vibe compare and Exchange chat export contracts (the Chat move)
640
641## 0.353.0 — 2026-11-09
642
643- Add `actor.ask@1`: durable approvals, questions, personal steps and sign-in hand-offs, linked to the person’s Actor and goal, with evidence and an answer or decline.
644
645## 0.352.0 — 2026-11-09
646
647- The menu's home screen and wall (M1): `network.home-screen@1`, `network.menu-feeds@2` (order and off; v1's on reads as
648 the start of the order), `network.frame-today@1`, `community.status@1`, `community.pulse-contribute-request@1` and the
649 person-granted capability `community.pulse.contribute`, with fixtures and the manifests' routes.
650
651## 0.351.0 — 2026-11-09
652
653- Add the five public Report AI comparison response contracts and fixtures, and list their cached public routes in the Report service manifest.
654
655## 0.350.0 — 2026-11-09
656
657- Define credential-free blind fill request, encrypted grant, and outcome contracts, plus the `run.fill.approve` capability.
658
659## 0.349.0 — 2026-11-08
660
661- Add `identity.emails@1` and `identity.email-add-request@1` and the `identity.emails.read` capability for a person's verified, privacy-limited email addresses.
662
663## 0.348.0 — 2026-11-08
664
665- Service manifests: `studio` (OpenVibe.Studio at openvibe.studio, live: Photo and Light in the browser), and
666 `connect` lives at `https://connect.openvibe.link` (its home on OpenVibe Link since 11-08; `connect.openvibe.website`
667 stays as the second domain). The registry still gave the old origin, so the sign-in canary read a 302 for Connect.
668
669## 0.347.0 — 2026-11-08
670
671- Add `identity.trust@1` and `identity.trust-request@1` for account and guest abuse signals, plus the app-grantable
672 `identity.trust.read` capability.
673 Responses contain coarse age bands and aggregate counts only; IPs, emails, last-seen timestamps, service user ids and
674 linked account identities are forbidden by the schema and fixtures.
675- Service manifests: `locker` (OpenVibe.Locker at openvibe.locker, live; it owns the `locker` namespace), and
676 `computer` is live (its exposure was still "repository").
677
678## 0.346.0 — 2026-11-08
679
680- `actor.skill-listing@2` (2.1.0) gains `visibility` (plan HO11, the agent writes its own skills): `public` (the
681 default, and what every listing is today) or `private`, meaning only its publisher sees or installs it. Additive:
682 the field is optional, so a listing without it stays public and nothing that exists today changes shape. A private
683 listing's `publisher.kind` must be `person`: OpenVibe's own skills are always public. JSON Schema states both the
684 enum and that rule, and the fixtures hold it.
685
686## 0.345.0 — 2026-11-08
687
688- Add `actor.approval-answer@1` (plan HO12, the phone as the agent's eyes and hands): the person's answer to an
689 approval that asked for the phone's camera or its location. The person does the thing themselves, and the answer
690 carries the result back to the step as untrusted input. `decision` is `answer`, and exactly one of:
691 - `photo`: `media_id`, a private Media object the person took in the system camera (JPEG, PNG or WebP, at most
692 10 MB, EXIF stripped by Actor); the step reaches it through a short-lived signed URL;
693 - `location`: `lat` -90 to 90, `lng` -180 to 180, `accuracy_m` 0 to 100000 metres and `precise`. A coarse answer
694 (`precise` false) carries `lat` and `lng` to at most two decimals; JSON Schema cannot count decimal places, so
695 Actor rounds the share and the repository's suite checks the rule.
696 The answer has no `secret`, `token` or `url` field, and a decline stays the ordinary denial.
697- `actor.skill@1` (1.1.0) and `actor.skill@2` (2.1.0) gain `device.camera`, `device.location` and `device.notify` in
698 `requires.kinds`, so a skill's steps may be one of those approvals like any other HO1 kind. Additive: nothing that
699 exists today changes shape.
700
701## 0.344.0 — 2026-11-08
702
703- `actor.trigger@1` (1.2.0) gains the mention kind (plan HO13, standing intents): a trigger that waits for the person
704 to say one of their phrases in their own conversation with their own agent. Additive:
705 - `kind` may now be `mention`; `when.mention` holds `phrases` (one to five, 2 to 80 characters each, trimmed) and
706 `match` (`any` or `all`), while `when.words` stays the card's line ("When you mention the release");
707 - `fires` may only be `once_per_conversation`: the trigger fires at most once in each conversation;
708 - `expires_at` is required for this kind and at most 90 days after `created_at` (the default is 30). JSON Schema
709 cannot compare two dates, so Actor enforces the cap, and the repository's suite checks the fixtures and the rule.
710- A mention trigger listens only to the person's own words to their own agent: never anyone else's messages, never a
711 room or a stream chat, and never the agent's own answers. Matching is case-insensitive, on word boundaries, after
712 Unicode normalisation. Nothing that exists today changes shape.
713
714## 0.343.0 — 2026-11-08
715
716- Add `actor.skill@2` and `actor.skill-listing@2` (ADR-060, plan HO8): a skill may now bring code that runs in a
717 sandbox instead of only a prompt. `runs` is `prompt` or `sandbox`; a sandbox skill carries 1 to 5 JavaScript
718 `tools` (name, description, `entry` naming one of its resources, a JSON Schema subset for `args`, `net`
719 `deny`/`openvibe-only`/`public` default `deny`, and limits under 30 s / 256 MiB), and the code itself is an
720 ordinary text resource (`.js`, at most 64 KiB) in the same integrity hash. `requires.kinds` gains `skill.run`.
721 The v2 listing pins each code resource's Media id and sha256 and lets a scan finding name the tool it is about.
722 Code never runs on an OpenVibe server, never outside a sandbox and never with a secret: it runs as a Run
723 `function` job on a Link that declared the skill runner. `actor.skill@1` and `actor.skill-listing@1` are
724 unchanged and remain what a prompt-only skill publishes.
725
726## 0.342.0 — 2026-11-07
727
728- Add `mail.agent_inbox.received@1` (track HO6, channels): a message arrived at an agent's own address and the person has switched that address's answering on, so their agent may read it. The payload names the inbox and the agent, the owner, the mail server's message id, the sender, the subject and a plain-text excerpt of at most 4000 characters. It never carries the attachments, the HTML or the whole body: the agent's system reads the text through `mail.agent.read`, on the owner's behalf, once it has decided to answer. Mail publishes nothing for a sender on the person's block list or a message the mail server marked as spam, and nothing at all until the person turns the agent's switch on.
729- Add `mail.agent-inbox-message@1`, the one message an agent reads: the sender, the addresses the mail server stamped at delivery, the subject, the text cut to 4000 characters, and the threading headers a reply needs. Never the HTML, never an attachment, and never a sender-written Delivered-To. The message is data from a stranger, and any instruction in it is that stranger's.
730- Add `mail.agent-reply-request@1` and `mail.agent-reply-result@1`, an agent answering one such letter: the body is plain text, the recipient is the sender of the message being answered (the same address may be named, never another), and the reply carries In-Reply-To and References so the thread stays one thread. The result says whether the mail server took it — `sent`, not "delivered", since a later bounce is not knowable at that moment.
731- Add `mail.inbox-answering@1`, the switch behind all of it: off by default, per agent, with when the person last set it.
732- Add the capabilities `mail.agent.read`, `mail.agent.reply` and `mail.agent.answering`. The first two are loopback-only and first-party: only a token that names the person (`on_behalf_of`) and the agent's own inbox reads a letter or sends a reply, and only OpenVibe.Actor is granted them. The third is the person's own switch, under the `mail.addresses.write` a caller already holds. The `mail` service manifest lists all three and now produces `mail.agent_inbox.received`.
733- Additive only: five new contracts, three new capabilities and one manifest field; nothing that exists today changes shape.
734
735## 0.341.0 — 2026-11-08
736
737- The actor capabilities name the canvas routes (plan HO9): `GET /api/v1/me/canvases` and `GET /api/v1/me/canvases/:id` under `actor.task.read`, and `POST /api/v1/me/canvases/:id/events` under `actor.task.create`. The documents are `actor.canvas@1` (0.340.0); a button's label starts a normal turn as the person, and a checklist tick flips the item and is told to the next turn. No schema changed.
738
739## 0.340.0 — 2026-11-08
740
741- Add `actor.canvas@1` (ADR-059, plan HO9): an agent's live panel beside the conversation, as data. A canvas is a
742 list of blocks (a heading, text, a list, a checklist, a table, a metric, a bar or line chart, a picture from
743 openvibe.media, a link, a button) drawn by one renderer (OpenVibe.Shared `ov-canvas.js`) wherever it is shown. There
744 is no HTML, style, script or frame; text is plain. A button only sends its label to the agent as the person's own
745 message, and ticking a checklist item tells the agent which item changed: a canvas never acts by itself. `version`
746 only grows, and the agent replaces the whole document.
747## 0.339.0 — 2026-11-08
748
749- The batches contract says what cancelling does. Only the prompts that never had a run are cancelled, and
750 nothing is charged for them. A prompt that already has a run (the provider is working on it) goes on and
751 settles on its own path: it keeps its status, the answer says so, and nobody is told it was not charged. The
752 batch itself is cancelled only when nothing is left in flight.
753- The prompt's `reason` now names the three notes a customer can read: it expired (it was not charged), it was
754 cancelled before it ran (it was not charged), or it was already sent to the provider (it finishes and is charged).
755
756
757## 0.338.0 — 2026-11-08
758
759- `actor.trigger@1` gains the goal kind (plan HO3): a trigger that keeps working toward a goal on a schedule. Additive:
760 - `kind` may now be `goal`, and `state` may be `done` (a goal ended itself when its done-test passed);
761 - `paused_reason` adds `done`, `budget` and `deadline` beside `person` and `failed`;
762 - the optional `goal` object says the goal in the person's words, the `done_test` the agent answers yes or no each run,
763 `runs_used` against `runs_max`, `spent_usd` against `budget_usd`, `deadline_at`, the last run's `not_yet` reason and
764 its `verdict`;
765 - the optional `answer_in_chat` (default true) says whether each run's answer is posted into the conversation that made
766 the trigger, under its card, and `notify` (default false) whether the person is also told through OpenVibe's
767 notifications.
768- Nothing that exists today changes shape: a schedule or event trigger without the new fields stays valid.
769- `actor.task-event@2` gains the `trigger-run` step (2.2.0): a routine's run posted into the conversation that made the
770 trigger, under its card. Additive: `trigger_id` names the routine, `run` says which task ran and how it ended
771 (`ok`, `failed`, `needs_you`), `text` is its answer or the one line saying why it did not finish, and `sources` are
772 the addresses it read (at most 8). An event without them, and the `trigger` card step, are unchanged.
773## 0.337.0 — 2026-11-07
774
775- Add `actor.skill@1` and `actor.skill-listing@1` (ADR-058, plan HO2: the skills registry's skeleton). A skill is a
776 document an agent loads to do one kind of job well: a slug, a name, a one-line description (the only part an agent
777 reads before it loads it), a version, Markdown instructions, up to ten text resources, and `requires` (the approval
778 kinds, connected apps and hosts it may ask for). It grants nothing: every step still goes through the agent's level
779 and approvals. A v1 skill runs as a prompt only (no code, no binary, no install recipe). Its integrity hash shows the
780 file was not edited; it is not a signature, and the author in a document is a claim.
781- The listing is the registry's record every site shows: the document, the publisher from the registry's own record,
782 the scan (`pending`, `passed`, `flagged`, `failed`, with findings) and the curator's state (`active`, `stale`,
783 `archived`, the last use and a near-duplicate). A passed skill installs in one tap, a flagged one after the person
784 reads the findings, a failed one never; a stale or archived one is not offered.
785
786## 0.336.0 — 2026-11-07
787
788- The run's options carry the latency class the caller asks for: `interactive` (answer as soon as the provider can),
789 `background` (minutes; the run is priced on the cheapest tier that can wait) or `batch` (hours; the run is queued and
790 answered through a provider's own batch API). A batch run may also say `deadline_hours` (1 to 72): how long the answer may
791 take. The class is the workflow's own (the route's `constraints.latency_class`): a caller may ask for a slower class and
792 never for a faster one, and a faster ask is not refused — the run happens in the workflow's own class and says so.
793- The run's answer carries `latency_class` (the class the run really ran in), `service_tier` (`standard`, `flex`,
794 `batch`, `offpeak`, `local`: the tier it was priced on — the one the provider served or the one the router chose) and
795 `latency_clamped` (the class asked for and the class used, when the ask was clamped).
796- Add the batches contract: `ai.batch@1`, `ai.batch-item@1`, `ai.batch-create-request@1`, `ai.batch-create-result@1` and
797 `ai.batch-read-result@1` for `/api/v1/batches` on OpenVibe.AI. A batch is a queue of many prompts that are answered
798 later, at half the retail price; the batch says where it stands, and a prompt that reaches its deadline without cheap
799 capacity expires and is never charged.
800- Add the grants `ai.batches.create` (open a batch, cancel one) and `ai.batches.read` (read the caller's own batches).
801 A first-party service opens a batch on the network's own account with `ai.batches.create`; a person or a developer app
802 pays with its own account.
803
804## 0.335.0 — 2026-11-07
805
806- Add `actor.voice@1`: an agent's voice as a file, and nothing else. The document carries the agent's name, a short bio, its instructions (the house voice it speaks in), its rules, its default approval level (`ask`, `auto-edits`, `approve-for-me`, `full` — the levels of `actor.agent@1`), the model it prefers and the connected apps it may use (ids only, never a key), an optional face (an avatar ref), an optional author and a `created_at`. It never carries memory, a connector's token or a file.
807- The document carries an **integrity** block, not a signature: `integrity: { alg: "sha256", hash }`, where the hash is the sha256 over the canonical JSON of the document. It shows the file was not edited after it was written. It says nothing about who wrote it: anyone can write a file that names an author and compute its hash, so the author in a document is a claim and the contract says so. Only the service that owns an agent may vouch for its author, in its own record.
808- The contract says exactly which fields the canonical JSON holds and in which order, and `created_at` is not one of them. The author may be absent: a document may name nobody.
809- Importing a voice makes a new agent at level `ask`, whatever the file says: a borrowed agent starts cautious and the person raises it themselves. Valid and invalid fixtures cover a full voice, a minimal one, a document carrying memory, one carrying a connector's token and one with a level that is not a level.
810- Additive only: a new contract and its fixtures; nothing that exists today changes shape.
811
812## 0.334.0 — 2026-11-07
813
814- The `chat` manifest names `openvibe.party`, the Watch Together host OpenVibe.Chat serves beside `openvibe.chat`
815 (Party watch v1, plan R1). Chat's service manifest is what services check a party link against: a media party plays a
816 Media ref or an https URL on a host a manifest names, so a party started from an OpenVibe page passes and a link to
817 somebody else's server does not. The `www.` name only redirects, so it is not listed.
818
819## 0.333.0 — 2026-11-07
820
821- The `network` manifest names the two hosts Network serves since 2026-11-07: `openvibe.my` (the account hub's own home,
822 Network#646) and `openvibe.link` (OpenVibe Link's home, Network#644). A service that builds its CORS list or its
823 checks from manifest domains (Network's first-party origins, Chat's Bearer-only DM grant, the registry's nightly
824 browser check, Space's reserved names) now includes them. The `www.` names only redirect, so they are not listed.
825
826## 0.332.0 — 2026-11-07
827
828- Add `common.control-lease@1`, the shared control lease (seven domains plan B3): the thing a lease controls, its holder (a `person`, an `ai` or `nobody`, with the holder's subject or null), when the holder got the controls, an optional absolute `expires_ms`, the subjects watching and a `seq` that increments on every holder change, expiry or take-back. A watcher-only change does not increment `seq`. The authority that owns the thing enforces the rules; Chat hosts a room's lease, names the thing `chat.room:<slug>` and accepts a control change only from the current holder, while take-back by the room's owner always wins; only the owner hands the remote to an `ai`, and a person holder who leaves keeps it for a minute.
829- Add `common.sync-clock@1`, the shared timeline (B4): the room, the media (a Media ref or an https URL; Chat accepts only a host an OpenVibe service manifest names, so Party plays OpenVibe media), the position at `at_ms`, the rate, whether it is paused, who set it and a `seq`. A player computes `position_ms + (authority now - at_ms) * rate` while it plays and `position_ms` while it is paused. Chat stamps `at_ms` and `seq` and stores the latest state in `room_sync_clocks` (the memory copy is the room's live state).
830- Valid and invalid fixtures cover a person, AI and free lease, a lease with a time limit, seq zero, a nobody with a subject, a duplicate watcher, a URL and a Media-ref clock, a clock at a rate and paused, an http URL, a bad room and a bad media object.
831
832## 0.331.0 — 2026-11-09
833
834- Add `actor.trigger@1`: a trigger made in an Actor conversation — its `trg_…` id, owner, agent, task, kind (`schedule` or `event`), the plain-language and machine schedule (a five-field cron in the person's timezone) or Watch event pattern and filter, the next run, the last run's result (`ok`, `failed`, `needs_you`), state, why it is paused, the consecutive failure count, the Watch subscription's own state and the ten-minute undo window. Owner-only: another person's trigger is the same 404 as one that does not exist.
835- `actor.task-event@2` gains an optional `trigger` and the `trigger` step: the card as it is created, edited, paused, resumed, undone or deleted in the conversation travels with the event, so a reader renders the live card without a second fetch. Additive: an event without one stays valid, and the task record is still the source of truth.
836- Additive only: a new contract and an optional field plus one new step value; nothing that exists today changes shape.
837
838## 0.330.0 — 2026-11-07
839
840- Add the `mail` service manifest: `openvibe.email` as the site **Email** (icon `mail`, the shared glyph font's E054), tagline "An address for every sign-up", the receive-only wording, legal profile `service`, and position 7, directly after Chat. It declares exposure `live`/`service`, port 5250, database `ov_mail`, the Stalwart mail server, `/api/health` and `/api/ready`, its shutdown and due-based recovery, an expand-only rollback, and the purge lease.
841- Add the two capabilities OpenVibe.Mail's API already checks: `mail.addresses.write` (make and retire a mask; make an agent inbox) and `mail.messages.read` (the person's addresses, message metadata and the newest burner code, never a body). Both are first-party, `owner`-constrained, and name their routes. Their request and result schemas are recorded in `compatibility/capability-schema-gaps.json` for now, like the config.manage capabilities added in 0.315.0.
842- The manifest lists no `eventsProduced` yet: the service publishes `mail.mask.created` and `mail.received`, but their payload contracts are not in this release.
843- Sites from the old position 7 up move one place (Services becomes 8, … Connect becomes 52) so Email sits beside Chat without breaking the unique-position rule. No contract changes shape; the only data change is the site order.
844
845## 0.329.0 — 2026-11-07
846
847- Add `mail.mask@1`: a per-site address on OpenVibe.Mail that delivers into its owner's OpenVibe mailbox and nowhere else. It carries the `msk_…` id, the owner's Network subject, the `<words>.<four characters>@<mask domain>` address, the person's label and purpose, whether it is enabled (a disabled mask leaves the SQL directory Stalwart reads, so it bounces) and when it was made. M1 is receive-only, so this is metadata: no body, no forwarding target.
848- Add `mail.burner@1`: a throwaway receive-only address with its `bnr_…` id, an owner (null for the ten-minute burner made without an account), the eight-character address on a rotating burner domain, the expiry, `first_message_only` and the creation time. The one-time read token a create call returns is deliberately not part of the resource.
849- Add `mail.agent-inbox@1`: an agent's address `<agent>.<user>@openvibe.email`, its `agi_…` id, the owner, the cleaned agent id and the creation time. The mail lands in the person's mailbox; one agent has one inbox.
850- Add `mail.message-summary@1`: the one shape a list API returns for a message — id, sender addresses, subject and received time. `additionalProperties` is false, so a `body`, `preview` or `html` field fails the contract rather than leaking into an API; the body is read only by the verification-code endpoint, in memory.
851- All four are new contracts, not changes to existing ones, and the minor is expand-only. Valid and invalid fixtures cover a disabled mask, a guessed address, an anonymous and a one-message burner, a bad owner or agent id, a non-address, and a summary that carries a body.
852
853## 0.328.0 — 2026-11-07
854
855- Add `actor.assignment@1`: one node of the tree of delegated work (plan §12) — id, root, parent, depth, origin (`person`, `routine`, `outside`), mode (`work`, `consult`, `notify`), reply (`resume`, `poll`, `none`), the agent and task it runs as, the node's level and effective level, the root's budget (limit, spent and remaining), state and timestamps. A node is one hand-off: a person giving Actor a task, a routine or Watch trigger starting a run, an agent handing work to another agent, or Actor starting a Codes or Space task. The effective level is the higher of the agent's own and the one inherited along a person's or routine's line; outside work never passes a level down. A cancel cascades down the tree, and a root's budget stops its children when spent. `GET /api/v1/assignments/:id` answers the node and its children and `POST /api/v1/assignments/:id/cancel` cancels the subtree; both are owner-only and another person gets 404. An existing task gets a root lazily.
856- Add the capabilities `actor.assignment.read` and `actor.assignment.cancel`, and name them in Actor's service manifest. They are the two assignment routes above.
857- `actor.task-event@2` gains an optional `assignment_id` on a step event, so the Dock's timeline can draw the work tree later. Additive: an event without one stays valid, and the task record is still the source of truth.
858
859## 0.327.0 — 2026-11-07
860
861- One Computer across Surf, Actor and the Dock (plan 2026-11-07: "Surf, Computer and Actor are one experience"): `platform.task@1` gains optional `computer` (`session_id`, `machine`, `where`, `cost_hint`, `driving`) — the browser or desktop session a running task opened, wherever it runs. `session_id` is OpenVibe.Run's `ses_…`; it is null only when the desk runs directly on the person's own machine through OpenVibe.Bot, where there is no Run session. `where` is `yours`, `home` or `network`, and `machine` is the person's own word for it.
862- `actor.task-event@2` and `agent.timeline-entry@1` carry the same `computer` object by `$ref`: the task's step in the Dock and the task record read the same fields, never a copy.
863- `run.session@1` gains optional `task_id` (the Actor task that asked for the session, so the session points back at the task) and `curtain` (the privacy screen: while it is up the session's still answers the curtain picture, never the screen). `run.session-create-request@1` gains optional `task_id`.
864- The `run.session.started` and `run.session.ended` event payloads carry the same optional `task_id` and `curtain`, so a session's own events stay valid with the new session shape.
865- Capabilities name the routes: `run.session.read` gains `GET /api/v1/sessions/{id}/still`, `run.session.control` gains `POST /api/v1/sessions/{id}/curtain`, `actor.task.read` gains `GET /api/v1/tasks/{id}/still`, and `actor.task.create` gains `POST /api/v1/tasks/{id}/takeover` and `…/giveback`.
866- Additive only: every new field is optional and nothing that exists today changes shape.
867
868## 0.326.0 — 2026-11-07
869
870- Add `network.menu-feeds@1`: the cards a person chose to show in the OpenVibe menu's "Choose your feeds", in their order, following them across every site. `on` holds up to four `<site>:<cardId>` ids (lower-case letters, digits and dashes) and `updated_at` says when the choice last changed. OpenVibe.Network keeps it at `GET` and `PUT /api/v1/me/menu-feeds`; a person who has never chosen gets `{ on: null }` from the GET. An empty array is a cleared choice.
871- Additive: a new contract only; nothing that exists today changes shape.
872
873## 0.325.0 — 2026-11-07
874
875- Add `media.vod@1` and `media.clip@1`: one recorded stream and one clip as OpenVibe.Media's API answers them. Both carry `watch_id`, the id openvibe.video addresses a watch page by (`openvibe.video/watch?v=<watch_id>`), and the shape around it that consumers already read — the numeric id (internal), the owning tenant, the app-local user ids, title and status, duration and size, the file basename, `playback_url`, thumbnail, storage provider, visibility, view counts and times; a clip also names the recording it was cut from, its window in that recording and whether an automation cut it. `watch_id` is **additive and optional** (11 characters of URL-safe base64 from 8 random bytes, one id space across VODs and clips, fixed for the row's life and never the numeric id), because a row written before Media's backfill may answer without one.
876- Valid and invalid fixtures cover a public recording with a watch id and an unlisted one before the backfill, a person-made clip and an AI clip, a watch id of the wrong length, one with a character base64url never has, one with a slash, and an unknown visibility.
877
878## 0.324.0 — 2026-11-07
879
880- Space's builder API moves under `/api/v1/builder/spaces`: `GET /api/v1/spaces` was the forum's old API (it lives on OpenVibe.Community since 2026-11-07, and Space still answers it with a redirect), so the API the person's own agent works through needs an address of its own. The capabilities name the new routes: `space.build.read` (`GET /api/v1/builder/spaces`, `…/:id`, `…/:id/files`, `…/:id/files/:path`, `…/:id/preview`), `space.build.create` (`POST /api/v1/builder/spaces`), `space.build.write` (`PUT /api/v1/builder/spaces/:id/files`) and `space.build.publish` (`POST /api/v1/builder/spaces/:id/publish`, and the person's answer at `POST /api/v1/agent/approvals/:id/decide`).
881- No contract shape changes: the bodies and the capability ids stay as they were.
882
883## 0.323.0 — 2026-11-07
884
885- Space's builder API says two more routes in its capabilities: `space.build.read` now names `GET /api/v1/spaces/:id/files/:path` (one file of one of the person's own spaces), and `space.build.publish` names `POST /api/v1/agent/approvals/:id/decide` (the person's answer to the agent's request to publish, which OpenVibe.Actor passes on with the person's own token).
886- No contract shape changes: `space.build.read` and `space.build.publish` keep the bodies they had.
887
888## 0.322.0 — 2026-11-07
889
890- Add `actor.agent@1`: one of a person's agents as a contact (plan §12 A-1) — id, owner, name, face, voice, model (`engine` runtime / own-keys / open-gpu / link, plus the model id), computer (null or a Computer kind and placement), connected app ids, OpenVibe Memory scope id (or null), approval level (`ask`, `auto-edits`, `approve-for-me`, `full`) and when it was added. Levels default to ask; money, passwords, deletions and sending to a new recipient always ask at every level, as a server-side floor.
891- Add `actor.agent-list@1`: a signed-in person's own agents (`GET /api/v1/agents`), Vibe first. Vibe is created on the first read and is not deletable. The public agent-system catalog keeps `actor.agent-list-result@2` and now has an explicit `GET /api/v1/agent-systems` for a signed-in caller.
892- Add `actor.level-change@1`: the body of `PUT /api/v1/agents/{id}/level`; optional `agent_id`, `thread_id` and `reason` are echoes, the path names the agent.
893- `actor.task-create-request@1` gains optional `agent_id` (the contact the task runs as; absent means Vibe) and `level` (the thread's own level). `platform.task@1` gains optional `agent_id`, `level`, `effective_level` and `agent_level`. The effective level is the higher of the agent's level and the person's own thread line; it never inherits from another person's or a service's work.
894- Name the contact routes in `actor.agent.manage` and the catalog and presets routes in `actor.agent.read`; add valid and invalid fixtures for the three new contracts.
895
896## 0.321.0 — 2026-11-07
897
898- Space's builder becomes a task of the person's one agent (plan 2026-10-22 §Z, stage Z1). Add the contracts of Space's builder API: `space.build-space@1` (one of a person's own spaces: its id, slug, name, description, whether it is published and where, and when it changed), `space.build-list@1` (`{ spaces }` or `{ space }`), `space.build-files@1` (the space's files, each a path and its whole content), `space.build-create@1` (the body of a request for a new space), `space.build-preview@1` (where the space can be seen now, its file paths, and whether it is live) and `space.build-publish@1` (`pending`, `published` or `declined`, with the request the person answers in the Dock).
899- Add the capabilities `space.build.read` (list and read the person's own spaces and their files), `space.build.create` (make a new space), `space.build.write` (write the files of one of them) and `space.build.publish` (ask to publish; the person answers before anything goes live). A first-party service names the person in `X-OV-Subject`, and only that person's own spaces are in reach.
900- Additive: nothing that exists today changes shape.
901
902## 0.320.0 — 2026-11-07
903
904- `frame.menu-card@1` items gain an optional `image`: `src` (https on the publishing site's own origin or an `openvibe.*` host, at most 400 characters), optional `w` and `h` (whole pixels, 16–1920) and an optional `alt` of at most 120 characters. Network keeps an image whose `src` passes the same host rule as the item's `url`, drops one from anywhere else, and passes it through in `GET /api/frame` so the Frame menu and Network's `/my` can draw a thumbnail.
905- Additive: every item without an image stays valid, so an older publisher file keeps passing and an older reader ignores the field.
906- Valid fixtures cover an item with a full image and one with only `src`; invalid fixtures cover `http`, a width under 16, an `alt` over 120, a missing `src` and an unknown image field.
907
908## 0.319.0 — 2026-11-07
909
910- The merged public site: OpenVibe.AI is no longer a site of its own. Its service manifest keeps the API, the run receipt and the operator console but drops the `site` block, so Network's Frame lists Exchange instead of AI. `manifests/products/ai.openvibe.services.json` is `kind: moved`, points at Exchange and keeps the API address, and Exchange's own site block now carries the merged tagline ("Every AI model, one account") and what it does.
911- No contract shapes change.
912
913## 0.318.0 — 2026-11-07
914
915- Add `network.presence@1`: one person's online status as another may see it — `online`, `away`, `dnd`, `invisible` or `offline`, an optional status line (80 characters) and one emoji, whether they are streaming on OpenVibe.Live (`live`), and when it changed. OpenVibe.Network owns it; the state is derived from a heartbeat (online under 2 minutes, offline after 3) and the last input (away after 10 minutes), and invisible or `show_status` off is seen as offline.
916- Add `network.presence-update-request@1`: the optional fields of `PUT /api/v1/me/presence` — the chosen state (`auto`, `dnd`, `invisible`), the status line and emoji, and the "Show my status" switch.
917- Add the event `network.presence.changed`, at most once per person per 30 seconds and only for a real change. Its payload is the public view: an invisible person is sent as offline with no status text or emoji, and the state list has no `invisible`.
918- Add the capabilities `network.presence.read` (OpenVibe.Network's `GET /internal/presence`, for Chat) and `chat.dm.peers.read` (OpenVibe.Chat's `POST /internal/chat/dm/peers`, for Network's "follows or has a DM" rule), and name them in the two service manifests.
919- Valid and invalid fixtures cover the presence, the update request and the event, so a bad subject, an unknown state, an over-long status or a second emoji fails the run.
920
921## 0.317.0 — 2026-11-07
922
923- Add `frame.menu-card@1`: one card a site publishes for the network's Frame menu (the menu's network cards). A card has a stable id and site, a title of at most 60 characters, a kind (`rail`, `rows` or `chips`), up to six items with a title of at most 80, an optional meta line of at most 120 and an https URL, an optional `more` link with a label of at most 24, the time it was built and its ttl. A URL must be https on the publishing site's own origin or an `openvibe.*` host; the text is plain words and Network strips markup and drops unknown fields.
924- Add `frame.menu-cards@1`: the public file each open site serves at `/.well-known/openvibe-menu.json` — an array of at most three cards from that site. An empty array is valid (the site has no card right now); Live serves its rail with empty items when nobody is live, and Network then skips it.
925- Valid and invalid fixtures cover a live rail with and without items, a Games rows card, a three-card file, an empty file, a title over 60, seven items, an unknown kind, an `http` URL, an unknown field, a ttl under 30, four cards and a card with a bad timestamp.
926
927## 0.316.0 — 2026-11-07
928
929- Add `agent.timeline-entry@1`: one entry of the agent's timeline (design 2026-11-07 §2) — one step of the agent's work, in one mode, for one person. It carries the mode, the product, the step's own id, a plain title, when it started and ended, its status (running, waiting, needs_you, done, failed, stopped), the placement (where it ran and why), the cost, a link to the step's page, the one-line reason when it failed, the transition sentence when the mode changed, and the audience (private is Only me, the default). It never carries a prompt, a diff or a page.
930- Add `common.agent-step@1` and the three events `agent.step.started`, `agent.step.updated` and `agent.step.ended`: the one shape every mode publishes when the agent does something (Chat, Codes, Run, Watch, Live, Surf), with the person's subject on the envelope. The payload is the step's shape only — a title, an outcome, a link, a cost — and never the step's content: a prompt, a diff, a page, a message or a file is refused by the schema. The `agent.*` namespace belongs to the network (like `provider.*`), so any first-party mode may publish into it; OpenVibe.Actor registers the family in Contracts and keeps the one timeline behind the Dock.
931- Add `agent.timeline-list-result@1`: what the Dock's Agent panel reads — the step happening now, what needs the person (oldest first), the entries themselves (newest first), the next cursor, and the per-mode counts so a filter never hides without a count.
932- Add `actor.timeline.read`: `GET /api/v1/agent/timeline`, the person's own timeline with the cursor and the mode and needs-you filters. Only their own entries; another person's entry is a 404.
933- Valid and invalid fixtures cover a step that starts, waits and ends, a timeline entry and a list, a payload with a prompt or a diff in it, an unknown status, a mode that is not one of the seven, and an entry of another person.
934
935## 0.315.0 — 2026-11-07
936
937- The owner's Setup tab reaches seven more services: `<service>.config.manage` for `chat`, `connect`, `deals`, `work`, `sources`, `design` and `domains` is now **active** and listed in each service's manifest, because each mounts openvibe-shared/config's routes on `/internal/config` (`GET /internal/config`, `GET|POST /internal/config/:namespace`, `PUT|DELETE /internal/config/:namespace/secrets/:key`, `POST /internal/config/:namespace/test/:key`). Only Network's admin proxy, acting for the owner, holds them and they are never grantable to apps. `media.config.manage` stays planned until Media mounts the routes.
938- Add `blog.review.ai_editor`, `news.review.ai_editor` and `wiki.review.ai_editor`: the editorial queue's AI editor decision (approved or rejected; approved or needs changes on Wiki) recorded by the first-party service principal acting as itself (a `svc:` principal with no `X-OV-Subject`) through Blog's `POST /api/v1/posts/:id/reviews`, News's `POST /api/v1/stories/:id/reviews` and `POST /api/v1/briefs/:id/reviews`, and Wiki's `POST /api/v1/pages/:id/revisions/:n/review`. An approval lets AI-written text publish and index and the page says "Checked by OpenVibe's AI editor" with its date, never "Reviewed by a person"; each is granted only to the orchestrator's service principal. Their requests and results are a recorded schema gap (`compatibility/capability-schema-gaps.json`).
939- `generated/` refreshed: Connect and Design gain an OpenAPI document now that each has an active capability, and Blog, Chat, Deals, Domains, News, Sources, Wiki and Work gain the new operations.
940
941## 0.314.0 — 2026-11-07
942
943- Add the capability `live.agent_sandbox.register` (Agent Streams S6): the chat plays sandbox worker's check-in on OpenVibe.Live, `POST /api/streams/agent/:id/plays/worker`, owned by Live and internal. Only a first-party service token whose principal holds it may register a worker, and the token names the person it works for in `X-OV-Subject`, who must own the stream. The owner's own session, a desk ticket (`wpt_`) and a person token are refused: an owner who could register a worker would declare their own unisolated machine a sandbox. The worker reports the isolation facts Live requires (no host network, no credentials, no profile, egress through the proxy, an ephemeral workspace) and Live derives health only from a check-in within the last minute; Live stores no endpoint and never calls the worker. Name the capability in Live's service manifest.
944- Add `live.agent-sandbox-worker-request@1`: the worker's check-in body, which names the five isolation facts Live reads exactly (`host_network` false, `credentials` false, `profile` false, `egress_proxy` true, `workspace` `ephemeral`) and may carry the worker's own checks, limits, versions and counts. A worker that cannot say each of the five is not registered. Add `live.agent-sandbox-worker-result@1`: the worker's state for the stream's owner, with the reason when there is no healthy one, the last check-in and the minute a check-in counts for. Live never returns an endpoint: there is none.
945- Valid and invalid fixtures cover a full worker check-in and an isolation-only one, a worker with the host's network and one that cannot say there is no profile, and a healthy worker, a stale one, a missing stale window and an unknown state code.
946
947## 0.312.0 — 2026-11-07
948
949- Add the Codes skills-hub records (the Compute plan §5, E6). `codes.skill@1` is one skill, rule, MCP server, command or hook: its owner, kind, stable slug, title, summary, the four sharing audiences (`private`, `people`, `link`, `public`), the harnesses it is written for, the newest version and that version's body. A `private`, `people` or `link` record is never in the gallery; only `public` is. The body is untrusted Markdown and the page renders it through the markup gate.
950- Add `codes.skill-version@1`: one immutable version of a record, keyed by `skill_id` and a growing `version`, with the body, summary, tools, audience, author and the note that says why it was written. A rollback copies the chosen version into a new one rather than rewriting history, so a Link that synced version 3 can still name it.
951- Valid and invalid fixtures cover a public skill, a private rule, a people-shared MCP record, versions 1 and 4, and the bad ids, kinds, audiences, tools, bodies and authors.
952
953## 0.311.0 — 2026-11-07
954
955- Add `<service>.config.manage` for the eight services that hold an owner input and that Network's admin proxy now reaches for the owner's Setup tab (OWNER-SETUP-AND-ADMIN-CLARITY-DESIGN, 2026-11-07): `chat`, `connect`, `deals`, `work`, `sources`, `design`, `domains` and `media`. Each is internal, held only by Network's admin proxy acting for the owner, never grantable to apps, and **planned** until its service mounts openvibe-shared/config's routes on `/internal/config`; the service then turns it active and lists it in its manifest (Deals' own test pins that list, so listing it early would break its pin bump). Planned capabilities verify like active ones, so Network's grant works the day a service mounts the routes.
956- Every `<service>.config.manage` (the nine active and the eight planned) names `POST /internal/config/:namespace/test/:key` among its routes: openvibe-shared 4.125.0's test hook, which tries a stored value with the provider on the server and answers `{ ok, message }` in one line that never carries a secret.
957- `common.config-namespace@1` (description only): the summary's schema may carry the annotations the Setup tab and the clear admin panel read, `x-owner-input`, `x-required-for`, `x-enum-labels`, `x-advanced` and `x-example`, beside the D11 ones (and `x-unit` names `seconds`). No shape changes.
958
959## 0.310.0 — 2026-11-07
960
961- Apps ask for consent per purpose at sign-in (the consent plan's C4). An app adds one scope `consent:<purpose>` per purpose to /oauth/authorize, beside its other scopes. It may ask for every purpose of the consent family except the retired `ai.looks`: `ai.train`, `data.public`, `face.recognize` and `app.data`. Any other `consent:` scope is refused with `invalid_scope`. The consent screen lists each purpose in plain words, nothing ticked, and the person can sign in with every purpose refused. A refused purpose is not asked again by that app for 30 days, unless the person asks for it again on their account page.
962- Add `network.consent-claim@1`: the `consent` claim of the tokens Network issues from that sign-in (a first-party user token, a Dock token or an app token). It holds exactly the purposes the sign-in asked for that the person granted to that app and that are active when the token is issued, `[]` when none. It never holds a refused purpose or another app's grant, and the app learns only "not granted". The claim is absent when no consent scope was asked. Every new token works it out again, so a purpose turned off is gone from the next one.
963- `identity.service-token-claims@1` gains the optional `consent` claim (additive): an app token from the authorization-code flow carries it when the sign-in asked for consent scopes.
964- Add `network.me-consent-apps-result@1`: "Apps you allowed" on the account page (`GET /api/v1/me/consent/apps`), listing each app's granted purposes and the ones refused in the last 30 days (`quiet`, with the day it ends), with the words the app consent screen shows. `network.consent.manage` names that route and `DELETE /api/v1/me/consent/:purpose/:client/refusal`, which ends a refusal's quiet days so the app's next sign-in asks again.
965- `network.consent@1`: an app's grant is one record per purpose, with the app as `client` and `source` `oauth`. `client` is no longer only for `app.data`, and `options.purposes` is not written any more (kept so older records validate). `network.consent-check-request@1`'s `client` may name the app for any purpose: one app's grant never answers for OpenVibe itself or for another app. Descriptions only: no shape changes.
966- Valid and invalid fixtures cover a user token with one purpose, an app token with none and with all four, a retired, unknown, duplicated or missing claim, a claim that is not a list, an app's grant record, the account page with two apps and with none, a bad client id, a retired purpose, an extra key and a quiet refusal with no end.
967
968## 0.309.0 — 2026-11-07
969
970- Add `bot.machine-pool@1` (the pooled machines design, 2026-11-06): several of one owner's machines on the same local network that serve one model together through llama.cpp RPC (`rpc-server` on the members, `llama-server --rpc` on the head). OpenVibe.Network holds the record: the owner proposes it on /machines with two to eight of their own machines (the default head has the most free VRAM), and each machine reads it with its own node token and approves it on itself. A member's `certificate` is null until it approves; then it is that machine's self-signed Ed25519 public certificate, which the other members pin for the pool's private link. The private key stays on the machine: a certificate slot holding anything with `PRIVATE KEY` in it is refused, and so is any field the schema does not name. A member's `address` is a private RFC 1918 address and prefix (never 0.0.0.0, loopback or a public address) and its `public_ip` is the address Network saw it from. The rules a schema cannot say are written in the description and checked by Network and Node: the head is a member, every member is the owner's today, all share one public address and one private subnet, the head's direct link probe to each passes, every key is its own, and any change of membership, owner, head or key revokes the pool so every machine approves a new one.
971- Add `ai.offer@1`: one community AI offer as Bot reports it to Network and AI reads it back (the fields Network already stores: machine, owner, models, hours, concurrency, credit price, audience, readiness and health), with the new optional `pool`.
972- Add `ai.offer-pool@1`, the `pool` part of the AI offer: `{ machines, head }`, two to eight machine ids and the head, which is the offer's own machine. Network adds it from its approved pool record, never from what a machine reports, and leaves a member's own offer out while it is in a pool. It names machines only: no address, key or certificate reaches AI. One price, audience, hours, idle-only and verification apply to the whole pool; AI verifies a pool's answers as it would one machine's, keys that verification on the exact membership, keeps a new or failed pool to the free tier only, and labels it "Community pool (N machines)".
973- `network.node.self.manage` names the five pool routes a machine calls with its own token (announce, read, approve, renew readiness, leave) in `implementedBy`.
974- Valid and invalid fixtures cover a pool waiting for approvals, an approved pool of three, a single-machine offer, a pool's offer and one still waiting, a group offer, a missing head or owner, a one-machine pool, a repeated member, a private key in the certificate slot, a public, loopback or wildcard address, a port under 1024, and an address, certificate or key smuggled into a field the schema does not name.
975
976## 0.308.0 — 2026-11-07
977
978- Add `ai.memory-export@1` (Memory M5): the one portable memory file. It carries `format: openvibe.memory-export@1`, `version: 1`, `exported_at` and every item's text, kind, scope, source, confidence and source reference. It deliberately has no ids, owners, merge links or conflict pair, so a file can be imported into another account without carrying anyone's identity, and a profile is derived from the items and rebuilt, never imported. OpenVibe.AI's `GET /api/v1/memory/export` writes it and `POST /api/v1/memory/import` accepts the same document; both redact again.
979- Valid and invalid fixtures cover an export with items and an empty one, a wrong format/version and a scope that is an absolute path instead of `user` or `project:<slug>`.
980
981## 0.305.0 — 2026-11-07
982
983- Give the id kinds the S7 work needs a prefix: `newId('agent_stream_schedule')` is `scd_…` (a scheduled public agent stream) and `newId('party')` is `pty_…` (a watch party's id when a party is not named by its room slug).
984- Add `live.agent-stream-schedule@1` (Agent Streams S7): an owner's schedule for a public agent stream — a time, a task template and the mode. Live starts it when the owner's desk is online; when the desk is not, the record says `missed` with `desk_offline` ("didn't start: the desk was offline") and nothing runs. A `chatplays` schedule keeps its time but waits for the owner's Go (`waits_for_go`), the S6 rule. The record carries the stream it started, its reminder count (the people who opted in, never who they are) and the page where it shows 24 hours before its time.
985- Add `chat.party@1` (Agent Streams S7): a watch party on a public agent stream or its VOD, a Chat room of kind `party`. On a VOD the position follows the host's; on a live stream it follows the live edge. A party is private by default, joining is by its link, and a listed party reaches the stream's page only as a count ("3 parties watching") — the count never carries names.
986- Extend `live.agent_stream.publish` with the schedule routes and the desk heartbeat: `POST|GET /api/streams/agent/schedules`, `DELETE /api/streams/agent/schedules/:id`, `POST /api/streams/agent/schedules/:id/remind`, `POST /api/streams/agent/schedules/:id/go` and `POST /api/streams/agent/desk/heartbeat`.
987- Valid and invalid fixtures cover a scheduled stream, a missed one with the desk offline, a chatplays schedule that waits for Go, a missing task and an unknown state; a private VOD party, a live party with a link, a party made public and a party with a room id that cannot exist.
988
989## 0.304.0 — 2026-11-06
990
991- Give the id kinds the Agent Streams work needs a prefix: `newId('agent_stream')` is `ags_…` (an agent stream's id), `newId('play_request')` is `req_…` (a chat plays request) and `newId('sandbox_session')` is `sbs_…` (the sandbox desk). Without them a service that had to name one of these ids had to build the ULID itself, and `newId('ags')` threw.
992
993- Add `chat.play-request@1` (Agent Streams S6): one viewer's request for the chat plays desk to build or do something. A request is written with `!do <request>` (at most 200 characters) in an agent stream's room, `agent:<ags_id>`; one open request per person at a time, and an account younger than a day cannot ask. The request carries its votes, its state (`queued`, `running`, `done`, `failed`, `skipped`, `removed` or `refused`), whether it is pinned, and the one-line reason it was refused (with the rule that refused it) when it was. A refused request carries no result; a finished one carries the outcome, the line the overlay and the voice said, and the scratch site the run left.
994- Add `codes.sandbox-session@1`: the sandbox desk a chat plays session runs on. The desk is started with `--shared` — no profile, no keys, no person's files, public egress only and a fresh workspace, wiped at the end — and the session carries the owner's time box (5 to 30 minutes), the step budget, the cap (money and minutes), what it has spent, whether the owner armed it with Go, and the throwaway scratch site with the 24 hours it lives. `egress_public_only` is always true: no private address is reachable.
995- `live.agent-stream-control@1` gains the control `wipe` (additive): Wipe now stops the run and resets the sandbox. The other four controls (pause, curtain, mute, end) keep their shape.
996- `live.agent-stream@1` gains the mode `chatplays` (additive; the enum already carried it): a chat plays stream is public or unlisted, and it works the room's queue.
997- Add the capabilities `chat.play_queue.read` and `chat.play_queue.write` for Codes, the task's service, acting for the stream's owner (a node token `on_behalf_of`), and name both in Chat's service manifest. Chat chooses what the queue holds: a request enters it only after the house text filters and the safety check, one open request per person at a time, and the people and the votes in it belong to the room.
998- Valid and invalid fixtures cover the queued, finished and refused requests, a request that is too long, a refusal without a reason, an unknown state, the armed and running sandbox sessions, a session with no cap, a time box outside 5 to 30 minutes, a sandbox that is not public-only, and the wipe control, so a missing field or a bad value fails the run.
999
1000## 0.303.0 — 2026-11-06
1001
1002- Add `chat.agent-digest@1` (Agent Streams S5): what a Co-pilot room said to an agent between two of its steps. The agent never reads the raw room: it asks Chat for a digest and gets at most ten items and 1,500 characters. Each item names who (the display name and the handle), what (cut to 200 characters), its kind (`question`, `suggestion` or `reaction`) and its upvotes; a repeated line is one item with the number behind it. Chat chooses what goes in (repeats grouped, greetings and spam dropped, the most-upvoted questions and suggestions first) and who is left out (a person who is timed out or banned, whose account is younger than a day, or who set 'Agents don't read my messages'). A link is kept as its domain only; the code and the commands stay as text.
1003- Add `chat.agent-poll@1`: the poll an agent asks a Co-pilot room to run, and the result it gets back — the question and the two to four options the agent wrote, the window it is open for, the state (`open`, `closed` or `vetoed`) and the counts. An open poll carries no result, a closed one carries its counts and its winner, a vetoed one names who refused it.
1004- Add `live.agent-stream-control@1`: one of the four controls the owner and the channel's moderators have over a live agent stream — `pause`, `curtain`, `mute` or `end` — with who pressed it (the handle and the role: owner or moderator) and when, and whose pause is in force.
1005- Add the capabilities `chat.agent_digest.read` and `chat.agent_poll.write` (first-party), and name both in Chat's service manifest. The caller is Codes or Actor, the task's service, acting for the stream's owner (a node token `on_behalf_of`), so a digest is the owner's room and nobody else's.
1006- `chat.preferences` is v2: it gains `agents_read_messages` ('Agents don't read my messages'). A v1 record upgrades with it true — joining a Co-pilot room and writing in it is the choice, and the person can take it back.
1007- `live.agent_stream.publish` now names the controls (`POST /api/streams/agent/:id/control`, `GET /api/streams/agent/:id/controls`) and the step credit: a step may name the suggestion it took.
1008- Additive: nothing that exists changes. Fixtures cover a digest over the ten-item cap, an unknown kind, a room that is not an agent room, a poll with one option and with five, an open poll carrying a result, an unknown control, a control with nobody behind it and a role that is neither owner nor moderator.
1009
1010## 0.302.0 — 2026-11-06
1011
1012- Add the capabilities `media.avatar.adopt` and `media.avatar.release` (internal), and name both in Media's service manifest. After the 2026-11-06 incident (eleven avatars were soft-deleted with the public screenshot copies), Media records which avatar object each profile slot points at, and its delete refuses an object a working profile still shows. A product (Network for `users.avatar_url`, Live for its own copy and the channel banner) records a slot with `POST /internal/avatar-adopt` and drops it with `POST /internal/avatar-release`.
1013- Add `media.avatar-adopt-request@1` / `media.avatar-adopt-result@1` (the slot: `object_id` `med_…`, `product`, `ref`, the optional `subject`; the answer is the active reference) and `media.avatar-release-request@1` / `media.avatar-release-result@1` (a slot, an object or a person; the answer counts the released references, 0 when there were none).
1014- Additive: nothing that exists changes. Fixtures cover a missing ref, an object id that is not `med_…`, a release that names nothing, a product without its ref and a negative count.
1015
1016## 0.301.0 — 2026-11-06
1017
1018- Add `live.agent-stream-state@2` (Agent Streams S4): the state the desk polls gains the voice (`mode` watch or narrated, the `voice`, the `personality` calm, hype, dry or roast, `muted`, `paused` with its reason), the newest `lines` to speak, and `captions_url` (the stream's WebVTT). `@1` is unchanged.
1019- Add `chat.tts-speak-request@1` and `chat.tts-speak-result@1`: the body and answer of `POST /api/agent-voice/speak` on OpenVibe.Chat (one line of at most 220 characters, an optional voice or the person's own; the audio, its MIME type and rate).
1020- Add the capability `chat.tts.speak`: a machine (a node token acting for its owner, `on_behalf_of`) asks Chat to speak a line in that person's chosen voice, never another person's. Chat's manifest names it.
1021- Additive: nothing that exists changes. Fixtures cover a missing text, a line over 220 characters, a missing audio and a wrong MIME type.
1022
1023## 0.300.0 — 2026-11-06
1024
1025- Add `report.session@1`: the report of one agent session, whatever ran it — a Codes task, an Actor task, a desk session or a session on a person's own machine (the Agent Streams plan, S3). It carries the id (`rps_<ULID>`), the owner (`usr_…`), the source (`codes`, `actor`, `desk` or `node`), the task (title ≤ 200 characters, the task's ref and its link back), the start and end, the worked seconds, the outcome (`done`, `stopped` or `failed`, with `stopped_because` in plain words when it did not finish), the summary (≤ 600 characters), the timeline (the steps, the same shape as `live.agent-stream-step@1`), the outputs (`pr`, `file`, `page`, `deploy`, `clip` or `vod`), the proof (the tests, the screenshots' media ids and the review's verdict), the cost and the models, up to five highlights, the agent stream it streamed on and the visibility (`private`, `unlisted` or `public`). The raw transcript, secrets and code are never in a report: the source service keeps the transcript for the owner, the house redactor runs over every text field before anything is stored, and a pull request is a link (its content shows only when the repository is public).
1026- Add `report.session-write-request@1` and `report.session-write-result@1`: the body of `POST /internal/session-reports` on OpenVibe.Report and what it answers. The route is idempotent per (source, task ref): the same session's task always answers the same report. The report's id is Report's own; the body never carries one. The write request's `stream_only` says a stream-only report (Live's, when no tool finished the session).
1027- Add the capability `report.session.write` (first-party) and name it in Report's service manifest. The caller is a first-party service — Codes, Actor or Live — with a service token that holds it for the audience `openvibe.report`.
1028- Valid and invalid fixtures cover the report, the write request and the write result, so a missing owner, an id that is not `rps_…`, an outcome outside the list or a URL that is not a Report page fails the run.
1029
1030## 0.299.0 — 2026-11-06
1031
1032- Add `live.agent-stream-step@1`: one step of the work an agent is doing on an agent stream (the Agent Streams plan, S2). It carries `at` (when the step began), `title` (at most 120 characters), `status` (`started`, `passed`, `failed` or `skipped`), the optional `detail` (at most 500 characters), the optional `tests` (`passed` and `failed`) and the optional `cost_usd`. The step is plain text: the house text filters have already run over it before Live stores it.
1033- Add `live.agent-stream-step-request@1`: the body of `POST /api/streams/agent/:id/steps` on OpenVibe.Live, which answers 201 with the step it stored. The publisher posts with its publish ticket, and Codes and Actor post through their service tokens with `live.agent_stream.publish` for the person; the capability is the one S1 named, so no new capability is introduced.
1034- Additive: nothing that exists changes. Valid and invalid fixtures cover both, so a missing title, a title over 120 characters, a detail over 500 characters or a status outside the list fails the run.
1035
1036## 0.298.0 — 2026-11-06
1037
1038- Add `live.agent-stream@1`: an agent's own stream on OpenVibe.Live (the Agent Streams plan, S1). It is a `managed_streams` row of kind `agent` with an `ags_<ULID>` id, no stream key and no normal slot; it carries the owner, the channel, the task it is doing (`codes`, `actor`, `desk` or `node`), the visibility (`private`, `unlisted`, `public`), the mode (`watch` in S1), the state, the curtain, the viewers, the worked seconds, the last frame, the VOD and the page. The card stays after the stream ends.
1039- Add the four request/result schemas: `live.agent-stream-create-request@1` (title, task, visibility, the optional `allow_sites`), `live.agent-stream-publish@1` (`whip_url`, the one-time publish ticket `wpt_…`, `expires_at`), `live.agent-stream-state@1` (viewers, `encode`, the curtain and `ends_at`, what the desk polls) and `live.agent-stream-curtain-request@1` (`up` and the reason).
1040- Add the event `live.agent_stream.changed` (`started`, `ended`, `visibility`, `curtain`, never the reason) and the capability `live.agent_stream.publish`, and name both in Live's service manifest. The stream's contract ids keep the design's hyphen (`live.agent-stream@1`); the capability and the event type carry an underscore because `identity.service-token-claims@1`'s `cap` pattern and `events.event-envelope@1`'s `event_type` pattern allow letters, digits and underscores only. The capability's description records the design's `live.agent-stream.publish` name and why it is written `live.agent_stream.publish`. `identity.service-token-claims@1`'s `on_behalf_of` description now says a node token names its owner on the audience where the machine acts for them (Live's), so a receiver knows where to read the stream's owner.
1041- Valid and invalid fixtures cover the stream, the create request, the publish part, the state, the curtain request and the event payload, so a missing field, a bad id or a reason outside the list fails the run.
1042
1043## 0.297.0 — 2026-11-06
1044
1045- Add `identity.subject-assertion-claims@1`: the claims of a short-lived ES256 assertion signed by OpenVibe.Network that says a person allowed one service to act for them on another service — `sub` (the person), `aud` (the service it is for), `act` (the service it was minted for), optionally `for` (the services that may carry it), `jti`, `iat`, `exp`. Network mints one only from the person's own access token (`POST /internal/subject-assertions`), so a service that merely knows a person's id cannot say the person allowed anything; the key is published in Network's JWKS (`kid ov-network-assertion-1`). The money routes of Billing and Tips check it against the person they act for, and refuse the old "the service vouches for its person" way once `BILLING_REQUIRE_SUBJECT_ASSERTION` / `TIPS_REQUIRE_SUBJECT_ASSERTION` is on. Only a service token Network issued for its own API (`openvibe.network`) mints one. See the ADR-003 amendment of 2026-11-06.
1046
1047## 0.296.0 — 2026-11-06
1048
1049- Sharing learns locked items. `share.update-request@1` gains `envelope`: a `locker.envelope@1`, base64, the content re-sealed for the people who stay, sent with the members that remain when someone is removed from a people-locked item. The service stores it before it drops the member; it never opens it.
1050- `share.transfer-request@1` gains `key_slot` (that recipient's people slot), required for a people-locked item and checked against the recipient's current key from the key directory.
1051- `share.member@1` gains `key_fingerprint` and `fingerprint_changed` (owner-only): the member's current eight-word fingerprint and whether it is still the key their slot was made for, so the share sheet can warn and re-wrap.
1052- Additive: every new field is optional and old documents stay valid. Fixtures cover the locked member, the locked member input, the re-seal request and a locked transfer, and a malformed slot is refused.
1053
1054## 0.295.0 — 2026-11-06
1055
1056- Add `sources.category@1`: one category of the sources registry and how long OpenVibe.Sources keeps its items (roadmap §3 F). The `retention` field is either `{ days, reason }` — the window an item lives after it was last current (its last fetch while live, its removal once removed) — or `"keep"`, for reference data that is never pruned by age (Sources keeps the newest row per source key and prunes only the rows a newer value replaced).
1057- The categories are the ones `sources.source@1` and `sources.item@1` already use; the three lists are compared in `test/run.js`, so a category added to one of them without the others fails the run. No existing schema changes: `sources.source@1`'s `category` and `sources.item@1`'s `category` keep their shape, so a consumer that reads them is unaffected.
1058- Valid and invalid fixtures cover a windowed category (`news`), a kept category (`housing`), an unknown category, a missing rule and a zero-day window.
1059
1060## 0.294.0 — 2026-11-06
1061
1062- Add the unsafe-image review capabilities: `vision.image.review` (Media, Community and Live sort an image or AI text into fine, sex acts or sexual content involving a minor), `vision.review.read` and `vision.review.decide` (the staff queue and an operator's decision), `media.object.review.view` (Vision's 60-second logged evidence view of a hidden or quarantined object) and `media.object.review.decide` (Vision applies an operator's overruling category and releases Media's evidence hold). The Vision and Media service manifests name them.
1063
1064## 0.292.0 — 2026-11-06
1065
1066- Add `locker.envelope@1`: the header of a sealed item — the suite (AES-256-GCM), the chunk size (1 MiB), the padded size, the counter nonce base, the lock kind and one key slot per way in. The content key is never in the header; it is wrapped in a people slot (ECDH P-256 + HKDF-SHA-256, bound to the recipient's key by its RFC 7638 thumbprint), a password slot (PBKDF2-SHA-256, 600000 iterations, the parameters in the header so they can be raised, and bounded above at 10000000 so a hostile header cannot freeze a reader) or a link slot (empty: the key travels in the link's fragment).
1067- The padded size is padded with Padmé (PoPETs 2019): at most about twelve per cent over the real size, never below 256 bytes, and it leaks O(log log n) bits. Every chunk but the last is a whole chunk; the last holds the rest.
1068- Add the key directory contracts: `locker.public-key@1`, `locker.public-keys@1`, `locker.keys-put-request@1`, `locker.key-backup@1` and `locker.key-change@1`, with the eight-word fingerprint (sixty-four bits, in two groups of four) and the signature that proves a person owns their signing key.
1069- `share@1` and `share.update-request@1` gain `lock` (`none`, `people`, `password`, `link`), and a share member may carry that member's key slot, so a member and its slot are saved together. Additive: the fields are optional and old documents stay valid.
1070- Valid and invalid fixtures cover every new contract, and the new fields of the sharing contracts. The format is written down in [docs/locker.md](docs/locker.md).
1071
1072## 0.291.0 — 2026-11-05
1073
1074- Add `share@1`: resource refs, audiences, members and member inputs, transfers, access requests, uniform API requests and responses. Transfers are recipient-bound, last seven days, and default to removing the former owner's membership.
1075- The uniform response names people: `share.person@1` on the owner, members, a pending transfer's `to` and each pending request; plus `share.you@1`, pending `requests` (`share.access-request-view@1`), the pending transfer view, and the service's `describe()` fields (`title`, `link`, `roles`, `audiences`, `transferable`). Add `share.people-lookup@1` for the exact-name people endpoint.
1076- PUT accepts `notify` (default true); access requests can be `dismissed`; a transfer request accepts `{ name }` or `{ subject }`.
1077- Add the five `share.*` event payloads with strict ids-only fields; Network owns the model, adopting services produce events using their own source. Valid and invalid fixtures cover every new contract. No existing schema changes.
1078
1079## 0.290.0 — 2026-11-05
1080
1081- **A comma-separated body, and an identity from several columns** (OpenVibe.Food's USDA ERS fruit and vegetable
1082 prices). An api endpoint of `sources.source@1` and `sources.source-write-request@1` may say `"format": "csv"`: a
1083 comma-separated file with RFC 4180 quoting (a UTF-8 BOM, a quoted field holding commas, doubled quotes and line
1084 breaks), whose first line names the columns, read as an array of records keyed by those names (`items_path` is "").
1085 `"identity_fields"` names two to eight columns whose values, joined in order with " | ", are the record's identity,
1086 for a table where no single column is unique (USDA ERS prices each product in several forms); it requires
1087 `items_shape` array and cannot be given with `fields.identity`. Additive: the existing formats, `duplicates` and
1088 `fields.identity` are unchanged, and an older reader ignores the new field. Valid fixture:
1089 `fixtures/sources.source/valid/api-csv-identity-fields.json`.
1090
1091## 0.289.1 — 2026-11-04
1092
1093- **`billing.credit-hold@1` answers a personal hold.** `project_id` is no longer required and its type is
1094 `[string, null]`, so the hold Billing sends after a personal `billing.credit-hold-create-request@1` (no
1095 `project_id`) validates. A project hold still carries its `prj_` id and an app subject still always names one.
1096 `compatibility/corrections.json` records the change against v0.289.0 because the compat gate treats the widened
1097 type as a retype; the string-only rule never described a personal hold's answer, since that case could not be
1098 produced validly. Valid fixture: `fixtures/billing.credit-hold/valid/personal-hold.json`.
1099
1100## 0.289.0 — 2026-11-04
1101
1102- **Balance and Vibes Pay (AI Exchange D12, MONEY.md build order step 1).**
1103 - **Vibes Pay schemas:** `billing.vibes-charge@1` (id `vch_<ULID>`, app, project_id, `amount` in whole Vibes,
1104 a 1–140 description, the app's reference, status pending|paid|refunded|expired|cancelled, pay_url, return_url,
1105 the timestamps and sandbox), `billing.vibes-charge-create-request@1` (`amount`, `description`, `reference` — the
1106 app's idempotency key — and an optional `return_url`) and `billing.vibes-charge-refund-request@1` (an optional
1107 `reason`; a refund is always for the whole charge).
1108 - **Vibes Pay events:** `billing.vibes.charge.paid@1` and `billing.vibes.charge.refunded@1` are also the signed
1109 webhook bodies (HMAC-SHA256, retried with backoff): the charge fields plus an opaque `payer_ref` that is stable
1110 per app, and deliberately no person id and no email. Billing's manifest lists both in `eventsProduced`.
1111 - **Balance:** `billing.balance@1` gains the D12 Balance branch — `owner` (user or project), `balance_nano_usd`,
1112 `held_nano_usd`, `available_nano_usd` and an optional `sandbox`, with money as integer nano-USD decimal strings
1113 (D1, never a float) — answered by `GET /api/me/balance`. The contract id is permanent, so the Vibes wallet body
1114 that `billing.balance.read` already answered stays as the second branch; both branches are closed with
1115 `additionalProperties: false`, and new code sends the Balance branch.
1116 - **Balance requests:** `billing.balance-transfer-request@1` (`to_project_id`, positive `amount_nano_usd`,
1117 `idempotency_key`) for moving a person's Balance to a project's, and
1118 `billing.vibes-purchase-from-balance-request@1` (`vibes` as a whole positive integer, `idempotency_key`) for
1119 Get Vibes with Balance.
1120 - **Vibes read:** `billing.vibes-wallet@1` is the person's own Vibes — credit, creator payable and bits_per_usd,
1121 never a Balance — answered by `GET /api/v1/vibes/me`.
1122 - **Capabilities:** `billing.vibes.charge` (public, grantable to apps, a sandbox app included, which charges
1123 sandbox Vibes only) implemented by `POST /api/v1/vibes/charges`, `GET /api/v1/vibes/charges/:id` and
1124 `POST /api/v1/vibes/charges/:id/refund`; `billing.vibes.read` (public, a person-delegated read of their own
1125 Vibes for an app they approved) implemented by `GET /api/v1/vibes/me`.
1126 - **Personal holds:** `billing.credit-hold-create-request@1` no longer requires `project_id`; without it the hold
1127 is personal and spends the subject's own Balance. An `app` subject must still name its project (`if`/`then`),
1128 so the accepted set only grows and the compat gate stays green.
1129 - Valid and invalid fixtures cover both Balance branches, whole-number Vibes, D1 decimal-string money, a personal
1130 hold, an app subject without a project, a partial-refund body, and webhook payloads with a person id or an
1131 email-shaped payer reference.
1132
1133## 0.288.0 — 2026-11-04
1134
1135- **Configuration contracts (AI Exchange D11, S1), built on openvibe-shared/config:
1136 `common.config-namespace@1`, `common.config-change@1` and `common.config-secret-put@1`** (internal).
1137 - `common.config-namespace@1` is the shape `openvibe-shared/config`'s `summary()` returns (`service`, `namespace`,
1138 `revision`, `values`, `classification`, `active`, `last_known_good`), plus `sealed`, `pins` and `schema`: whether
1139 a KEK seals secret values, the keys pinned by their `x-env` variable, and the namespace's JSON Schema so a client
1140 can draw the form. The annotations `title`, `description`, `x-group`, `x-env`, `x-danger`, `x-bind` and `x-unit`
1141 (`nano_usd`, `ms`, `bps`) are allowed.
1142 - A secret-class value in `values` is a marker (`redacted: true`, a keyed 64-hex `fingerprint`, and the optional
1143 four-character `hint`, `set_at`, `set_by` and `bound_to`); a marker that carries `value` is invalid, so a
1144 summary never carries a secret.
1145 - `common.config-change@1` is `{ values, reason, merge?, unset? }`; a secret value is refused by the store
1146 (`422 config.secret_write_only`) and is written only through the secret route.
1147 - `common.config-secret-put@1` is `{ value, reason }`; the answer is the marker.
1148- **Nine internal capabilities, one per service:** `ai`, `billing`, `services`, `watch`, `bench`, `report`, `host`,
1149 `codes` and `actor` each gain `<svc>.config.manage` (owner that service, active, internal, never grantable to apps),
1150 implemented by `GET /internal/config`, `GET|POST /internal/config/:namespace` and
1151 `PUT|DELETE /internal/config/:namespace/secrets/:key`. Only Network's admin proxy, acting for the owner, holds them;
1152 Network uses its own admin config routes.
1153- Contracts keeps no default-grants list: Network's seeded default grants live in OpenVibe.Network, so granting
1154 these nine to the network service is that repository's change.
1155
1156## 0.287.0 — 2026-11-04
1157
1158- **`billing.credit.settled@1`** (AI Exchange money, D1 and D9).
1159 - OpenVibe.Billing emits it from the settle transaction of a Credits hold (`server/ops/credits.js` `settleHold`);
1160 OpenVibe.Report consumes it for aggregate analytics.
1161 - It carries `settlement_id`, `hold_id`, the hold's `service`, `settled_at`, the answering attempt's
1162 `deployment_id` (`<provider>:<model>`, nullable) and `provider_access` (nullable), `rate_version`, the four
1163 `usage` token counts, `charge_nano_usd`, `supply_cost_nano_usd`, `shortfall_nano_usd`, `released_nano_usd`,
1164 `byok` and `sandbox`.
1165 - Deliberately no `subject`, no `project_id` and no account id: the event is for aggregates, while per-person
1166 statements are read from Billing.
1167 - Money is integer nano-USD as decimal strings (D1); a number amount and a subject field are invalid fixtures.
1168 - Billing's manifest lists the event in `eventsProduced`; Report's lists it in `eventsConsumed`.
1169- **`sandbox` on Credits holds: `billing.credit-hold@1` and `billing.credit-hold-create-request@1`** (D10, additive).
1170 - An optional boolean `sandbox` (default false) says the hold draws on that person's sandbox credit for the project
1171 (account kind `usd_credit_sandbox`, owner `subject:project`), never on real Credits; a real hold never draws on
1172 sandbox credit.
1173 - `billing.credit-sandbox-grant-request@1` now says its grants land in that sandbox account.
1174 - Valid fixtures cover `sandbox: true`; `sandbox: "yes"` is invalid.
1175
1176## 0.286.0 — 2026-11-04
1177
1178- **Provider-rate evidence events: `watch.rate.changed@1`, `watch.rate.approved@1`, `watch.rate.rejected@1`**
1179 (OpenVibe.Watch #205, plan P6, flag `WATCH_PROVIDER_RATES` off by default).
1180 - `watch.rate.changed` is raised when a provider's official price document states a new value for one model and
1181 token class. It carries `change_id`, `source_key`, `provider`, `model`, `token_class` (`input`, `cached_read`,
1182 `cache_write`, `output`), `from_nano_usd_per_m` (null for a first price), `to_nano_usd_per_m`, `currency`,
1183 `region`, `effective_date`, `source_url`, `fetched_at` and `approval_required`.
1184 - `watch.rate.approved` and `watch.rate.rejected` are the same change plus `state`, `decided_by` (a person's
1185 `usr_` id; Watch refuses a service or an agent), `decided_at` and `applied` (always false).
1186 - Money is integer nano-USD per million tokens as decimal strings (D1); all three schemas refuse numbers and floats.
1187 - Evidence only: Watch writes no rate card. An approval is dated evidence for OpenVibe.AI's catalog operator, who
1188 alone changes the supply rate card through AI's own path.
1189 - Watch's service manifest now lists the three events in `eventsProduced`. OpenVibe.AI consumes no events yet
1190 (`eventsConsumed` is empty), so it is not registered as a consumer.
1191
1192## 0.285.0 — 2026-11-03
1193
1194- **`ai.inference.create` is retired** (AI Exchange D8′).
1195 - It duplicated `ai.app.run`, the public capability developer apps already use to call OpenVibe AI (ADR-014, on
1196 `/v1/chat/completions` and `/v1/messages`).
1197 - It was added in 0.284.0, and was never granted or served.
1198
1199## 0.284.0 — 2026-11-03
1200
1201- **AI Exchange contract foundation (D1-D4, D8)**:
1202 - `ai.model@1` extended to a catalog entry with optional `id`, `family`, `variant`, `quant`, `revision`, `sha256`, `license`, `context`, `capabilities`, `modalities`, `retail_rate` (nano-USD per million tokens) and `availability`; existing provider-model documents stay valid.
1203 - New schemas: `ai.model-artifact@1`, `ai.inference-deployment@1`, `ai.route-explain@1`, `ai.model-list@1`, `ai.model-read-result@1`.
1204 - New Billing inference subledger schemas: `billing.credit-hold@1`, `billing.credit-settlement@1`, plus internal route contracts for `POST /internal/credits/holds`, `/holds/:id/extend`, `/holds/:id/settle` and `/holds/:id/release`.
1205 - `platform.rate-card@1` compatibly extended with optional `side` (`supply`|`retail`), `version` and `effective_to`; existing documents stay valid.
1206 - New public capability `ai.inference.create` for developer-app inference on `POST /v1/chat/completions` and `POST /v1/messages`, and public capability `ai.model.read` for `GET /v1/models` and `GET /v1/models/:id`.
1207 - All new schemas ship valid and invalid fixtures, including wrong money type and float money value examples.
1208
1209## 0.283.0 — 2026-11-03
1210
1211- **`chat.timeline-result@1` buckets may say how many people wrote** (`people`, optional): a signed-in user, an
1212 anonymous viewer or a relayed name each count once. OpenVibe.Live's VOD clip cutter reads it as "a reacted room"
1213 (item 151, C08: 12+ messages from 3+ people before an AI clip can be public); without it the count is unknown and the
1214 clip stays unlisted. The description now says what Chat already does since Chat #338: Live's own AI viewers
1215 (`source_platform` ai) are not counted. Optional, so older readers and writers are unaffected.
1216
1217## 0.282.0 — 2026-11-03
1218
1219- **`connect.hook.received@1`** (OpenVibe Connect, CON-15, ADR-057 decision 7): a webhook reached a share's hook at
1220 `https://connect.openvibe.website/h/<hook_id>`. Connect keeps the request (body and headers, 7 days) by reference and
1221 publishes only a pointer (`body_ref`, method, size, content type), never a body, header or address. Events keeps the
1222 event and retries Connect's own subscription for up to seven days, so the request reaches the person's computer once
1223 it is back. Connect's manifest now produces it and consumes it, along with the account events it already handled.
1224
1225## 0.281.0 — 2026-11-03
1226
1227- **Two legal profiles: `public` and `service`** (`registry.service-manifest@1` and `registry.product@1`
1228 `legalProfile`, openvibe-shared 4.107.0). `public` is an open, read-only site with no account. `service` is a personal
1229 tool or API that keeps what you make with your account. Ten sites served no `/terms`, `/privacy` or `/dmca` because
1230 no profile told the truth about them (the 11-02 sweep). Their manifests move:
1231 - `public`: Domains, Report and Search;
1232 - `service`: AI, Bench, Design, Events, OpenRestream, Surf and Watch (and AI's product manifest).
1233
1234## 0.280.0 — 2026-11-02
1235
1236- **`today.agenda.read`** (first-party, owner today; plan L48 V3, "plan my day"): a first-party service names a
1237 person with X-OV-Subject and reads that person's own agenda (`GET /api/v1/me/agenda`), the same one they see at
1238 openvibe.today/me. Read-only. OpenVibe.Chat's Vibe reads the day before suggesting a plan, and sets nothing until
1239 the person says yes. Schemas `today.agenda-request@1` (the `days` query) and `today.agenda@1` (from, to, days,
1240 events, follows_unavailable), with fixtures.
1241
1242## 0.279.0 — 2026-11-02
1243
1244- **Website Connect v0: OpenVibe Connect is live** (CON-1 landed with the OQ-13 review; ADR-057 accepted). The nine
1245 CON-1 contracts join the catalog, all additive: `website.share@1`, `website.share-create-request@1`,
1246 `website.share-connect-request@1`, `website.policy@1`, `website.audit-entry@1`, `connect.device@1`,
1247 `connect.policy@1`, `events.hook@1` and `events.hook-delivery@1`, with valid and invalid fixtures. Id prefixes
1248 `shr`, `dev`, `hok`, `pol` and `aud`.
1249- **`manifests/services/connect.json`** (live, connect.openvibe.website, port 5240, ov_connect, site position 51 in
1250 "make") replaces CON-1's placeholder `website.json`: one id, `connect`, for the repository, ovhost, the database and
1251 the OAuth client. It owns `website.*` and `connect.*`; the 20 capabilities stay `planned`, now owned by `connect`,
1252 and none is served or granted.
1253- **ADR-057's review** decides v0: the WebSocket fallback through Cloudflare inside Connect (no UDP, no DNS-only
1254 record), names `<label>--<user>.openvibe.website` (Space names never contain "--"), a share-scoped connect key until
1255 the Link plugin, the gate's host-only signed cookie, modes owner/named and staff-first signin, no public shares
1256 until CON-9 and CON-21.
1257
1258## 0.278.0 — 2026-11-02
1259
1260- **`live.index_document.upserted` v1 takes type `doc`** (expand only): one of Live's guides, `openvibe.live/docs/<name>`
1261 (for instance go-live-in-your-browser), as an OpenVibe.Search document. Its id is the guide's name
1262 (`^[a-z][a-z0-9-]{1,63}$`); channel, vod and clip keep their numeric ids. Live's guides were on no network search.
1263 Fixtures: `doc` (valid), `doc-bad-name` (invalid).
1264
1265## 0.277.0 — 2026-11-02
1266
1267- **`bot.command@1` kind `ai` carries tool calls** (expand only; plan L55 C3, "a local model on your Node"). The value
1268 may add `tools` (up to 64 OpenAI Chat Completions function definitions) and `tool_choice` (`auto` | `none`);
1269 messages may be `role: tool` with `tool_call_id`, and an assistant message may carry the `tool_calls` the model
1270 asked for in an earlier answer. The answer's data adds `message.tool_calls` and `finish_reason`. The machine passes
1271 the tools to its model server and hands back the calls; it never runs one. A machine whose Link can pass them says
1272 `ai.tools: true` in its capabilities (Link v0.36.0), so a caller sends tools only to such a machine. Older commands
1273 validate as before. Fixtures: `ai-chat-tools` (valid), `ai-tool-without-call-id` and `ai-tool-bad-name` (invalid).
1274
1275## 0.276.0 — 2026-11-02
1276
1277- **Taglines end without a full stop, every one.** 29 service and product manifests' `tagline` ended with one and
1278 the other ~45 did not, so the site switcher (Shared's `icons/sites.json`, built from these) and the share cards
1279 mixed both. A tagline with two sentences keeps the one in the middle ("Upload anything. Share it anywhere"). No
1280 schema or field changes.
1281
1282## 0.275.0 — 2026-11-02
1283
1284- **`report.index_document.upserted` / `.deleted` v1** (active, first-party; plan T9): OpenVibe.Report's Rundown
1285 topic pages (type `topic`, `/rundown/t/<slug>`) as OpenVibe.Search documents: the title, headline and summary of
1286 what streamers said. Live's own topic pages are noindex; Report's are the public copy. 60 topics were on no network
1287 search.
1288- **`design.index_document.upserted` / `.deleted` v1** (active, first-party): OpenVibe.Design's icon pages (type
1289 `icon`, `/icons/<name>`) and theme pages (type `theme`, `/t/<slug>`). 280 icons and 50 themes were on no network
1290 search.
1291- Both are sent through `openvibe-publishing/search-feed`; the Report and Design manifests list them in
1292 `eventsProduced`; the catalog has their entries and fixtures.
1293
1294## 0.274.0 — 2026-11-02
1295
1296- **`tours.index_document.upserted` / `.deleted` v1** (active, first-party; plan T9): OpenVibe.Tours' pages as
1297 OpenVibe.Search documents. A place to see (type `place`, `/place/<plc_ id>`, from OpenStreetMap: its kind, city and
1298 access facts), a city (type `city`, `/city/<slug>`: its Wikivoyage summary, how many places and walks) and a
1299 self-guided walk (type `route`, `/routes/<rte_ id>`: stops, distance and time). Sent through
1300 `openvibe-publishing/search-feed`; the Tours manifest lists them in `eventsProduced`; the catalog has their entries
1301 and fixtures. 2,754 places, 100 cities and 170 walks were on no network search.
1302
1303## 0.273.0 — 2026-11-02
1304
1305- **`shoes.index_document.upserted` / `.deleted` v1** (active, first-party; plan T9 "Search: real documents from every
1306 product"): a shoe model's page on open.shoes (type `shoe`, `/shoe/<slug>`, the slug as the id) as an OpenVibe.Search
1307 document: its name and brand, the lowest price seen today and how many stores sell it. Sent by OpenVibe.Shoes through
1308 `openvibe-publishing/search-feed` (a boot sweep and a timer; a model with no live offer is a `thin_content` noindex
1309 document, one that left the catalogue a tombstone). The Shoes manifest lists them in `eventsProduced`; the catalog
1310 has their entries and fixtures. Network searches for a shoe ("nike air max 90") found deals and coupons but never the
1311 model's own page with every store's price.
1312
1313## 0.272.0 — 2026-11-01
1314
1315- **`network.dock.timer.write`** (active, first-party; plan L48 R2): a first-party service sets or clears ONE
1316 person's Dock timer in the Network, so Vibe can start a focus timer where the person is
1317 ("Vibe, start a 25-minute focus timer"). `PUT /api/v1/people/:subject/dock/timer` takes
1318 `network.dock-timer-request@1` (the minutes, or `clear: true`) and answers `network.dock-result@1`. The
1319 service names the person and writes the timer and nothing else. The first holder is OpenVibe.Chat.
1320
1321## 0.271.0 — 2026-11-01
1322
1323- **`network.dock-state@1`** gains an optional `timer` (plan L48 R2): a timer, a focus block or the break after one,
1324 with its end, so it counts down in the Dock's pill on every site and rings at its end; a focus timer of rounds
1325 alternates focus and break by itself. Additive: absent or null is none.
1326
1327## 0.270.0 — 2026-11-01
1328
1329- **`network.dock-state@1`**: the Dock's tab may be `vibe` too (plan L48 V2: the person's Vibe in the Dock on every
1330 site, openvibe-shared 4.74.0). Additive: the three tabs before it are unchanged.
1331
1332## 0.269.0 — 2026-11-01
1333
1334- **`actor.model.manage`** (active, first-party, sensitive; plan L55 C3): a person chooses the model their OpenVibe.Actor
1335 tasks run on — OpenVibe's own keys, or their own provider key (which stays sealed in OpenVibe.AI and never reaches
1336 Actor). `GET /api/v1/me/model` reads the choice, `PUT /api/v1/me/model` sets it (`actor.model-manage-request@1`,
1337 answered by `actor.model-manage-result@1`). The person's choice alone: another person's is 404.
1338
1339## 0.268.0 — 2026-11-01
1340
1341- **`bot.machine.watch_link`** (active, first-party, sensitive; plan L55): the owner's agent (OpenVibe.Actor) asks Bot
1342 for a link that shows the desk it works on (the private desk or its own `desk-<name>`, never the owner's own screen),
1343 live, inside a chat turn. `POST /api/v1/machines/:id/watch-links`
1344 (`bot.watch-link-request@1`, answered by `bot.watch-link-result@1`) makes one for the machine the named person owns —
1345 never another person's — and it lives for 5 to 240 minutes. The page needs no sign-in (the token is the credential),
1346 may sit in a frame on openvibe.chat or openvibe.actor, and carries the mouse and keyboard only when the caller asks
1347 for it. Only the owner's agent may make one: the capability alone would let any service that holds it name any
1348 person.
1349
1350## 0.267.0 — 2026-11-01
1351
1352- `today.reminder.write` (active, first-party; plan L48): a first-party service sets, lists, snoozes, stops and removes a
1353 person's own reminders on OpenVibe.Today for that person, named with X-OV-Subject (`POST /api/v1/reminders/parse`,
1354 `GET|POST /api/v1/reminders`, `POST /api/v1/reminders/:id/done|snooze`, `DELETE /api/v1/reminders/:id`). The first
1355 holder is OpenVibe.Chat, for Vibe's "remind me…".
1356
1357## 0.266.0 — 2026-10-31
1358
1359- **`space.app.claimed`** (plan 5.9, OpenVibe.Space): a guest draft (a space with no owner, edited with a secret
1360 link, made on openvibe.space without an account) was claimed by a signed-in person. The draft is that person's
1361 space now, with an address from its name, and the secret is gone. The payload holds the space's id, its new slug,
1362 its name and the template it started from — never the secret, never file contents. Visibility internal, owner
1363 `space`, ADR-004 (Space's events).
1364
1365## 0.265.0 — 2026-10-31
1366
1367- **OpenVibe.Tours** (`manifests/services/tours.json`, plan 5.12): openvibe.tours, cities, places and walking routes
1368 from Wikivoyage and OpenStreetMap, IRL streams, stays and shared trips. Port 5170, OAuth client `tours`, site
1369 position 49 in the streams neighbourhood.
1370- **OpenVibe.Shoes** (`manifests/services/shoes.json`, plan 5.6): open.shoes, shoe offers from Deals with price
1371 history, a cited drops calendar and price alerts. Port 5180, OAuth client `shoes`, site position 50 in the shop
1372 neighbourhood.
1373
1374## 0.264.0 — 2026-10-31
1375
1376- **OpenVibe.Casino** (`manifests/services/casino.json`, plan 5.14): openvibe.casino, the Casino room. Open engines for
1377 blackjack, roulette, baccarat, craps and slots with their house edges checked against the published figures, tables
1378 with free play chips worth nothing, Learn and a simulator. No real money, no operators, no affiliate links. Port 5210,
1379 OAuth client `casino`, namespaces `casino.*`, site position 48 in the games neighbourhood, legal profile `games`.
1380
1381## 0.263.1 — 2026-10-31
1382
1383- **openvibe.website is Space's own front door** (plan 5.9; the owner, 10-31: the new domains "just redirect"). Space
1384 now answers the apex itself with OpenVibe.Website's home and its website templates, so `openvibe.website` joins
1385 `space`'s `domains` (Network's CORS allow-list and Space's reserved custom domains read that field; only the exact
1386 origin, never a tenant subdomain). The product manifest is no longer `kind: "moved"`: its description, pillars,
1387 questions and links say what the front door is, with the room's accent.
1388
1389## 0.263.0 — 2026-10-31
1390
1391- **`report.ai-usage-me-result@2`** (plan L41 R1, OpenVibe.Report): GET `/api/v1/me/ai/usage` as the route now
1392 answers it. The body is `{ group, rows, totals, by_paid_by, insights, source }`: `rows` are one bucket each
1393 (`day`, `week`, `month`, `provider`, `model`, `surface` or `paid_by`) with `key`, `calls`, `input_tokens`,
1394 `output_tokens`, `cached_tokens`, `cache_write_tokens`, `cost_usd`, `fee_usd`, `charged_usd` and `saved_usd`;
1395 `totals` repeats those measures for the window; `by_paid_by` holds the same measures for each payer
1396 (`own_key`, `openvibe_key`, `plan`, `own_machine`, `free_tier`, `network_allowance`, `org_key`); `insights` are
1397 two or three plain lines worked out from the numbers; and `source` is `raw`, `rollups` or `raw+rollups`.
1398- **Breaking shape:** v1's `usage` array and its `input`/`output`/`reasoning`/`cache_read`/`cache_write`/
1399 `list_cost_usd`/`cache_saved_usd` field names are gone, so v1 is deprecated in favour of `@2` and stays
1400 loadable until 1.0.0. The v2 TypeScript type is `ReportAiUsageMeResultV2`.
1401
1402## 0.262.0 — 2026-10-31
1403
1404- **The task-aware router's explain** (L33 P3 "the router picks for the task", L36 Y7 "a smarter router";
1405 OpenVibe.AI). `ai.run@1` (1.1.0) gains an optional `explain`: why the run answered as it did.
1406 - `task`: the requirement set the router read off the request with no model call — `vision`, `tools`, `json`,
1407 `min_context` (tokens), `reasoning` (none, some, deep), `output` (text, image, audio, video) and `weight`
1408 (light, standard, heavy).
1409 - `ranked`: the candidates the router ranked for that task, best first (at most five), each with its reason
1410 (the cheapest with vision, the strong tier, warm cache), its price and its catalogue tier.
1411 - `attempts`: every provider that was tried, why it was chosen and what went wrong when it failed.
1412 - `objective`, `reasons`, `selected`, `candidates` and `paid_by`: the placement view the ranking came from and
1413 who paid. `bench` and `usage_readings` stay the optional projections they are.
1414 - Nothing else changed: the release is additive, the contract's own id and major stay, and no tag is cut yet.
1415
1416## 0.261.0 — 2026-10-31
1417
1418- **The machines hub** (plan L34, steps M2 and M4). A person's computers are the network's: Bot stays the device
1419 registry underneath, and Network fronts it on openvibe.link/machines for the person and for apps the person
1420 consented to.
1421 - **`network.machine@1`:** one machine as the hub shows it — its id (Bot's `dev_…`), name, kind, os, whether it is
1422 online, when it was last seen, its `roles` and what it does right now (`running`: its Codes jobs, its desks, its
1423 local models, its robots).
1424 - **`network.machine-roles@1` and `network.machine-role@1`:** the catalogue of roles. Each role has a name, what it
1425 installs on the machine and what the hub shows. A product declares its roles in its own service manifest
1426 (`machineRoles`), so the catalogue is the union of what the products declare: `codes.worker` (Codes), `desks.host`
1427 (Run), `ai.host` (AI) and `bot.robot` (Bot) are the first four.
1428 - **`network.machine-roles-put@1`:** the roles a machine has after a change — the whole set, not a diff.
1429 - **`network.machine-pairing@1`:** a one-time pairing code, its expiry and the command to run on the machine.
1430 - **`network.machine-list-result@1` and `network.machine-manage-result@1`:** what the hub answers with.
1431 - **`bot.machine-manage-request@1` and `bot.machine-manage-result@1`:** what Bot's machines API takes and answers
1432 with. `bot.device@1` gains `roles` and `os` (both optional; the old shape still holds).
1433 - **The capabilities:** `network.machines.read` and `network.machines.manage` (owner `network`, public: an app may
1434 hold them with the person's consent, and may then do only what the person could) and `bot.machine.manage` (owner
1435 `bot`, first-party: Network holds it for the hub, so Bot stays the authority and checks the machine is the named
1436 person's own).
1437 - **The events:** `network.machine.online`, `network.machine.offline`, `network.machine.paired`,
1438 `network.machine.roles_changed` and `network.machine.revoked` — Network publishes them through OpenVibe.Events.
1439 - **Presence policy:** `network.machine.online` and `network.machine.offline` are a machine's connectivity (the
1440 machines hub, plan L34), not a person's presence, and are allowed like `bot.robot.online` and `bot.robot.offline`
1441 (ADR-043). Any other `.online`, `.offline` or presence event type is still refused.
1442 - **`registry.service-manifest@1` gains `machineRoles`** (optional): the roles a product declares. The manifest
1443 keeps its old shape; a manifest without the field means a product with no machine role.
1444
1445## 0.260.0 — 2026-10-31
1446
1447- **One AI meter across the network** (plan L40): every AI call on the network leaves one usage record, whoever made it.
1448 - **`ai.call.recorded@1`** (`contracts/events/payloads/ai.call.recorded.v1.json`): one call, and who and where it
1449 happened (`subject`, `attribution`, `surface`), what ran (`system`, `provider`, `model`, `effort`), who paid
1450 (`paid_by`: `own_key`, `openvibe_key`, `plan`, `own_machine`, `free_tier`, `network_allowance`, `org_key`, with
1451 `paid_by_detail`), the tokens (`input` uncached, `output`, `reasoning`, `cache_read`, `cache_write` with
1452 `cache_write_ttl` `5m` or `1h`, `images`, `audio_seconds`, `video_seconds`), the money in USD (`list_cost_usd`,
1453 `charged_usd`, `fee_usd`, `cache_saved_usd`, with `price_source` and `price_date`), how it went (`latency_ms`,
1454 `ttft_ms`, `attempts`, `outcome`) and the ids (`run_id` or `turn_id`, `at`).
1455 - **No prompt and no answer text, ever.** The payload has no field for either, and the schema closes the object.
1456 - **The meter belongs to OpenVibe.Report** (plan L40 and L41): OpenVibe.AI writes the records, Report keeps the ledger
1457 and rolls it up.
1458 - **`report.ai-usage-open-result@1`**: the public AI totals (tokens, the cache share, the own-key share, the spend by
1459 week). No person, no site and no key in it.
1460 - **`report.ai-usage-result@1`**: the same meter in groups (day, site, model, system, paid_by) for a service token with
1461 the new **`report.ai_usage.read`** capability. A group that fewer than ten people share reads 'fewer than 10'
1462 instead of counting them.
1463 - **`report.ai-usage-me-result@1`**: the AI usage of one person (GET /api/v1/me/ai/usage), for the person and nobody
1464 else. The route answers 501 until Report has sign-in; the shape is fixed here first.
1465 - Phase 1 is OpenVibe.AI's own runs; Codes, Actor and the rest feed the same event later. Report rolls the
1466 records up, and a record taken twice is stored once (idempotent by `system` and `run_id` or `turn_id`).
1467
1468## 0.259.0 — 2026-10-31
1469
1470- **`network.notification-push-request@1` addresses a person by subject as well as by user id (F1, familiar faces).**
1471 Vision sends a named person a consent request and Cam sends the camera owner an event alert; both know the
1472 canonical `usr_` subject from the token and never hold the numeric Network user id. `POST
1473 /internal/notifications/push` accepts `{ subject }` as an alternative to `{ user_id }` (unknown subject: 404), and
1474 `POST /internal/notifications/push-bulk` accepts `{ subjects }` as an alternative to `{ user_ids }` (unknown
1475 subjects are skipped). The rest of the body and every other rule is unchanged; `subject` is not the actor
1476 (`actor_subject` still carries the block check). Two valid fixtures prove the subject forms.
1477
1478## 0.258.0 — 2026-10-31
1479
1480- **Labels and choices** (L1, `OpenVibe_Consent_Plan_2026-10-31.md` §"Labels and choices"): light rules, not bans.
1481 - **`common.content-labels@1`:** the six labels (`nudity`, `language`, `graphic`, `18+`, `flashing`, `spoilers`)
1482 and the shape `{ labels, suggested }` for a stream, VOD, clip, picture or post. `labels` are in force (the
1483 creator, a moderator, or three viewer suggestions); `suggested` is what the AI or a viewer proposed and nobody
1484 confirmed, so a suggestion never applies itself and never takes anything down.
1485 - **`network.label-prefs@1`:** one person's choice per label — `show`, `blur` (until tapped) or `hide` — in
1486 Network's site prefs, so one setting covers every site. The web default is `show`; the native apps start
1487 `nudity` and `18+` at hide until the person turns them on in their web settings. The home page shows nothing
1488 labelled `18+` whatever the prefs say.
1489 - **`labels`** is exported from the package (`LABELS`, `CHOICES`, `INFO`, `defaults()`), so a service reads the
1490 one list instead of copying it. `test/content-labels.test.js` checks that every list matches and that the
1491 fixtures hold the rules the schemas cannot say.
1492
1493## 0.257.0 — 2026-10-31
1494
1495- **"Your AI": a person's own provider keys, and how their runs route** (L36 Y1/Y3/Y8; OpenVibe.AI). Five additive
1496 v1 contracts and one event:
1497 - **`ai.me-credential@1`:** one key as its owner reads it — provider, a four-character hint, base_url, daily budget,
1498 status (`ok`, `failing` or `untested`), checked_at, a redacted last_error, models_count and created_at. Never the
1499 key.
1500 - **`ai.me-credential-put@1`:** `PUT /api/v1/me/credentials/{provider}` for the providers the console knows
1501 (Anthropic, OpenAI, Gemini, DeepSeek, Mistral, xAI, Groq, Cerebras, Together, Fireworks, OpenRouter, MiniMax and
1502 a custom endpoint). A key is required the first time and when the endpoint changes, and is tested on save.
1503 - **`ai.me-credential-test@1`:** the model list (up to five samples) or a one-token request, the balance when the
1504 provider reports one, and a redacted error that never carries the key.
1505 - **`ai.me-credential-list@1`:** `GET /api/v1/me/credentials`, every key without any key.
1506 - **`ai.me-preferences@1`:** `GET/PUT /api/v1/me/ai/preferences` — only_my_keys, free_first, a price ceiling and a
1507 default model (or `auto`) per kind of work.
1508 - **`ai.credential.failed@1`:** a provider refused a person's key with 401/403 during a run; its status becomes
1509 failing and the event says so, never the key.
1510- **Two person capabilities**, `ai.me.read` and `ai.me.manage`: only the person's own Network token, or the person
1511 session on AI's own site behind a same-origin check, reaches them. A service token is refused, and so is any token
1512 carrying `on_behalf_of`, whatever capabilities it holds (the AI #204/#205 rule).
1513
1514## 0.256.0 — 2026-10-31
1515
1516- **`ai.looks` is retired** (`network.consent@1`). The owner removed the rule that AI text never describes people
1517 (2026-10-31), so describing how someone looks needs no opt-in. The value stays in the family's lists so readers of
1518 0.255.0 still validate (removing it is a breaking change); nothing writes it, and Network offers it on no page.
1519
1520## 0.255.0 — 2026-10-31
1521
1522- **Data and AI by consent** (L24, the consent plan `OpenVibe_Consent_Plan_2026-10-31.md`): nothing a person makes is
1523 off-limits to AI or data use by design; each use is off until that person turns it on.
1524 - **`network.consent@1`:** one person's choice for one purpose (`ai.train`, `data.public`, `face.recognize`,
1525 `ai.looks`, `app.data`), narrowed by kinds of content, an app and options (a licence, face features). It records
1526 the wording seen (`text_version`), where it was made, and `granted_at`, `revoked_at` and `expires_at`. A choice is
1527 turned off by revoking it, never by deleting it. The id prefix is `cns_`.
1528 - **`network.consent-choice@1` and `network.me-consent-result@1`:** "Your data choices" (`GET` and `PUT
1529 /api/v1/me/consent`, capability `network.consent.manage`).
1530 - **`network.consent-check-request@1` and `network.consent-check-result@1`:** a service asks before each use, for up
1531 to 500 people (`POST /internal/consent/check`, capability `network.consent.read`, first-party). An unknown person is
1532 false, like one who never chose. Network unreachable means off.
1533 - **`network.consent.changed`:** drops cached answers. It names the change, never the content.
1534 - **No purpose sells data.** That needs its own contract and a yes for each deal.
1535
1536## 0.254.0 — 2026-10-30
1537
1538- **`actor.wait@1`** (plan A2, Watch mode; the design note `research-2026-10-30/agent-a2-watch.md`): one wait — the
1539 task and the step it belongs to, whose it is, what wakes it (`until`: an Events topic, a Watch target or a time),
1540 the deadline, `on_timeout` (`ask`, `retry`, `fail`) and the short line the person reads. A wait is a record, not a
1541 running loop: while a task waits no model runs, its desk is released and its budget clock stops. The event that woke
1542 it is untrusted input and is never part of the record; `woken_by` names the event, never its payload.
1543- **A new id prefix**: `wait` → `wai_`, the id a wait carries (`ids.newId('wait')`).
1544
1545## 0.253.0 — 2026-10-30
1546
1547- **A2A for OpenVibe.Actor** (Actor v2 stage V2-11). New capability `actor.a2a.task` (owner `actor`, active,
1548 first-party, sensitive): a Network service token with it may hand Actor one agent-to-agent task
1549 (`POST /a2a/v1/tasks`, the A2A message shape: text parts, an optional skill). The task runs under the person's
1550 allowance, budget and allow-list, exactly like a task they started; anonymous callers get 401 and a token
1551 without the capability 403. The agent card is `/.well-known/agent.json`.
1552- **Two additive v1 contracts** (new files, no existing schema changed): `actor.a2a-task-request@1` and
1553 `actor.a2a-task-result@1`.
1554## 0.252.0 — 2026-10-30
1555
1556- **Memory M2 capabilities and contracts** (OpenVibe.AI; plan `OpenVibe_Memory_Plan_2026-10-30.md`, spec
1557 `research-2026-10-30/memory-m2-spec.md`).
1558 - New active first-party capabilities `ai.memory.read` and `ai.memory.write`, owned by `ai`: the person's own API
1559 reads and writes, and a service acting `on_behalf_of` a person with the capability (agent search is at most 8
1560 active items in the scopes its grant names, audited in `memory_reads` with ids only, never text).
1561 - Three additive v1 contracts: `ai.memory-item@1` (one decrypted item as its owner reads it), `ai.memory-result@1`
1562 (the list, item, profile, deletion count and agent search answers) and `ai.memory-write-request@1` (the batch
1563 import, the patch and the source deletion). The sealed fields (`text_enc`, `text_mac`, `source_ref_enc`) are never
1564 in a response, and the text is never logged.
1565
1566All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) that consumers install
1567from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
1568the notes were in the tag and commit messages (`git tag -n1`).
1569
1570## 0.251.0 — 2026-10-30
1571
1572- **`network.dock-state@1`** (the Dock plan 2026-10-30, K-D1): the state of one person's Dock — the little floating
1573 surface every OpenVibe site draws. It lives in the Network, not in the browser, because `localStorage` is per site and
1574 the Dock follows the person across every domain. `open` (open or collapsed to its pill), `tab`
1575 (`agent` | `chats` | `activity`), `pinned` (keep the pill even when nothing runs or waits), `agent`
1576 (`{ service: actor|codes|run|desks, id }` or null — the agent the Agent tab follows), `chat` (the conversation the
1577 Chats tab has open, or null), `place` (where it sits per device class: a `corner` for the phone, a `corner` plus an
1578 optional `width` (320..720) and `height` (360..900) for the desktop) and `updated_at`. Every object refuses extra
1579 keys, so a page cannot smuggle a field into the state another page reads.
1580- **`network.dock-result@1`** (the Dock plan 2026-10-30, K-D1): what `GET /api/v1/me/dock` answers on OpenVibe.Network
1581 — the person's `network.dock-state@1`, the `counts` the pill's status dot is drawn from (`running`, `waiting`,
1582 `unread`) and `sources_partial` (true when an authority behind the counts did not answer, so the counts are lower
1583 than the truth). Additive: two new contracts, nothing changed or removed.
1584
1585## 0.250.0 — 2026-10-30
1586
1587- **`bot.device-message@1`'s heartbeat gains an optional `fleet`** (Codes C9c): what the machine's coding agents have
1588 left — each agent's id, whether it is installed and signed in, and each limit window's label, used and limit and
1589 when it frees. OpenVibe Link reads it with OpenVibe.Codes' own logins probe as the machine's user and reports labels,
1590 numbers and times only (no key, token or account name); absent means no reading yet, never "nothing installed".
1591 Additive: no field changed or removed, and a heartbeat without `fleet` validates unchanged.
1592- **`run.job-create-request@1` gains an optional `node`** (Codes C9c): the device id (`dev_…`) of the job's own
1593 machine in Run's placement (`platform.resource-offer@1` node_id, as OpenVibe.Bot's `GET /api/v1/machines` names it),
1594 which pins the job to one machine — a conductor must run where its folder and its memory are. Run places a pinned
1595 job only on that machine and refuses it `409 run.job.node_offline` when it is not connected, never moving it to
1596 another one. Omitted (every existing caller): Run places the job wherever it fits, exactly as before. Additive: no
1597 field changed or removed, and a caller that never sends `node` validates unchanged.
1598
1599## 0.249.0 — 2026-10-30
1600
1601- **`actor.task-event@2`** (OpenVibe.Actor v2, stage V2-4): a `tool_result` event on a task's live stream now carries
1602 `artifacts`: the files and charts that tool made, each `{ kind, name, mime, url, size }`, stored on OpenVibe.Media
1603 private to the task's requester. `url` is Actor's stable link, which signs a fresh Media URL for the requester when
1604 opened, never an expiring one. Every field of `@1` keeps its name, type and meaning; `@1` is deprecated with `@2` as
1605 its replacement.
1606- **`actor.task.read`** now implements `GET /api/v1/tasks/:id/artifacts/:mediaId`, a redirect to that fresh signed
1607 Media URL (the same 404 for another person, an unknown id, or a file the task never made).
1608
1609## 0.248.0 — 2026-10-30
1610
1611- **`actor.agent-list-result@2`** (OpenVibe.Actor v2): `GET /api/v1/agents` now lists the model each tier resolves
1612 to (`tiers`: fast, smart, best, check, vision, with its provider, model, family and availability) and the models the
1613 server's keys reach (`models`). Every field of `@1` keeps its name, type and meaning; `@1` is deprecated with `@2`
1614 as its replacement. The `actor.agent.read` capability's output schema is `@2`.
1615
1616## 0.247.0 — 2026-10-30
1617
1618- Add `bench.run@2`, allowing a null run or task score while human judges have not scored verified outputs. `bench.run@1` stays unchanged.
1619- `bench.run@1` allows a null run or task score while human judges have not scored the published output yet.
1620
1621## 0.246.1 — 2026-10-30
1622
1623- The `claude-other` harness offer names its provider `custom`: Claude Code on another provider is the person's own
1624 endpoint (`base_url`, a URL that speaks the Anthropic format), and `custom` is the provider id a person's key is
1625 kept under. The example and its fixture say so now; nothing else changed.
1626
1627## 0.246.0 — 2026-10-30
1628
1629- **Two more harnesses in the catalogue** (OpenVibe.Codes): `platform.harness-offer@1` publishes MiniMax Code
1630 (`minimax-code`, the `mcode` CLI on the person's own MiniMax plan) and Claude Code on another provider
1631 (`claude-other`, the same `claude` CLI in the cm-style environment: the person's own key, another provider's
1632 model) as two of its examples, with the fields their siblings have.
1633- **`platform.harness-offer@1` gains the optional `agents`** — the agents (models) a harness offers, each one a
1634 `platform.agent-offer@1` whose `harness` names the offer. A catalogue row is one contract instance now: the
1635 offer and the models it runs. Additive: every harness offer that leaves it out still validates.
1636
1637## 0.245.0 — 2026-10-30
1638
1639- **`codes.task-start-request@1` accepts `permission: "review"`** — a read-only coding task (research, an audit, a
1640 review), which Codes runs at its `read` permission level: the agent looks and answers and changes nothing. Additive
1641 to the enum (`review` beside `edit` and `full`); every existing request still validates.
1642
1643## 0.244.0 — 2026-10-30
1644
1645- **Bench as an open benchmark platform, stage B1** (spec 2026-10-30): `bench.benchmark@1` and `bench.run@1`.
1646 A benchmark is an owned, versioned and forkable set: its tasks, its judges (pinned by version), how they combine
1647 into one score, the limits a run may not pass, the default model and harness matrix, and whether it is public or
1648 unlisted. A run is one result: a benchmark version × a model × a harness × settings × who ran it, with the
1649 per-task scores, cost, time, tokens, the artifacts, and its provenance — `verified` (an executor ran it) or
1650 `submitted` (posted with no executor, badged and out of the default rankings).
1651- **Three new capabilities** for Bench: `bench.benchmark.write` (create, edit, freeze and fork a benchmark),
1652 `bench.run.publish` (publish a run) and `bench.run.read` (the run, the comparison, the rankings and the percentile).
1653 OpenVibe.Bench's service manifest lists them.
1654
1655## 0.243.0 — 2026-10-30
1656
1657- The release cut from `main` for codes.task@2 (#250): a coding task's attempts and outcome, one id with two majors.
1658 It carries 0.241.0 (the AI credential v2 release) as well. `v0.242.0` and `v0.242.1` were tagged from the PR
1659 branch before it merged; pin `v0.243.0` instead (OpenVibe.Codes moves to it).
1660
1661## 0.242.1 — 2026-10-30
1662
1663- The generated OpenAPI files carry the release's own version again: `v0.242.0` shipped them with 0.240.0's,
1664 because the version was raised after they were written. Nothing else changed; `v0.242.1` is the release to pin.
1665- This release is rebased on `0.241.0` (the AI credential v2 release, merged while it was being written), so the
1666 branch carries that work too; the published `v0.242.1` tarball, which OpenVibe.Codes pins, is the cut from
1667 before the rebase and holds the codes.task@2 work alone. The next tag cut from `main` carries both.
1668
1669## 0.242.0 — 2026-10-30
1670
1671- **`codes.task@2`** (OpenVibe.Codes): a coding task's timeline. It is `codes.task@1` with the same fields, plus two
1672 added ones: `attempts` (every try of the task, in order: the agent, the machine, the session, the state it ended
1673 in, why, what it cost) and `outcome` (what the attempts added up to: done, unfinished with what is left, or
1674 stopped). `GET /api/v1/tasks/:id` answers it — the task's own fields stay at the top level, exactly as
1675 `codes.task@1` had them, and the two new fields are added to them. `codes.task@1` stays as it is.
1676- **One contract id may hold more than one major** now: the catalog lists a v1 and a v2 file for the same id, the
1677 bare id resolves to the newest major, and `id@N` names that major, so a v1 caller keeps resolving while a v2
1678 caller names it exactly. (`ai.credential@2` is the first to use it.)
1679
1680## 0.241.0 — 2026-10-30
1681
1682- **AI: one credential per provider** (Codes C3; research `research-2026-10-30/codes-c3-connections.md` items 1 and 2).
1683 `ai.credential-put@2` and `ai.credential@2` are additive on `@1`: the provider enum gains `deepseek`, `minimax`,
1684 `openrouter` and `custom` beside `anthropic`, `openai` and `node`, and a PUT may carry `key` (v1's `api_key` stays
1685 accepted) and its own `budget_usd_per_day`. `custom` requires an https `base_url`; `node` still takes a machine and no
1686 key. A person may now keep one key per provider, and the route without a provider still stores the default one.
1687 `ai.credential@2` returns the same body as `@1` with the widened provider, and `key_hint` for every provider except
1688 `node`.
1689- **Tooling:** the registry can hold more than one major of one contract id — the bare id resolves to the newest listed
1690 and `id@N` to that major — so `ai.credential-put@1` keeps resolving while `@2` is the one callers name. The bundle
1691 keys a multi-major id as `id@N`, the catalog check looks each entry up by its own major, and a fixture set is checked
1692 against the newest major of its id. `ai.credential-put@2` is the first contract to use this.
1693
1694## 0.240.0 — 2026-10-29
1695
1696- **OpenVibe.Vision's API** (plan §5.8b): the service manifest now lists the 20 capabilities its routes serve today —
1697 `vision.image.ask`, `vision.text.read`, `vision.model.compare`, `vision.ui.check`, `vision.alt.write`,
1698 `vision.media.find`, `vision.receipt.read`, `vision.product.match`, `vision.camera.watch`, `vision.video.moments`,
1699 `vision.face.detect`, `vision.face.blur`, `vision.face.consent.manage`, `vision.face.verify.self`,
1700 `vision.face.find.self`, `vision.face.library`, `vision.face.cast.match`, `vision.face.cast.read`,
1701 `vision.models.read` and `vision.benchmarks.read` — with their input and output schemas: `vision.image-request@1`,
1702 `vision.ask-request@1`, `vision.ocr-request@1`, `vision.compare-request@1`, `vision.find-request@1`,
1703 `vision.receipt-request@1`, `vision.product-request@1`, `vision.watch-request@1`, `vision.moments-request@1`,
1704 `vision.answer@1`, `vision.answer-result@1`, `vision.alt-result@1`, `vision.find-result@1`,
1705 `vision.receipt-result@1`, `vision.product-result@1`, `vision.watch-result@1`, `vision.moments-result@1`,
1706 `vision.face-detection@1`, `vision.face-blur@1`, `vision.face-enrol-request@1`, `vision.face-verify@1`,
1707 `vision.face-find-result@1`, `vision.face-cast-match-request@1`, `vision.face-cast-match@1`, `vision.face-tag@1`,
1708 `vision.face-tag-list@1`, `vision.face-library-request@1`, `vision.face-library-result@1`,
1709 `vision.face-library-group@1`, `vision.models@1` and `vision.benchmarks@1`.
1710- **Consent** `vision.consent@1`: whose face or voice (subject and modality), the purpose-scoped feature and scope,
1711 who signed which text version, when it expires, when and how it was revoked (subject, retention, account deletion),
1712 the retention limit and whether the template and derived data were erased. `vision.consent-request@1` and
1713 `vision.consent-revocation@1` are the grant and revoke bodies.
1714- **Events** `vision.result.ready@1` (a result's identifiers, engine, provenance, cost, latency, retention and
1715 consent id; never an image or answer text) and `vision.alert@1` (an owner-granted camera alert: source reference,
1716 classes and confidence). `events.event-envelope@1` now accepts a two-segment event type (`vision.alert` is the
1717 first), a backward-compatible widening; every capability id still needs three segments.
1718
1719## 0.239.0 — 2026-10-28
1720
1721- Added `graph.link@1` (`from`, `rel`, `to` OVRN relation) for the planned object graph. The `graph.link.created` event waits for a producing service.
1722- Added `report.metric@1` from OpenVibe.Report's `docs/report.metric.v1.json` proposal, including exclusive UTC day and 7/30/90-day window forms. Report v1 currently reads upstream numbers and does not publish metric rows.
1723- Added the optional `site.neighbourhood` field to `registry.service-manifest@1` (1.2.0), last in each of the 48 service site blocks. The seven ids match OpenVibe.Shared `rooms.js` and Network's neighbourhood menu.
1724- Today already had all three live `today.event.*` outbox payloads and fixtures. Today, Report, Design, Domains and Vision already have manifests; Website is served by Space, so no duplicate service manifest was added.
1725
1726## 0.238.0 — 2026-10-28
1727
1728- **OpenVibe.Bench** (`bench`, live at bench.openvibe.services, port 5230, database `ov_bench`): the shared AI
1729 benchmark and comparison engine for every room (plan §4.12). It owns kinds, pinned rounds, entries, blind
1730 judgements, ratings, boards, the open dataset per kind and private evals; AI stays the run authority and Report
1731 the analytics authority. New `bench.kind@1`, `bench.task@1`, `bench.round@1`, `bench.entry@1`,
1732 `bench.judgement@1` and `bench.rating@1` schemas, the `bench.round.finished`, `bench.judgement.recorded` and
1733 `bench.rating.changed` event payloads, and nine first-party `bench.*` capabilities. The manifest is modeled on
1734 OpenVibe.AI (`bench.openvibe.services`, not `openvibe.bench`) and its site block (Bench, icon `bench`, position 47,
1735 legal profile `tools`) sits in For developers. Bench calls `ai.run.create` (namespace `ai.generate`) and subscribes
1736 to the account events; Design moves its Arena onto Bench with `bench.task.create`, `bench.round.create`,
1737 `bench.round.read`, `bench.judgement.cast` and `bench.board.read`.
1738- **Codes** (`codes.task-start-request@1` 1.1.0, `codes.task@1` 1.1.0): optional `actor_task_id`/`actor_step_id`
1739 request fields and the `actor_ref` back-reference, so a task started from OpenVibe.Actor can carry its Actor task
1740 and step. Both are optional, so existing producers and consumers are unaffected.
1741
1742## 0.237.0 — 2026-10-28
1743
1744- **OpenVibe.Cam** (`cam`, live at openvibe.cam, port 5160, database `ov_cam`): the camera app (preview, timer,
1745 3-shot burst, grid and an on-device colour/light/softness filter), a private wall for the cameras a person owns,
1746 and the still Live's cam button takes. A camera is private to its owner and visible to a viewer only while the
1747 grant naming them is unrevoked and unexpired, checked on every read, with no staff bypass. Photos and stills are
1748 uploaded to OpenVibe.Pics with the person's own Network token and stored by reference (Pics slug, page and direct
1749 links, filter, caption) — Cam keeps no picture bytes and runs no face recognition. The manifest names `cam.*` and
1750 the two account events it consumes, and the site block (Cam, icon `cam`, position 46, legal profile `ugc`) in
1751 Streams & places. Live calls `POST /api/v1/stills` with the viewer's own Network token, which Cam verifies against
1752 Network's JWKS; no service token is involved, so it registers no capability of its own. The account export/deletion
1753 pair, `identity.subject.resolve`, Events subscriptions and the (absent) Search relay are Network grants.
1754
1755## 0.236.0 — 2026-10-28
1756
1757- **OpenVibe.Design** gets the Design Arena and its database `ov_design`: rounds, outputs, votes and Elo ratings.
1758 Migration 0001 only creates the Arena's own tables, so a rollback has no blocker. Design calls `ai.run.create`
1759 (namespace `ai.generate`) to pin three of AI's generate offers. The contracts range is now `>=0.236.0`.
1760- **OpenVibe.Fun** (`fun`, live at openvibe.fun, port 5140, database `ov_fun`): IRL quest boards on a streamer's
1761 public Live channel, a deterministic local guide from OpenStreetMap (Ticketmaster only when a key is configured)
1762 and group plans the group votes on, with the winner added to the viewer's own Today using the viewer's token.
1763 Public quests and plans are `search.index-document@1` rows queued in `fun_outbox` with tombstones; Live and Chat
1764 are public reads, never writes. The manifest names `fun.*`, the two account events it consumes, and the site
1765 block (Fun, icon `fun`, position 45, legal profile `ugc`) in Games & laughs. No route needs a service token, so it
1766 registers no capability of its own; the account export/deletion pair, Events subscriptions and Search relay are
1767 Network grants, and the Search relay waits for its writer.
1768
1769## 0.235.0 — 2026-10-28
1770
1771- **OpenVibe.Vision** (`vision`, live at openvibe.vision, port 5130, database `ov_vision`; plan 2026-10-28 §5.8): ask
1772 a picture, read its text with the local Tesseract engine first, compare the local reader with up to three AI hints,
1773 and check HTML, a public URL or a screenshot for overflow, cut-off text, low contrast, overlap and layering faults.
1774 OpenVibe.AI is the only model gateway (`ai.run.create`, workflow `ai.complete`); Vision holds no provider key, uses
1775 no face recognition and stores no image bytes. The manifest names `vision.*`, the two account events it consumes, and
1776 the site block (Vision, icon `vision`, position 43, legal profile `ugc`) in News & answers. It registers one
1777 capability, `vision.ui.check` (first-party, the route Design's Arena calls), with `vision.ui-check-request@1` and
1778 `vision.ui-check-result@1` (new); `vision.ask`, `vision.ocr` and `vision.compare` are served but wait for a caller.
1779- **OpenVibe.Exchange** (`exchange`, live at openvibe.exchange, port 5150, database `ov_exchange`): free and swap
1780 listings with a permission passport, conformance tests for each version, a manifest/passport sandbox dry run,
1781 install with the exact passport snapshot, one-tap revoke, claims and swap offers, a prohibited-items/no-money filter
1782 and staff hide. Every public listing is one `search.index-document@1` queued in `exchange_outbox`; v1 writes no
1783 Network grant and executes no listing code, so it registers no capability of its own. The manifest names
1784 `exchange.*`, the two account events it consumes, and the site block (Exchange, icon `exchange`, position 44, legal
1785 profile `ugc`) in Shop & swap.
1786
1787## 0.234.0 — 2026-10-28
1788
1789- **OpenVibe.Meme** (`meme`, live at openvibe.meme, port 5120, database `ov_meme`): the open meme database, rebuilt
1790 with AI. Entries cite the chat line or VOD second they came from, follow later uses on a timeline and keep a
1791 status; candidates stay hidden until a staff person publishes them; a daily job re-verifies every citation; people
1792 vote once an ISO week for meme of the week and captions are plain text over a template. Every public entry is one
1793 `search.index-document@1` queued in `meme_outbox`. The manifest names `meme.*`, no capabilities or events of its
1794 own, and the site block (Meme, icon `meme`, position 42, legal profile `ugc`) puts it in Games & laughs.
1795- **Search's hybrid ranking** (additive): `search.fabric-result@1`'s `route.explain` entries gain optional `ranking`
1796 (`hybrid` or `keyword`) and `reason` (`no_vectors`, `ai_unavailable`, `short_query`), and its results gain optional
1797 `ranks` (the 1-based keyword and vector positions, null when absent from that list). `search.query-result@1` gains
1798 the same per-hit `ranks` and an optional `explain` object. Keyword-only answers stay valid.
1799
1800- `domains.proposal@1`: a change may be `type: "NS"` (a domain's nameservers at the registrar, update only), with
1801 `before`/`after` as the list of nameservers (additive; OpenVibe.Domains' Porkbun connection).
1802
1803## 0.233.0 — 2026-10-28
1804
1805- **OpenVibe.Domains' control panel** (plan 2026-10-28 §5.1, DOM-2):
1806 - **`domains.proposal@1`** (new, public): a DNS change waiting for its person. It holds the record diff (create,
1807 update, delete), why, the risk, its status (pending, applying, applied, declined, failed, rolled_back, expired) and
1808 who asked. The credential is never part of it.
1809 - **`domains.actions.read`** and **`domains.proposal.decide`** (new, first-party, for OpenVibe.Network): Domains'
1810 proposals in the Action Center, approved or declined there.
1811 - `common.action-item@1`'s `service` and `network.me-actions-result@1`'s `sources` gain `domains` (additive).
1812 - The Domains manifest names both capabilities and its database (`ov_domains`). The provider credential is a Network
1813 project secret (ADR-056), granted to `domains` for reveal to the provider's origin only.
1814
1815## 0.232.0 — 2026-10-28
1816
1817- **codes.task.queued|running|succeeded|failed|cancelled** (new payload contracts, first-party, owner `codes`; plan
1818 2026-10-28 §6, decisions 2 and 3). OpenVibe.Codes announces each state change of a coding task:
1819 `{ task_id, state, agent, repo, cost_usd, files_changed, started_at, finished_at, error }`. The envelope's subject
1820 is the owner; the prompt is never in a payload.
1821- The Codes manifest now names what it produces (the five topics) and consumes: `run.job.*`, which finalize a task
1822 without polling, and the two account events. Its notes and startup recovery cover the session lines and the
1823 outbox.
1824
1825## 0.231.0 — 2026-10-28
1826
1827- **OpenVibe.Surf** (`surf`, live at openvibe.surf, port 5110; plan 2026-10-28 §5.6, the Surf room). One room, three
1828 surfs:
1829 - Ride: OpenVibe.Games' CS-style surf maps in the browser, with a millisecond timer and Play time boards;
1830 - Web (Surf with Vibe): one OpenVibe.Actor task, made with the person's own Network token, browses on a private desk
1831 and reports with its sources;
1832 - Watch: a lean-back TV over OpenVibe.Live's live streams, clips and AI moments.
1833
1834 v1 is a stateless front and an OAuth client of OpenVibe.Network (`surf`); it stores nothing. The site block (Surf,
1835 icon `surf`, position 41, legal profile `account`) puts it in Games. `surf.*` is its namespace.
1836
1837## 0.230.0 — 2026-10-28
1838
1839- **OpenVibe.Today** (`today`, live at openvibe.today, port 5100, database `ov_today`; plan 2026-10-28 §5.3, the Today
1840 room). v1 is the network's calendar authority:
1841 - stream and event schedules;
1842 - reminders sent as Network notifications;
1843 - calendar feeds: a channel's public one and a person's private one (RFC 5545);
1844 - the daily brief.
1845
1846 It publishes `today.event.scheduled`, `today.event.updated` and `today.event.cancelled` (new payload contracts,
1847 first-party) from an outbox. It consumes `live.stream.started` and `live.stream.ended` to move a stream live and
1848 then ended. The site block (Today, icon `today`, position 40, legal profile `account`) puts it in News & answers.
1849 `today.*` is its namespace.
1850
1851## 0.229.0 — 2026-10-28
1852
1853- **The Action Center** (plan 2026-10-28 §3.10, NOTIF-5): one list of a person's agent work on every site.
1854 - `common.action-item@1`: one item (an agent task, a coding task, an AI run, an approval), with its bucket
1855 (running, waiting, scheduled, done, failed), state, cost in USD, steps, error, page and the actions it allows.
1856 - `common.action-list-result@1`: one authority's items for a person. Served by Actor, Codes and AI at
1857 `GET /api/v1/actions?subject=usr_…` under the new first-party capabilities `actor.actions.read`,
1858 `codes.actions.read` and `ai.actions.read`, which are granted to Network only.
1859 - `actor.approval.decide`: Network approves or declines an Actor approval for its person.
1860 - `network.actions.read` and `network.me-actions-result@1`: `GET /api/v1/me/actions` merges them with Network's
1861 own confirmations into the five buckets, and `POST /api/v1/me/actions/:service/:id/:action` acts on one.
1862
1863## 0.228.0 — 2026-10-28
1864
1865- **OpenVibe.Design** (`design`, live at openvibe.design, port 5090; plan 2026-10-28 §5.2, the Design room). v1 is the
1866 theme studio, a stateless front and an OAuth client of OpenVibe.Network (`design`). It has:
1867 - every theme in the catalogue, tried on a Live channel, a Chat room and a shop at once, with colour-vision views;
1868 - a six-colour editor that derives the full token set, with WCAG checks that must pass before the theme is used;
1869 - Use (Network's `PUT /api/themes/me`, source `studio`), sharing to the gallery, and History with Restore.
1870
1871 The site block (Design, icon `design`, position 39, legal profile `account`) puts it in the menu's Make
1872 neighbourhood. `design.*` is its namespace: the Arena (AI designers judged by people) comes next.
1873
1874## 0.227.0 — 2026-10-28
1875
1876- **OpenVibe.Report** (`report`, live at openvibe.report, port 5080; plan 2026-10-28 §5.4, the Report room). v1 is a
1877 stateless front over OpenVibe.Network's open stats and OpenVibe.Live's Rundown and after-show reports. It has:
1878 - the network's numbers, open to everyone, each with its window and definition;
1879 - The Rundown: topics, takes, episodes and voices;
1880 - each stream's after-show report: viewers minute by minute, chat, the moments with links into the recording, and
1881 the AI write-up, labelled;
1882 - an open JSON API.
1883
1884 The site block (Report, icon `report`, position 38, legal profile `info`) puts it in the menu's News & answers
1885 neighbourhood. `report.*` is its namespace: v2 makes it the analytics authority.
1886
1887## 0.226.0 — 2026-10-28
1888
1889- **OpenVibe.Domains** (`domains`, live at openvibe.domains, port 5070; plan 2026-10-28 §5.1, the Domains room). v1 is
1890 a stateless front over OpenVibe.Host's price catalog and OpenVibe.Tools' domain history:
1891 - one box prices a name across every ending, with 1-, 3- and 5-year totals and renewal traps flagged;
1892 - a page per ending lists every registrar;
1893 - a page per domain gives its public record;
1894 - an open JSON API.
1895
1896 The site block (Domains, icon `domains`, position 37, legal profile `info`) puts it in the menu's Make & build
1897 neighbourhood. `domains.*` is its namespace: the v2 control panel (registrar connections, portfolio, proposals) is
1898 that authority.
1899
1900## 0.225.0 — 2026-10-28
1901
1902- **The Search Fabric** (plan 2026-10-28 §4.5; the owner, 10-28: "a shared sdk/api enabled multi purpose search system
1903 for OpenVibe to reuse across sites and more"): one search over several scopes, routed the cheapest way that answers.
1904 - **`search.fabric.query`** (public, owned by `search`): `POST /api/v1/query` (or `GET /api/v1/query?q=&scopes=`), and
1905 `GET /api/v1/query/providers`. It is the SDK's `createSearchClient().query()` and the MCP tool `openvibe.search`.
1906 - **`search.fabric-request@1`:**
1907 - `q` and `scopes`: `network`, `mine`, `web`, and `news`, `images`, `video`, `products`, `people`, `places`,
1908 `code` (accepted now; v1 answers them as network results by kind);
1909 - `filters` (owner, type, lang, site);
1910 - `freshness`;
1911 - `depth`: `quick` reads only the indexes and caches, `standard` climbs the provider ladder until a step
1912 answers, `deep` asks every step;
1913 - `answer`, `limit` and `cursor`.
1914 - **`search.fabric-result@1`:**
1915 - `results`, each with its scope and kind (a document in Search's index, or a web page with its provider,
1916 URL, date and when it was read);
1917 - `groups` (counts per scope) and `citations`;
1918 - an optional `answer`. It is labelled "Written by AI from these sources" and is never without citations.
1919 - `route.explain`: step by step, what was asked, what answered, from the cache or not, why a step was
1920 skipped, and what it cost.
1921
1922 The query is never echoed (the `?q=` rule).
1923 - **`search.provider-offer@1`:** a web provider as the ladder and Route see it. It gives the scopes, the price
1924 per call, whether the provider has its own index, availability (balance, key, rate limit, daily cap),
1925 latency, answered rate and terms.
1926 - **Who may use what:**
1927 - anonymous callers get network results, plus web results from the open index and the cache;
1928 - a signed-in person, or a first-party service, also reaches the paid providers within OpenVibe's daily caps;
1929 - `mine` needs a person;
1930 - providers never receive an account identifier.
1931
1932 Fixtures, valid and invalid, for all three schemas.
1933
1934## 0.224.0 — 2026-10-28
1935
1936- **A `crawl` source type for OpenVibe.Sources** (the owner, 2026-10-28: "aggregate all websites and select deals on all
1937 sites… a full comprehensive crawler system… the open source Google"). A crawl source walks one site from its endpoints
1938 (the seeds):
1939 - **How pages are found:** the site's own sitemaps (robots.txt `Sitemap` lines, else `/sitemap.xml`, indexes
1940 followed), and, if asked, its same-host links.
1941 - **Which pages:** `include` and `exclude` patterns.
1942 - **Limits:** `max_pages`, `pages_per_run`, `recrawl_sec` and `max_depth`.
1943 - **What is kept:** `require_structured`, only pages that publish schema.org JSON-LD.
1944 - **The rules every source already follows still apply:** robots.txt on every request and redirect hop, per-host
1945 spacing and Crawl-delay, a terms note before it can be enabled, and noindex pages never kept.
1946 - **What is read:** only what a page publishes for machines (products and offers, articles, reviews).
1947 - **Price history:** a page fetched again on schedule turns a price seen twice into a history (Deals' observations).
1948 - **Fields:** `type` gains `crawl` and sources gain `crawl` on `sources.source@1` and its write request. There is a
1949 valid fixture.
1950
1951## 0.223.0 — 2026-10-28
1952
1953- **Run sessions** (the Desks plan's D6; `OpenVibe_Agent_Desks_Plan_2026-10-27.md`). A session is a browser desk that
1954 OpenVibe.Run places for one person and OpenVibe.Bot leases to it:
1955 - `run.session@1` (states placing, starting, running, ended; where it runs and with what trust; desk-seconds),
1956 `run.session-create-request@1` (`POST /api/v1/sessions`: the person's own named machine, or placement over desk
1957 hosts, `ttl_s`, `idle_s`, requirements, an idempotency key), `run.session-control-request@1` and
1958 `run.session-control-result@1` (`POST /api/v1/sessions/:id/commands`: screen, input and browser on the session's
1959 desk only), `run.session-list-result@1`, and the events `run.session.started` and `run.session.ended`.
1960 - Capabilities `run.session.create`, `run.session.read` and `run.session.control` (public, the caller's own sessions).
1961 - Desk time is metered as one `platform.usage-sample@1` a minute (service `run`, operation `browser.desk`, unit `s`,
1962 idempotency key `run:<session>:<minute>`).
1963- **Desk leases on Bot**: `bot.desk-lease@1` and `bot.desk-lease-create-request@1`, with the capability
1964 **`bot.desk.session`** (first-party, sensitive): Run leases one named desk for one session on the person's own machine
1965 (where they let agents use it) or on a desk host whose owner offers it to other people and whose OpenVibe Link runs
1966 every desk in its own sandbox (Link v0.32.0, `desk_isolation: sandbox`); only that session's commands reach the desk,
1967 never the machine itself.
1968- Fixtures for each, and `test/platform-run.test.js` holds the two sides together (ids, desk names, sizes, kinds).
1969
1970## 0.222.0 — 2026-10-27
1971
1972- **Site names say their domain** (owner, 2026-10-27: "it says memberships … couldn't it say VIP memberships since the
1973 domain is VIP? … consider these kind of small things, especially when it comes to domain names across all the tools
1974 and websites"). The `site.name` the launcher, menus and pages show is now the domain's own word:
1975 - VIP (was Memberships), Trade (Markets), Host (Hosting), Space (Spaces), Bot (Robots), Actor (Agents), Work (Jobs)
1976 - Quest (Quests), Rent (Rentals), Watch (Alerts), Inventory (Items), AI (AI API), Run (Compute), Play (Game services)
1977 - Zone (Storage), Codes (Code)
1978- Each tagline still says what the site is for: "Memberships for creators and their software", "Watchlists and alerts".
1979- Live, Video, OpenRestream and the rest already matched.
1980
1981## 0.221.0 — 2026-10-27
1982
1983- **Any of your own machines** (AI on your own machines). A node credential's `machine`, in `ai.credential-put@1` and
1984 `ai.credential@1`, may be **`any`**: whichever of the person's machines is on, lets their AI use its models and offers
1985 the model.
1986 - The fastest goes first, by the speed OpenVibe.Bot reports (`computer.ai_speed`, OpenVibe Link v0.29.0).
1987 - The next one is tried when one is busy or away.
1988 - It is never anyone else's machine, and never another provider.
1989- Fixtures: a valid `any`, and an invalid machine that is neither a `dev_` id nor `any`.
1990
1991## 0.220.0 — 2026-10-27
1992
1993- **A person's own provider may be their own machine** (AI on your own machines, step 4). `ai.credential-put@1` and
1994 `ai.credential@1` take provider **`node`** with **`machine`**, a `dev_` id.
1995 - There is no key or base_url, and no cost.
1996 - OpenVibe.AI reaches the model only through OpenVibe.Bot (capability `bot.machine.ai`), only for that person, and
1997 only where they turned on "Let my AI use this computer's models".
1998 - A node credential has no `key_hint`; the others still require one.
1999- Fixtures: a valid node credential (put and read), a node credential with a key, and one without its machine.
2000
2001## 0.219.0 — 2026-10-27
2002
2003- **AI on your own machines** (the roadmap's user-owned GPU route; `OpenVibe_AI_On_Your_Machines_Plan_2026-10-27.md`).
2004 `bot.command@1` gains kind `ai`: one chat completion (`model`, `messages`, `max_tokens`, `temperature`) on the
2005 person's own machine. OpenVibe Link v0.27.0's `ai` plugin relays it to a local model server (Ollama, llama.cpp,
2006 LM Studio) and answers `{ model, message, usage? }`.
2007- New capability **`bot.machine.ai`** (first-party, sensitive, owned by `bot`). A service, OpenVibe.AI, runs a model on a
2008 person's own machine for that person, where they turned on "Let my AI use this computer's models". It never places
2009 one person's request on another's machine, and the audit keeps the model and token counts, never the text.
2010- Fixtures: a valid chat, and an invalid one with no messages.
2011
2012## 0.218.0 — 2026-10-27
2013
2014- **Programs on a desk** (the Desks plan's desk templates; OpenVibe Link v0.26.0). `bot.command@1`'s `exec` takes:
2015 - `desk`: the program runs in that desk's session (its display, session bus and temp folder), so a program with
2016 windows opens on the desk.
2017 - `detach`: on a whole desk only. It starts a program that keeps running, such as an office suite, a terminal or an
2018 editor, and answers at once with its pid. The program runs until the desk stops.
2019 - An agent can now work in real applications on a desk of its own: open them with `exec`, look with `screen`, use
2020 them with `input`.
2021- Fixtures: a valid detached program on a named desk, and an invalid one with a bad desk name.
2022
2023## 0.217.0 — 2026-10-27
2024
2025- **Kept desk profiles** (the Desks plan's step D7, on one machine; OpenVibe Link v0.24.0). On `start`, kind `desk`
2026 takes `profile`: a browser profile kept on the machine by that name.
2027 - The desk's browser starts from that profile, with its cookies and site storage, so a person signs in once, on any
2028 desk (an agent's "Needs you" sign-in carries over to the next task).
2029 - The desk saves the profile back when it stops; when several desks stop, the last one wins. Caches are never kept.
2030 - The private desk keeps its own profile. A machine that keeps profiles says so in its computer capabilities
2031 (`desk.profiles`).
2032- Fixtures: a valid start from a kept profile, and an invalid start with a bad profile name.
2033
2034## 0.216.0 — 2026-10-27
2035
2036- **Browser desks** (the Desks plan's step D2; OpenVibe Link v0.23.0). Kind `desk` takes `kind` on start:
2037 - `desktop` (the default) is a whole screen: a display, a window manager and a browser shown on it. It needs Linux
2038 with Xvfb.
2039 - `browser` is a browser alone, with no display, at about half the cost. Its screen, mouse and keyboard, and its live
2040 view, are the page's own. It runs on Linux or macOS with Chromium, so a Mac can host desks too.
2041 - A machine says which kinds it runs in its computer capabilities (`desk.kinds`).
2042- Fixtures: a valid browser desk start, and an invalid start with an unknown kind.
2043
2044## 0.215.0 — 2026-10-27
2045
2046- **Several desks per machine** (the Desks plan's step D1, `OpenVibe_Agent_Desks_Plan_2026-10-27.md`; OpenVibe Link
2047 v0.19.0). `bot.command@1`'s `desk` on `screen`, `input` and `browser` takes a named desk, `desk-<name>` (lower-case
2048 letters, digits and dashes, up to 24 after `desk-`), besides `main` and `private`. Kind `desk` takes `desk` (which
2049 desk; `private` by default) and the action `list` (the desks that run). Each desk is a separate computer for its
2050 agent: its own display, browser profile, downloads and temp folder. A machine runs at most its `max_desks` at once.
2051 Fixtures for a named start, list, a browser on a named desk, a bad name and `main` as a desk to start.
2052
2053## 0.214.1 — 2026-10-27
2054
2055- Site text only (`manifests/services/*.json`), so the Network's home and menus say what each product does today:
2056 - **Games:** the tagline is "Browser games, and games you make". The description and the build-your-own FAQ name
2057 the creator platform shipped on 10-27: starter ground, a team of up to eight, remix with credit, the asset store,
2058 and first-person or top-down. World scripts are left out while they are switched off in production.
2059 - **Tools:** more than 180 tools (184 on the home today), with barcodes and QR codes.
2060 - **Robots:** drive by keyboard, gamepad or on-screen joystick, from the robot's page or under a live stream.
2061- `docs/ESTATE.md` and `manifests/repositories/` regenerated from every repository's main (Contracts#219).
2062
2063## 0.214.0 — 2026-10-26
2064
2065- **`chat.vibe.deliver`** (first-party, sensitive, owned by `chat`; consumer plan §4: "each run is a chat you can
2066 open"): a first-party service puts a result of the person's own work into their Vibe chats (`POST
2067 /internal/chat/vibe/deliver`). OpenVibe.Actor posts each finished run of one of their OpenVibe Agents into one chat per
2068 agent, named after it, as Vibe's message. No AI answer is made and nothing counts against the allowance. Schemas
2069 `chat.vibe-deliver-request@1` (subject, source { kind agent, id, name }, text in Markdown, url, idempotency_key) and
2070 `chat.vibe-deliver-result@1` (chat, url, repeated), with fixtures. `actor.agent-manage-request@1` and `-result@1`
2071 gain `send_to_vibe` (boolean, default true), the agent's switch for it.
2072- **`actor.agent.manage`** lists the suggestions routes (`GET /api/v1/me/agents/:id/suggestions`, `POST
2073 …/suggestions/:pid/:action` with apply | dismiss | undo): a personal agent may suggest a line for its instructions after a
2074 run that passed its check, which waits for the person (OpenVibe.Actor#115).
2075- **Run's manifest names its loopback origin** (`internalOrigin` http://127.0.0.1:4920, `health` /api/health, `ready`
2076 /api/ready): Network's status page showed Run as unknown ("no internal address known to Network") although it runs.
2077 Its `lifecycle` said "not built yet" throughout; it now says what Run does (shutdown drains, what it resumes at boot,
2078 rollback, no leases).
2079- **Vibe by voice on a person's own machine** (the owner, 2026-10-24: "a call word on Live and on Node"; consumer plan
2080 §8). `bot.device-message@1` gains two frames and two config fields, all additive:
2081 - `voice_ask` (device to server): `id` and `text`, what the person asked after the machine's call word, transcribed
2082 on the machine (nothing leaves it before the call word); optional `lang` (BCP 47) and `robot_id`.
2083 - `voice_answer` (server to device): the same `id`, `state` working | answered | refused, the `text` to speak and the
2084 `url` of the Vibe chat that keeps it.
2085 - `config` carries `voice` (the owner turned it on for this machine) and `call_word`.
2086 Fixtures for each, and two invalid ones.
2087- **`chat.vibe.ask`** (first-party, sensitive, owned by `chat`): a first-party service asks Vibe on a person's behalf
2088 (`POST /internal/chat/vibe/ask`): Bot's Vibe by voice, with the machine's owner as `subject`. Chat keeps the question
2089 and the answer in that person's own Vibe chats (one chat per source, "Voice on <machine>") and counts the answer
2090 against their daily allowance. Schemas `chat.vibe-ask-request@1` (subject, text, source { kind voice, id, name },
2091 lang, idempotency_key) and `chat.vibe-ask-result@1` (state answered | refused, text, url, chat, code), with fixtures.
2092- **Quiet hours for personal agents** (consumer plan step 4: "recurring work … with quiet hours and a budget").
2093 `actor.agent-manage-request@1` and `-result@1` carry `quiet_from` / `quiet_to` (HH:MM UTC, both or neither; the window
2094 may cross midnight): no scheduled run starts inside it, an hourly run waits until it ends, and a run the owner starts
2095 still runs. Fixtures for both.
2096- **A private desk for agents on a person's own machine** (plan track K, consumer plan step 2: Vibe's desk on Node).
2097 `bot.command@1` takes kind `desk` (`action`: start | stop | status; `width`, `height` on start): a display of its own
2098 on the machine (Xvfb, a window manager, its own session and browser profile) where an agent works without touching
2099 the person's screen, which the person can watch and take over. `screen`, `input` and `browser` take `desk: private`
2100 to act there instead of on the person's screen (`main`, the default). Starting and stopping act (refused at observe,
2101 approved one by one at ask); status runs at every level. Fixtures for both.
2102- **Support inboxes open to developer apps** (the owner, 2026-10-24/25: openvibe.chat "fully modular and SDK and
2103 API"). Three public, sensitive capabilities owned by `chat`, on the routes OpenVibe.Chat already serves; an app acts
2104 only for the person who authorized it (`on_behalf_of`), and that person's role in the inbox decides the rest:
2105 - `chat.inbox.read`: the inboxes the person works in, conversations (waiting first), messages, saved replies, and
2106 the owner's export (JSON or CSV);
2107 - `chat.inbox.reply`: reply, resolve, reopen, give back to Vibe, assign, mark read, translate;
2108 - `chat.inbox.manage`: make an inbox, and as its owner change it (Vibe, sites, hours, routing, retention), its people,
2109 saved replies, webhooks, actions and verified visitors.
2110- **Schemas:** `chat.inbox-request@1`, `chat.inbox-result@1`, `chat.inbox-reply-request@1`,
2111 `chat.inbox-conversations-result@1` (public), with fixtures.
2112- **`capability@1`:** `resourceConstraints` may say `inbox_member`.
2113
2114## 0.213.0 — 2026-10-25
2115
2116- **Plain names in every menu** (the owner, 2026-10-24: make the products consumer-friendly and familiar, with the
2117 developer side on OpenVibe.Services; plan of record track K). The `site` names and lines the launcher, the footer
2118 and Network's home show:
2119
2120 | Service | Name | Line |
2121 |---|---|---|
2122 | actor | Agents | Agents that work while you are away |
2123 | bot | Robots | Drive any robot from your browser |
2124 | codes | Code | Build and fix apps with AI |
2125 | watch | Alerts | Know the moment it changes |
2126 | work | Jobs | Find work, with an agent on your side |
2127 | rent | Rentals | Every rental site, one search |
2128 | trade | Markets | Watchlists and alerts |
2129 | host | Hosting | Hosting, compared honestly |
2130 | vip | Memberships | Memberships for creators and their software |
2131 | space | Spaces | Make a space: an app on your account |
2132 | quest | Quests | Badges for what you really do |
2133 | inventory | Items | Your items, on every OpenVibe site. |
2134 | run | Compute | Run jobs on machines that can. |
2135 | zone | Storage | Private S3-compatible storage for your projects. |
2136 | ai | AI API | Many models, one API. Every answer explained. |
2137 | play | Game services | Achievements, leaderboards and cloud saves for every game. |
2138
2139 - Chat's line is now "Chat with Vibe, friends and groups": Vibe, OpenVibe's assistant, lives at openvibe.chat/vibe
2140 (OpenVibe.Chat#139).
2141 - Service ids, domains, capabilities and events are unchanged: only what people read.
2142- **`turn_epoch` on a device command** (`bot.device-message@1`, additive). This was the community LOOI driver's
2143 reviewers' question A2. It carries the robot's control epoch when Bot decided the command: it rises when a queue turn
2144 ends, is left or is paused by an owner takeover (OpenVibe.Bot#155), and Bot's halt for that change carries the new
2145 value. A device or plugin may refuse a command older than the newest halt's epoch. It is milliseconds on Bot's
2146 clock, so it keeps rising across Bot restarts. Older devices ignore it (Node's decoder skips unknown fields).
2147
2148## 0.212.0 — 2026-10-24
2149
2150- **A tab-separated body, and which duplicate wins** (OpenVibe.Food's BLS prices). An api endpoint of
2151 `sources.source@1` and `sources.source-write-request@1` may say `"format": "tsv"`: a file whose first line names the
2152 columns, read as an array of records keyed by those names (`items_path` is ""). `"duplicates": "first" | "last"` says
2153 which of two records with the same identity is kept (first, as before, by default); BLS's series files list each
2154 series oldest to newest, so `last` keeps its newest month.
2155- **`extra_lists` on an api endpoint of a source** (plan 2026-10-22, track F2). `sources.source@1` and
2156 `sources.source-write-request@1` take, beside `extra`, up to ten list fields: each maps to a path whose array of
2157 scalars Sources keeps as up to 20 of them (a lone scalar is a list of one, a missing value an empty list). Job boards
2158 give tags and job types as arrays, which `extra` reads as null; OpenVibe.Work filters by both, so it can follow
2159 Arbeitnow through Sources without losing them. Additive: an older reader ignores the field, and `extra` is unchanged.
2160- Catalog copy checked against each product's code once more (plan 2026-10-22, track H5; Bot, Actor and Help were
2161 fixed in 0.210.0).
2162 - **OpenVibe.Watch** promised what it does not do:
2163 - "videos, streams and cameras" as sources, "AI summaries", and keywords for YouTube video analysis and security
2164 camera alerts (the `ai` extraction and the browser rung do not exist yet);
2165 - "robots rules" on every check (Watch reads no robots.txt; it sends the site's validators, spaces requests per
2166 host and honours Retry-After).
2167 - It also left out what it does: a price, OpenVibe events and webhooks with no polling, a device on your own
2168 network checked by your computer, and actions that start an Actor agent or a coding task, all on its site.
2169 - "Next" is now browser checks and AI summaries.
2170 - **OpenVibe.Quest**'s "Next" named OpenCoins rewards (on in production), quests for OpenVibe.Games (counted:
2171 joining and publishing a world) and quests streamers and communities write, which its own FAQ rules out; the
2172 "streamer quests" keyword goes too.
2173 - **OpenVibe.Work**'s "Next" named Watch alerts and the Actor helper, both live: any search is an Atom feed Watch
2174 follows, and the agent drafts an application and asks before each step.
2175 - **OpenVibe.Food**'s "Next" named the household chat, which is live: a household opens a room on OpenVibe.Chat with
2176 Pantry, an AI member that knows the plan and every cupboard.
2177 - Pics, Download, Video, Rent, Homes, Events, Services and Zone read true against their code.
2178
2179## 0.211.0 — 2026-10-23
2180
2181- **`retire_after_sec` on a source** (plan 2026-10-22, track F2). `sources.source@1` and
2182 `sources.source-write-request@1` take an optional integer (an hour to a year) or null. Once a fetch of the source
2183 succeeds, an item it has not seen for that long is removed with reason `gone_from_source`: a change in the feed, so a
2184 consumer following `GET /api/v1/items` learns that the job or the listing is gone. Sources kept every item it ever saw,
2185 so OpenVibe.Work could not follow Arbeitnow through it without showing closed jobs. null, the default, keeps today's
2186 behaviour for news, prices and datasets. Additive: an older reader ignores the field.
2187
2188## 0.210.0 — 2026-10-22
2189
2190- **Sources categories `housing`, `food` and `jobs`** (plan 2026-10-22, track F1). `sources.source@1`,
2191 `sources.item@1`, `sources.source-write-request@1` and the four `sources.*` event payloads accept them, so the
2192 owner's top aggregators can move their own fetches into Sources:
2193 - OpenVibe.Rent's and Homes' listings and rent data;
2194 - OpenVibe.Food's recalls and food data;
2195 - OpenVibe.Work's job boards.
2196
2197 They then share Sources' robots and terms checks, retention and the Search feed. A consumer that switched on the
2198 old nine values should treat an unknown category as "other". Nothing in production sends the new values until
2199 Sources pins this release.
2200- Catalog copy that promised what the products do not do (plan 2026-10-22, track H5), checked against each product's
2201 code. **OpenVibe.Bot**:
2202 - Its description, FAQ and keywords named ESP32 boards, Android apps, ONVIF and RTSP cameras, ready-made bots to buy
2203 and "kits that list exactly what to buy". None ships:
2204 - OpenVibe sells no hardware, and the one curated kit (Adeept ADR036) is a parts list;
2205 - the ONVIF camera is a server-side connector the operator configures.
2206 - It now names what Bot's profiles and drivers run: the Adeept kit, ROS 2, Cozmo, LOOI, a phone in its browser, and
2207 the generic relay for anything else.
2208 - The planned-site `vision` block (robot arms, telepresence bots, a recording toggle, "flash a ready-made card")
2209 and the `plannedRepo`/`meanwhile` pointers go, as for the other live products; nothing reads them since
2210 OpenVibe.Sites retired.
2211- **OpenVibe.Actor**'s cost answer gives its real free tier (20 tasks a day, $0.05 a task, $0.25 a day), not "limits
2212 published before launch".
2213- **OpenVibe.Help** no longer says "live or coming": every site it covers is live.
2214- The catalog changes are text only.
2215
2216## 0.209.3 — 2026-10-21
2217
2218- Codes' site text names OpenVibe Git at `git.openvibe.codes`, where it moved on 2026-10-21 (Codes#93; the old
2219 `openvibe.codes/git` redirects there), and its "Where is the code?" answer mentions the read mirrors there.
2220 Network's frame footer prints `site.what` on Codes' pages. Text only, with no schema or status change.
2221
2222## 0.209.2 — 2026-10-21
2223
2224- The service manifests of Reviews, Tips and VIP no longer say they are "deployed internally (loopback only), not
2225 launched publicly" behind the OpenVibe.Sites placeholder. Reviews has been public since 2026-10-09, and Tips and
2226 VIP since 2026-10-17. Network's public registry API served the old notes. Notes only, with no schema or status change.
2227
2228## 0.209.1 — 2026-10-21
2229
2230- The four Watch capabilities (`watch.watch.read`, `watch.watch.manage`, `watch.observation.read`, `watch.check.run`)
2231 no longer say "PLANNED (plan T18; OpenVibe.Watch is not built yet)" or that they become active once Watch implements
2232 their routes. They have been `active` since Watch launched on 2026-10-08, and openvibe.services' capability docs
2233 printed the old note beside each. Descriptions only, with no schema or status change.
2234
2235## 0.209.0 — 2026-10-20
2236
2237- OpenVibe.Space's site capabilities are public, so a developer app can be granted them: `space.deploy.create`
2238 (sensitive: upload, activate and roll back deploys — "an app principal added to a project as deployer can deploy
2239 from CI", which no app could do while it was first-party), `space.site.config` (headers, local redirects, the SPA
2240 fallback), `space.site.manage` (sensitive: sites and members; apps still cannot own projects) and
2241 `space.domain.manage` (sensitive: custom domains, served only after DNS TXT verification). Space judges every one by
2242 the acting principal's project role as well: an app is a principal of its own and can touch only the projects a
2243 person added it to, as deployer, maintainer or owner. Sandbox tokens stay confined to sandbox projects.
2244
2245## 0.208.0 — 2026-10-20
2246
2247- Coupons, Deals and Trade open what a person does for themselves to apps (all three already act for an app only as
2248 its `on_behalf_of` person and refuse sandbox tokens):
2249 - Coupons: `coupon.lookup` and `merchant.resolve` (public data), `coupon.submit` (sensitive: a code under the
2250 person's name, status unknown until reports) and `report.create` (worked or failed, one a day per code).
2251 - Deals: `offer.submit` (sensitive), `offer.update` (the person's own offers, or a new price observation),
2252 `flag.create`, `vote.set` (sensitive) and `vote.remove`, and `watch.create`, `.read` and `.delete`.
2253 - Trade: `instrument.resolve`, and the person's own `watchlist.*` and `alert.*`.
2254- Moderation (`coupons.status.update`, `coupons.merchant.manage`, `deals.offer.moderate`, `.merge`, `.expire`),
2255 `deals.product.resolve` (which creates products) and `trade.context.read` (drafts awaiting review and OpenVibe.AI's
2256 workflow input) stay first-party.
2257
2258## 0.207.0 — 2026-10-20
2259
2260- Reviews and the Wiki open their reads to apps: `reviews.entity.resolve` (look up a business, product or place and
2261 read its record and history), `reviews.correction.submit` (send a correction to the editors' queue for the person),
2262 `wiki.page.read` and `wiki.search.query` (what the person may read; without a person, public pages only) are
2263 `public`. Both services already act for an app only as its `on_behalf_of` person and refuse sandbox tokens. News'
2264 `story.read` and `cluster.read` stay first-party: they are the editorial reads (drafts, flags, ingestion), and
2265 published stories need no capability. `wiki.revision.propose` stays first-party (it is OpenVibe.AI's output).
2266
2267## 0.206.0 — 2026-10-20
2268
2269- Blog's posts are open to apps: `blog.feed.read` and `blog.post.create`, `.read`, `.update`, `.publish`,
2270 `.unpublish`, `.schedule` and `.delete` are `public` (they were `first-party`), so Network can grant them to a
2271 developer app for the person who authorizes it. Blog already acts for an app only as its `on_behalf_of` person
2272 and refuses sandbox tokens; AI-origin drafts (`X-OV-Origin: ai`) stay first-party, since only a `svc:` principal
2273 may set it. Publishing, unpublishing, scheduling and deleting are `sensitive`. Creating a blog, its settings,
2274 members and theme stay first-party. This is the first step of the roadmap's "Every product in the SDK" for products
2275 whose API only their own site could use.
2276
2277## 0.205.4 — 2026-10-20
2278
2279- Live's site block leads with what it is for: the tagline is "Go live from your browser" (it was "Streams, clips and
2280 chat") and the summary says no OBS, no downloads, no follower minimum. It still described ARENA ALERT, the drama desk,
2281 with the Lolcow Index and the Clout Rankings, which The Rundown replaced on 2026-10-19; the Arena question in its FAQ
2282 is now "What is The Rundown?". The share card, the launcher and the help centre read these.
2283
2284## 0.205.3 — 2026-10-19
2285
2286- Host's catalog entry says what it is since the 19 October maintenance: offers from LowEndSpirit's Offers board (it
2287 named LowEndTalk and LowEndBox, whose feeds refuse the production host), benchmarks people run with YABS, and the
2288 console for your own servers on Linode, DigitalOcean, Vultr and Hetzner Cloud, with a question for each.
2289
2290## 0.205.2 — 2026-10-19
2291
2292- openvibe.website is a moved address (`kind: "moved"`, service `space`, linking to OpenVibe.Space): the apex redirects
2293 to openvibe.space and published sites take names under it, so the help centre no longer lists it as a site "still
2294 coming".
2295
2296## 0.205.1 — 2026-10-18
2297
2298- Space's catalog entry describes spaces as built (they shipped 2026-10-16; it said "next and not built yet"), and its FAQ
2299 says plainly that publishing for everyone waits on abuse handling and a designated DMCA agent.
2300
2301## 0.205.0 — 2026-10-18
2302
2303- `sources.source@1`, `sources.item@1`, the source write request and the `sources.item.*` / `sources.fetch.failed`
2304 payloads: a `games` category, for game store data OpenVibe.Games shows (Steam's featured lists: top sellers, new
2305 releases and specials, read from store.steampowered.com/api, which its robots.txt allows).
2306- `quest` consumes `network.subject.merged`: account merges move a person's quests to the survivor (OpenVibe.Quest#65).
2307
2308## 0.204.1 — 2026-10-18
2309
2310- Catalog says what each site is today (owner: "lots of stuff across websites is still unfinished / coming soon / next
2311 steps"): every stale `launch` note is gone (Actor, Bot, Download, Events, Help, Pics, Quest, Rent, Services, Watch,
2312 Work, Website, Zone, Coupons, Host, News, OpenRestream, Reviews, Space, Tips and VIP are live), and so are the "Next"
2313 pillars (Pics, Video) and "planned"/"comes later" sentences (Services, Video, Pics, Events, admin, themes).
2314 openvibe.website describes OpenVibe.Space (where it redirects) and Zone its live S3-style storage, in the present tense.
2315- FAQs for the 16 sites Help showed with none: Download, Events, Homes, Pics, Services, Video, Website, Zone, News,
2316 Reviews, Run, Tools, Trade, Wiki, Play and Search. Quest's FAQ: OpenCoins rewards are on (`QUEST_COINS=on`).
2317
2318## 0.204.0 — 2026-10-18
2319
2320- `sources.source@1`: an api endpoint may carry `timeout_ms` (1 s to 120 s), its own fetch deadline instead of the
2321 deployment's (OpenVibe.Sources#76: NYC Open Data computes the HPD per-building violation tally in 12 to 60 seconds).
2322
2323## 0.203.0 — 2026-10-17
2324
2325- `billing.stats.read` (`GET /api/v1/stats`, `billing.stats-result@1`): network-wide money counts with no person in them
2326 (Vibes bought with money, channel subscriptions active and started, recent windows and daily series), so a product's
2327 public stats read Billing, the money ledger, instead of tables that stopped at the cutover (OpenVibe.Live's home).
2328
2329## 0.202.0 — 2026-10-17
2330
2331- OpenVibe.Tips: other ways to support a creator, paid outside OpenVibe (the owner's 10-08 ask: Billing is provider
2332 agnostic; creators bring Ko-fi, PayPal.me, Patreon and other links). Optional `support_links` on `tips.profile@1`
2333 (`{ provider, label, handle, url }`, Tips builds the link) and on `tips.profile-update-request@1`
2334 (`{ provider, handle }`, at most 8). Providers: Ko-fi, PayPal.me, Patreon, Buy Me a Coffee, Cash App, Venmo, GitHub
2335 Sponsors, Liberapay, Open Collective, Streamlabs and StreamElements tip pages.
2336
2337## 0.201.0 — 2026-10-17
2338
2339- Subscription tiers priced by OpenVibe.Billing (the owner's VIP ask: creator memberships with tiers). New capability
2340 `billing.tier.manage` (`GET /api/v1/tiers/:streamer`, `PUT /api/v1/tiers/:streamer/:tier`) with `billing.tier-request@1`
2341 and `billing.tier-result@1`: the product where a creator sells tiers (OpenVibe.VIP) sets each tier's monthly price
2342 within Billing's bounds; Billing keeps and charges it (ADR-012). Optional `tier` on `billing.intent-request@1`
2343 (subscriptions), `billing.subscription-request@1` and `billing.entitlement@1`. Tier 1 without a price keeps the site's
2344 default subscription price, so nothing changes for anyone who does not set tiers.
2345
2346## 0.200.0 — 2026-10-17
2347
2348- OpenVibe.Tips and OpenVibe.VIP are live sites (`exposure.state: live`, `publicSite: service`) now that OpenVibe.Billing is
2349 the money ledger. Tips: a tip page per creator, paid messages, text-to-speech, media requests, paid sounds, goals and OBS overlays on
2350 any platform. VIP: memberships open to anyone, with perks across OpenVibe and subscriptions to people's own software
2351 (openvibe-sdk/vip). Both catalog entries say so, with FAQs, and name what comes next.
2352- Tips: paid sounds (the owner's "paid soundboard … triggers"). A new interaction `kind: sound` appears in every Tips
2353 kind enum (interaction, public interaction, moderation view, simulation request, and the tips.interaction.ready,
2354 failed and cancelled payloads). Optional `sound` fields cover the paid and simulation requests (`{ id }`) and the
2355 interaction and public interaction (`{ id, name, url }`). The profile gets optional `sounds` (`enabled`, up to 12
2356 `items`) and `minimums.sound`; the profile update gets `sounds_enabled` and `sound_min`. Capability
2357 `tips.sound.request` covers `POST /api/v1/sound-requests`. Everything is optional or additive, so the current
2358 Tips release still validates.
2359
2360## 0.199.3 — 2026-10-16
2361
2362- Chat's catalog copy says what it is now: rooms with AI members on their own models with tools, Discord-style servers
2363 with roles, invites and text and voice channels, pictures, DMs, global and stream chat (Chat#102-#109). Its tagline
2364 is "Group chats with AI, servers and voice".
2365- Space's summary adds that spaces run their own server code (space functions, Space#62).
2366
2367## 0.199.2 — 2026-10-16
2368
2369- Space's catalog copy names spaces (small apps on a person's OpenVibe account: the AI builder, templates, the editor,
2370 sign-in, shared lists, private storage and AI; Space#58) ahead of static hosting, with a FAQ (`site.faq`).
2371
2372## 0.199.1 — 2026-10-16
2373
2374- Chat's FAQ (`site.faq` in its service manifest): one account everywhere, servers with text and voice channels and
2375 roles, AI members in rooms (OpenVibe's AI or the person's own key, with tools), pictures through OpenVibe.Pics.
2376- Live's one-line `what` names ARENA ALERT, the drama desk on every stream.
2377
2378## 0.199.0 — 2026-10-16
2379
2380- `host.index_document.upserted` / `.deleted` v1 also carry **domain endings** (type `tld`, id `tld-<tld>` such as
2381 `tld-dev` or `tld-co.uk`, page /catalog/domains/<tld>): the cheapest first year, renewal and five years at any
2382 registrar, facets kind, register_usd, renew_usd.
2383
2384## 0.198.2 — 2026-10-16
2385
2386- FAQs for the twelve sites whose Help pages had none: Live, Blog, Codes, Community, Coupons, Deals, Games, Host,
2387 Media, Network, Inventory and the AI service (`site.faq` in their service manifests).
2388
2389## 0.198.1 — 2026-10-16
2390
2391- Host's catalog copy names what openvibe.host compares today: plans, the offers providers post on LowEndTalk and
2392 LowEndBox, and domain prices (first year, renewal, transfer, five years per ending) with a name check at the registry;
2393 a "Domains too" pillar; the old line about Host's own static hosting opening after a review now points to
2394 OpenVibe.Space.
2395
2396## 0.198.0 — 2026-10-16
2397
2398- `rent.index_document.upserted` / `.deleted` v1 also carry **OpenVibe.Homes city pages** (type `homes_city`, the same
2399 `<state>-<slug>` id, canonical on openvibe.homes): the median home value and rent, sent by Rent's sweep.
2400
2401## 0.197.2 — 2026-10-16
2402
2403- Copy: OpenVibe.Work's "Will an AI apply for me?" says the Actor agent helps prepare applications today (it said the
2404 agent was coming), and OpenVibe.Quest's community-quests answer names the SDK's app quests that already work.
2405
2406## 0.197.1 — 2026-10-16
2407
2408- Copy: OpenVibe.Rent's FAQ says where the listings come from (every major rental site, opened at your place) instead
2409 of "nothing is copied in this first version", and answers "How do I know if a rent is fair?" (Rent by city, the rent
2410 check, the Companion); its pillars add Rent by city. OpenVibe.Play's tagline and `site.what` name cloud saves.
2411
2412## 0.197.0 — 2026-10-16
2413
2414- `rent.index_document.upserted` / `.deleted` v1 also carry **city pages** (type `city`, id `<state>-<city slug>`, e.g.
2415 `tx-austin`): OpenVibe.Rent's Rent by city pages with the typical rents by size (Census ACS), sent by its sweep.
2416
2417## 0.196.2 — 2026-10-16
2418
2419- Fix: `media-hub` declares `openvibe.pics` and `rent` declares `openvibe.homes` in `domains`. Network builds its CORS
2420 allow-list from manifest domains, so both sites' shared navbars were refused (403 on /api/auth/me: signed-in people
2421 saw "Sign In").
2422
2423## 0.196.1 — 2026-10-16
2424
2425- Copy: MediaHub's tagline is "Videos, pictures and your files" (it serves Video uploads, Pics and Download, not only
2426 Live's past streams), and OpenVibe.Games' is "Browser games, and worlds you build" (creator worlds since 0.193).
2427
2428## 0.196.0 — 2026-10-16
2429
2430- **MediaHub publishes events** (in its hyphen-free namespace `mediahub.*`, Events#91): `mediahub.video.published` v1
2431 (a person's upload is public and ready for the first time: `{ upload, owner, title, url, published_at }`, public) and
2432 `mediahub.picture.uploaded` v1 (a signed-in person's picture on OpenVibe.Pics: `{ picture, owner, uploaded_at }`,
2433 internal, without the link or title since pictures are unlisted). MediaHub's eventsProduced; Quest consumes both
2434 for its "Publish a video" and "Share a picture" quests.
2435
2436## 0.195.2 — 2026-10-16
2437
2438- Copy: OpenVibe.Pics' pillars name resize and convert ("Any size, any format") and alt text, and its Next is AI image
2439 generation; OpenVibe.Video's AI edit names the AI cut and its playlists hold uploads; MediaHub's `site.what` follows.
2440
2441## 0.195.1 — 2026-10-16
2442
2443- Copy: OpenVibe.Download says what is live (a 25 GB drive, public or signed-in share links, folder backups with
2444 `openvibe-download`) instead of "will be" and "no anonymous downloads"; MediaHub's `site.what` names Download's
2445 backups and Video's uploads and playlists.
2446
2447## 0.195.0 — 2026-10-15
2448
2449- **Search documents for creator worlds:** `games.index_document.upserted` and `.deleted` v1 (type `world`,
2450 `/worlds/<id>`, id `w` + ten base-36 characters), `search.index-document@1` with the owner, type and id fixed, plus
2451 the tombstone. A published world is a document; unpublished, taken down or deleted, a tombstone. Games'
2452 eventsProduced; fixtures (valid document, tombstone; refused: bad id, other owner, tombstone as an upsert, other
2453 type, a full document as a tombstone).
2454
2455## 0.194.0 — 2026-10-15
2456
2457- **`games.world.published`** (OpenVibe.Games creator worlds): a player published one of their worlds for the first
2458 time `{ world, owner, title, url, published_at }` (public). Games' eventsProduced, Quest's eventsConsumed (the
2459 "Publish a creator world" quest). Games' `site.what` says players build and publish their own worlds.
2460
2461## 0.193.2 — 2026-10-15
2462
2463- Copy: Quest's `site.what` says developer apps add quests on their own events (Quest#55, SDK 0.47.0).
2464
2465## 0.193.1 — 2026-10-15
2466
2467- `generated/openapi/quest.json`: Quest's routes now that it declares a capability (left out of the 0.193.0 commit).
2468
2469## 0.193.0 — 2026-10-15
2470
2471- **App quests** (the owner's "moddable in the SDK" for Quest): capability `quest.app_quest.manage` (owner quest,
2472 public, project-scoped) and `quest.app-quest-request@1` / `quest.app-quest@1`. A developer app defines quests on its
2473 own project's events (`app.<project_key>.<name>`, the actor a person); OpenVibe.Quest counts production events only,
2474 keeps at most 20 per project, and rewards a badge named for the app — never OpenCoins.
2475
2476## 0.192.0 — 2026-10-15
2477
2478- **`bot.robot.online` / `bot.robot.offline`** gain an optional `owner` (the robot owner's `usr_` subject; absent from
2479 older events): OpenVibe.Quest credits the owner's "Bring a robot online" quest from it (the audit's device and robot
2480 quest type).
2481- **Quest consumes** `blog.post.published`, `deals.offer.created`, `deals.vote.changed`, `run.job.succeeded`,
2482 `inventory.item.equipped` and `bot.robot.online` (Quest#53 and the robot quest): quests on Blog, Deals, Run,
2483 Inventory and Bot.
2484
2485## 0.191.1 — 2026-10-15
2486
2487- **Copy** (copy only): Deals' site names its crowdfunding discovery (Deals#62: one search across Kickstarter,
2488 Indiegogo, GoFundMe and more, beside Open Collective campaigns) and drops its `launch` (DealNews is on). Food gains the
2489 "A recipe library" pillar (Food#55: budget recipes written by AI from the food list, costed by Food).
2490
2491## 0.191.0 — 2026-10-15
2492
2493- Sources category `crowdfunding` (`sources.source@1`, `sources.item@1`, `sources.source-write-request@1` and the
2494 `sources.item.created|updated|removed` and `sources.fetch.failed` payloads): campaigns and collectives raising money in
2495 the open, read by OpenVibe.Deals' crowdfunding discovery (the owner's crowdfunding aggregator ask).
2496- Sources `api` endpoints may set `request_content_type` (`application/json` only): sent as the Content-Type of the
2497 endpoint's GET. Open Collective's public GraphQL API answers a GET only with it (its CSRF guard).
2498
2499## 0.190.1 — 2026-10-15
2500
2501- **Copy for what shipped on 2026-10-15** (copy only): OpenVibe.Homes is live (served by OpenVibe.Rent, Rent#58): every
2502 for-sale site at once, foreclosures, land and commercial, county records, FHFA prices and a mortgage calculator; its
2503 `launch` and `noRepo` are gone. OpenVibe.Video uploads, records in the browser and makes AI captions, chapters and a
2504 summary (MediaHub#67-#71). Trade covers every company on SEC's ticker list with reported numbers and cited AI briefs
2505 (Trade#68-#70; `launch` gone). Food fills the cupboard by barcode, shelf photo or receipt (Food#53-#54; `launch` gone).
2506 Blog's `site.what` names the AI desks (Blog#57); Codes' names OpenVibe Git at openvibe.codes/git (Codes#85-#86).
2507
2508## 0.190.0 — 2026-10-15
2509
2510- **`live.setup.task_completed`** (owner live, internal; Live produces, Quest consumes): a streamer finished one of the
2511 18 tasks of Live's go-live setup hub for the first time. Payload `{ task, user, title, group, completed_at, done,
2512 total }`, `task` one of the hub's ids (slot, method, restream, golive, profile, offline, emote, sound, goal, powerchat,
2513 panels, share, mods, requests, moderation, robot, aibot, paste). The owner's Q16: Live's setup steps become quests.
2514
2515## 0.189.1 — 2026-10-15
2516
2517- **Food compares delivery** (Food#52): its product description, pillars and `site.what` say one search opens every
2518 delivery app and meal kits are side by side; the household chat is named as next.
2519- **Rent's board and the Companion** are built (Rent#55, Extensions v0.2.0): the product description and pillars say
2520 so instead of naming them as next. Copy only.
2521
2522## 0.189.0 — 2026-10-15
2523
2524- **`food.household.read`** (owner food, internal, granted to Chat): a household's pantry and plan as plain text for
2525 the AI member of its OpenVibe.Chat room, `GET /internal/households/:planId/chat-context` →
2526 `food.household-chat-context@1` `{ text, source, updated_at }` (new contract, with fixtures). The owner's Q15: a Food
2527 household's group chat with an AI member that knows what is in the cupboard. Chat's AI members (Chat#102) read it
2528 with Chat's own service token; Network grants it (Network follows); Food serves it (Food follows).
2529
2530## 0.188.3 — 2026-10-15
2531
2532- **OpenVibe.Pics is live** on openvibe.pics (MediaHub#64): the product's tagline, description and pillars, and
2533 media-hub's `notes` and `site.what`, say what it is now: signed-in picture uploads re-encoded without metadata,
2534 unlisted share and embed links, albums, reports and takedowns. Signed-out uploads and AI image tools are named as
2535 next. The `pics.*` capabilities stay planned (no app may call the API yet). Copy only.
2536
2537## 0.188.2 — 2026-10-15
2538
2539- **Rent is the rental aggregator** the owner asked for. Its `site.tagline` and `site.what`, and the product's tagline,
2540 description and pillars, now say: one search opens Craigslist, Facebook Marketplace, Zillow, Apartments.com, Zumper
2541 and more, next to HUD affordable housing and listings posted here (Rent#53). "Nothing scraped" is gone.
2542 Copy only.
2543
2544## 0.188.1 — 2026-10-15
2545
2546- **Quest's site text:** quests pay badges and OpenCoins. OpenCoins have been credited since `QUEST_COINS` was switched on, but the
2547 `site.what` and the product description still said "once they are switched on" (Network's front door and Help read
2548 them). Copy only; no schema or capability changes.
2549
2550## 0.188.0 — 2026-10-15
2551
2552- **`coupons.watch.matched` v1:** a person watching a merchant on OpenVibe.Coupons is told when a code for it is
2553 publicly listed (created published, or approved from review). One event per (watcher, coupon), never for the code's
2554 submitter, inside the listing's transaction. Coupons produces it, and OpenVibe.Network consumes it into an inbox
2555 notification linking the coupon page, as for `deals.watch.matched`. The payload carries no code text. Coupons'
2556 watches had been recorded but never delivered.
2557
2558## 0.187.0 — 2026-10-15
2559
2560- **openvibe.video: playlists are built** (MediaHub's `/playlists`, its API and "Add to playlist" on every watch
2561 page; MediaHub#55 puts Playlists in the navbar). The pillar list gains Playlists, and "Next" names only uploads and
2562 publishing to other platforms.
2563
2564## 0.186.0 — 2026-10-15
2565
2566- **More pillars say what is built** (the 0.184.0 audit, finished): openvibe.download has no AI search or summaries
2567 and no sync (its drive, share links, sign-in rule and reports instead); openvibe.quest has no quest creation for
2568 people (one log across eight sites, real activity only, badges, games); openvibe.rent does not gather other sites'
2569 listings or summarise them with AI (posted by people, HUD affordable housing, alerts through Watch, your account);
2570 openvibe.help has no anonymous or email inbox and no project widget (answers from the manifests, one search,
2571 tickets, every site); openvibe.zone's keys scope zones, not people, and zones do not back streams (keys you scope,
2572 any S3 tool); openvibe.actor calls its models directly, not through OpenVibe.AI, and there is no Website yet.
2573
2574## 0.185.0 — 2026-10-15
2575
2576- **openvibe.food: "Plan together" is a pillar again, because it is built** (Food#39). A saved meal plan is shared with
2577 a household by a link shown once (only its hash is kept), and everyone in it ticks the shopping list off for
2578 everyone. Delivery price comparison stays out: the delivery apps publish no open prices.
2579
2580## 0.184.0 — 2026-10-15
2581
2582- **The catalog says what each site does today.** OpenVibe.Help shows every site's pillars as "What you can do".
2583 Several pillars promised features that are not built; they now repeat what each site's own front page lists as
2584 working.
2585 - **openvibe.food:** "Compare delivery", "Kits & boxes" and "Plan together" are not built. The pillars are now its
2586 food near you, meal planner, food list and cupboard recipes. The prices FAQ no longer promises live delivery
2587 prices, and `keywords` and `launch` follow suit.
2588 - **deals:** prices as of a time, votes, compare across stores, watches and saved searches. There are no AI
2589 summaries.
2590 - **news:** cited paragraphs, revisions on the record, source checks, discussion. There are no "many angles" or
2591 framing controls.
2592 - **coupons:** shop matching, stated restrictions, honest expiry, reports from people. There is no browser helper.
2593 - **trade:** find an instrument, values with their times, filings, watchlists and alert rules.
2594 - **reviews:** sourced signals, a checkable aggregate, history, editor summaries.
2595- **openvibe.pics is not a live domain of media-hub.** It is parked: MediaHub answers its host with a 302 to
2596 openvibe.network. Listing it made Help call Pics "live". Its product manifest stays its catalog home.
2597
2598## 0.183.0 — 2026-10-15
2599
2600- **Ask Actor from chat** (plan T17, "Reach"). OpenVibe.Actor consumes `chat.message.created` and calls
2601 OpenVibe.Chat's service API with `chat.message.send`.
2602 - **What it answers:** a signed-in person's `@actor <task>` in the global chat or their own channel becomes their task.
2603 - **Public tools only:** the task never uses the person's computers, robots or code.
2604 - **The reply** is posted back in the same room, answering the message.
2605 - Guests, relayed external chatters and other people's channels are ignored.
2606 - The service manifest's `eventsConsumed` and notes say so.
2607
2608## 0.182.0 — 2026-10-15
2609
2610- **The live screen** (plan T14, OpenVibe Link v0.12.0): `bot.device-message@1` commands take the kind `screen_stream`.
2611 Its value is `{ action: 'start', whip_url, publish_key, seconds?, fps? }` or `{ action: 'stop' }`. It shows the machine's
2612 screen live to its owner on the machine's own OpenRestream stream: playback private, no recording, never mirrored to
2613 Live.
2614 - Bot alone fills in the WHIP URL and key. The kind is not in `bot.command@1`, so no operator, agent or service can
2615 send it or choose where the screen goes.
2616 - `bot.computer.control` says so too.
2617- Devices: `deadline_ms` is the reply window of `screen_stream`, as of the other computer kinds.
2618
2619## 0.181.0 — 2026-10-15
2620
2621- **OpenVibe.Sites is retired** (plan T11, 2026-10-14). The service manifest's `status` and `exposure.state` are
2622 `retired`, with the reason in the note, and its repository record is no longer deployed. `scripts/docs-currency.js`
2623 skips a retired service whether or not an old checkout is around, and counts it apart (`44/44 current, 1 retired
2624 skipped`).
2625- **The estate covers every repository again** (`docs/ESTATE.md`, `manifests/repositories/`): 50, regenerated from
2626 current clones. It adds the ten built since the last refresh (Actor, Food, Help, Inventory, MediaHub, Play, Quest,
2627 Rent, Work, Zone), and the other 37 records now carry their current pins. `scripts/estate.js` reads symlinked
2628 checkouts, and a retired service's record is never "deployed".
2629- The 0.180.0 Sources descriptions named the implementing pull request as Sources#49; it is Sources#51.
2630
2631## 0.180.0 — 2026-10-15
2632
2633- **Sources api endpoints read catalogs that keep plans, hardware and prices apart** (Sources#51, for OVHcloud's public
2634 VPS catalog). `sources.source@1` and `sources.source-write-request@1`:
2635 - A path segment may carry a selector, `key[field=value,…]` (one to four conditions). It steps into the first
2636 element of the array `key` whose fields equal the values, compared as text. A value is literal text or
2637 `$rec.<path>`, read from the record. This is documented on `extra` and `where`; the field types are unchanged.
2638 - A `where` expectation may be `{ "pattern": "<regular expression, at most 200 characters>" }`, which the value must
2639 match as text.
2640 - `max_bytes` (an integer from 1 KiB to 32 MiB) sets one endpoint's body cap.
2641- Fixtures: a valid OVHcloud-shaped source with a selector, a pattern and `max_bytes`; an invalid pattern with an extra
2642 key; an invalid `max_bytes` over the cap.
2643
2644## 0.179.0 — 2026-10-15
2645
2646- **Watch uses project secrets** (ADR-056).
2647 - A source credential (`auth`) may name `secret_ref` instead of `env`: a project secret granted to `watch` for
2648 `reveal` to the source URL's origin, answered by OpenVibe.Network at fetch time.
2649 - A webhook action may name `secret_ref` instead of `secret_env`: a project secret granted to `watch` for `sign`, so
2650 Network signs each delivery and Watch never holds the value. Exactly one of the two is required.
2651 - `watch.watch-request@1` takes `project_env` (sandbox or production; production by default when the watch names a
2652 project), and `watch.watch@1` shows it.
2653- Fixtures: a watch with a project webhook secret, and an invalid webhook action with neither secret.
2654
2655## 0.178.0 — 2026-10-15
2656
2657- **Actor webhooks name a project secret** (ADR-044 §7, ADR-056). `actor.task-create-request@1` webhooks take
2658 `secret_ref`, the lower-case name of a project secret granted to `actor` for `sign`. OpenVibe.Network signs each
2659 delivery in the same headers, so Actor never holds the value, and no `webhook_secret` is minted when every webhook
2660 names one. A task outside a project is refused 422 `actor.webhook.secret_unavailable`.
2661- **`platform.task@1`** `secret_ref` accepts the ADR-056 lower-case names as well as the earlier upper-case
2662 environment-variable references.
2663- Fixtures: a valid task webhook with `secret_ref`, and an invalid one with spaces in the name.
2664
2665## 0.177.0 — 2026-10-15
2666
2667- **Project secrets (ADR-056).** OpenVibe.Network keeps secrets per project and environment, written once and used by
2668 name: no API returns a value to a person.
2669 - `network.project-secret@1`: what members and staff see (name, environment, version, a keyed fingerprint, grants,
2670 who set it and when).
2671 - `network.secret.use` (first-party, `POST /internal/secrets/use`): a service the project granted a secret to either
2672 signs a message with it (`sign`, HMAC-SHA256; the value never leaves Network) or receives the value for an https
2673 origin the grant lists (`reveal`). `network.secret-use-request@1` and `network.secret-use-result@1` refuse a sign
2674 without a message, a reveal without an origin, and either one mixed with the other's field.
2675 - Listed in Network's manifest. Fixtures: valid signing and reveal grants, sign and reveal requests and results;
2676 invalid a secret with its value, an upper-case name, an http origin, and mixed or missing fields.
2677
2678## 0.176.1 — 2026-10-15
2679
2680- **`media.object.s3`** lists CopyObject and UploadPartCopy (Media#113): server-side copies within the key's environment,
2681 COPY or REPLACE metadata, the copy-source conditions, part byte ranges, and the same commit path. A `versionId` source
2682 still answers NotImplemented. ADR-031's "what v1 leaves out" says the same.
2683
2684## 0.176.0 — 2026-10-15
2685
2686- **Person-owned resources can be controlled** (ADR-048 amendment, step 8 phase 2, the control half).
2687 `common.owned-resource-control-request@1` names a robot, room, restream definition or paste by its index kind and id
2688 and its owner (a person). It goes to the same `POST /api/v1/resources/control`.
2689 `contracts.resources.checkControlRequest` takes either form (`checkOwnedControlRequest` for this one) and refuses a
2690 person acting on someone else's resource.
2691- **Four control capabilities, active:**
2692 - `bot.resource.control`: stop and resume a robot's e-stop;
2693 - `chat.resource.control`: archive a room;
2694 - `openre.resource.control`: suspend and resume a restream definition;
2695 - `community.resource.control`: delete a paste.
2696
2697 Each is listed in its service's manifest.
2698- **Fixtures:** valid `bot-robot-stop` and `community-paste-delete-dry-run`; invalid `with-project`, `agent-owner` and
2699 `create`.
2700
2701## 0.175.0 — 2026-10-15
2702
2703- **`media.usage.recorded`** (ADR-031 section 8): Media's per-zone hourly rollups (`common.usage-recorded@1`). Each one
2704 names the zone twice: `resource` is its OVRN and `dimension` its id in lowercase. The series:
2705 - stored bytes (`media.object.upload`, `byte_hours`);
2706 - writes (`media.object.upload`, `media.object.delete`) and lists (`media.object.list`), each in `requests`;
2707 - reads (`media.object.read`), in `requests` and `egress_bytes`.
2708
2709 Media produces it. Network (the project's usage) and Zone (its usage view) consume it.
2710- **`media.object.s3`** lists multipart uploads (Media#109) and their routes. Copy and part copy still answer
2711 NotImplemented.
2712- **ADR-031:**
2713 - the interim `s3.openvibe.network` host behind Cloudflare, where a HEAD forwarded as GET is served (Media#110);
2714 - what v1 leaves out, now that multipart and the rollups exist.
2715
2716## 0.174.0 — 2026-10-14
2717
2718- **`browser`, a computer kind** (plan T14/T17 next step; OpenVibe Link's computer plugin 0.5.0). `bot.command@1` takes
2719 `{ action, url, selector, text, key, max_width }`:
2720 - `open` an http(s) `url`;
2721 - `click` a CSS `selector` or the button or link showing `text`;
2722 - `fill` a field (`selector`, `text`);
2723 - `press` a named key;
2724 - `back`, `read`, `screenshot` and `close`.
2725
2726 The browser is the agent's own, in a profile of its own on the person's machine. `read`, `screenshot` and `close` run at
2727 every level; the rest are refused at observe and approved one by one at ask. Below level full, `open` refuses an
2728 address on the machine's own network. `bot.computer.control` and the device frame list `browser`.
2729- **Fixtures:** valid `browser-open` and `browser-fill`; invalid `browser-open-file`.
2730
2731## 0.173.0 — 2026-10-14
2732
2733- **OpenVibe.Zone is live, and so is Media's S3 surface** (ADR-031 and its zone amendment). Zone owns named object
2734 zones per project environment at https://openvibe.zone (port 5050), provisioning each change in Media by revision.
2735 Media serves the zones as S3 buckets and keeps the objects.
2736- Zone's `zone.*` contracts and capabilities are now active, and two more are added: `zone.resource.read` and
2737 `zone.resource.control` (delete, for Services).
2738- **Media has three new capabilities:**
2739 - `media.object.s3`: the S3 door, reached with an access key;
2740 - `media.access_key.manage`: issue, list and revoke keys, for a project admin;
2741 - `media.zone.provision`: Zone only.
2742- **Access-key schemas:** `media.access-key@1`, `media.access-key-issue-request@1`, `media.access-key-issued@1` (the
2743 only answer with the secret) and `media.access-key-list@1`.
2744- **ADR-031 amendment 2026-10-14:**
2745 - Media issues the keys, not Codes: the verifier must hold the secret, and Codes became the coding harness.
2746 - The S3 surface is served by Host.
2747 - Zone serves on its apex until api.openvibe.zone has DNS.
2748
2749## 0.172.2 — 2026-10-14
2750
2751- **Who consumes `network.subject.merged`, written down.** Live, Chat, Community, Media and Games have folded merged
2752 accounts since ADR-029 (2026-09-27) and Play since 0.2.0, but none of their manifests listed the topic in
2753 `eventsConsumed`; all six do now. No change in behaviour.
2754
2755## 0.172.1 — 2026-10-14
2756
2757- **Play's site has its own icon.** `play`'s site block named the `games` icon, and the Network frame keys a site's
2758 navbar entry by its icon, so Play showed as a second Games. It names `play` (openvibe-shared 4.1.4's podium and star).
2759
2760## 0.172.0 — 2026-10-14
2761
2762- **`play`, a new service** (OpenVibe.Games ADR-0007 decision 10): OpenVibe.Play at play.openvibe.network (port 5040),
2763 the platform's game services. A title is registered by its own principal, which alone writes to it; it holds
2764 achievements and leaderboards (best or sum, this week and all time), idempotent score and unlock posts, and guest
2765 adoption. Boards and titles are public reads. People's rows are in the account export and erasure (consumes
2766 `network.account.export_requested` and `network.account.deleted`). Site block: Play, position 35 (the games icon).
2767- Capabilities (active, public): **`play.title.manage`**, **`play.result.write`**, **`play.player.read`**.
2768- Additive.
2769
2770## 0.171.0 — 2026-10-14
2771
2772- **`input`, a computer kind** (plan T14/T17, "keyboard and mouse input"): `bot.command@1` takes
2773 `{ action, x, y, width, height, dy, text, keys }`. move, click, double_click and right_click go to a point, scroll
2774 by `dy` clicks, type text into whatever has focus, or press one key or chord (`keys`: letters, digits, `+`, `-` and
2775 `_` only, for example `ctrl+s`). Coordinates are in the space of the screen picture the caller last saw (`width` and
2776 `height`, the `screen` kind's answer); the Link scales them to the real screen. The machine's level decides: refused
2777 at observe, approved one by one at ask. `bot.computer.control` lists it for a person's agent; the device frame
2778 lists it.
2779- Fixtures: valid `input-click` and `input-key`, invalid `input-key-shell`. Additive.
2780
2781## 0.170.0 — 2026-10-14
2782
2783- **`space.resource.control`** (active, first-party, sensitive): OpenVibe.Space's control API (ADR-048, plan T13 step
2784 10). `POST /api/v1/resources/control` takes `delete` for a `space.site`, `space.deploy` or `space.domain`, exactly as
2785 the API's DELETE routes (a site's deploys and domains go with it; the deploy being served, a default domain and anything
2786 taken down are refused with Space's own reason). Space decides by its own project roles (maintainer or owner). Dry runs; idempotent per
2787 (caller, project, key). The `space` manifest lists it. Additive.
2788
2789## 0.169.0 — 2026-10-14
2790
2791- **`actor.resource.control`** (active, first-party, sensitive): OpenVibe.Actor's control API (ADR-048, plan T13 step
2792 10). `POST /api/v1/resources/control` takes `stop` for a person's `actor.task` (cancel: a queued task ends at once, a
2793 running one is aborted and ends cancelled). The `actor` manifest lists it.
2794- **`media.resource.control`** (active, first-party, sensitive): OpenVibe.Media's control API. `delete` soft-deletes a
2795 person's `media.object` exactly as `DELETE /api/v1/objects/:id` does (restorable until its retention period ends; held
2796 and legacy-managed objects are refused). The `media` manifest lists it.
2797- Both: only the resource's owner, inside the OVRN's project; dry runs; idempotent per (caller, project, key). Additive.
2798
2799## 0.168.0 — 2026-10-14
2800
2801- **`events.resource.control`** (active, first-party, sensitive): OpenVibe.Events' control API (ADR-048, plan T13 step
2802 10). `POST /api/v1/resources/control` takes a `common.resource-control-request@1` for a project's subscription from
2803 a first-party service acting for its consumer. The actions are suspend (disable) and resume (enable); there are dry
2804 runs, and requests are idempotent per (caller, project, key). It is the second authority behind OpenVibe.Services'
2805 control route. The `events` manifest lists it.
2806- Additive.
2807
2808## 0.167.0 — 2026-10-14
2809
2810- **`probe`, a read-only computer kind** (plan T18 step 7, the `node` carrier): `bot.command@1` takes
2811 `{ target, timeout_s }`. The target is `http(s)://…`, one GET from the machine with no redirect followed, or
2812 `tcp://host:port`, which checks that it accepts a connection. Targets are on the machine's own network only:
2813 private, loopback or link-local addresses. The device `command` frame lists it.
2814- **`bot.computer.control`**: OpenVibe.Watch may send only `probe`, for owners who turned on "Let my watches check
2815 things from this computer". `watch.watch@1`'s `node` source documents `node_id` (the machine) and `probe` (that
2816 value).
2817- Additive. Fixtures: valid `probe`; invalid `probe-ftp`.
2818
2819## 0.166.0 — 2026-10-14
2820
2821- **Computer control (plan T14/T17, OpenVibe Link's `computer` plugin, Node#41).** `bot.command@1` takes the kinds
2822 `exec` (argv, cwd, timeout_s, stdin), `fs` (op list|stat|read|write|mkdir, path, offset, length, content_b64, mode) and
2823 `screen` (max_width), each with its value's shape. `bot.command-result@1` and the device `ack` of
2824 `bot.device-message@1` gain `data`: the machine's answer. The device `command` frame lists button, point and the
2825 computer kinds.
2826- **`bot.computer.control`** (active, first-party, sensitive): an agent service uses a person's own machine through
2827 `POST /api/v1/robots/:id/commands`. It works only for the machine's owner, and only when the owner turned it on for
2828 their agent. The owner's control level on the machine decides what may happen. The `bot` manifest lists it.
2829- Additive. Fixtures: valid `exec`, `fs-read`, `screen` and an ack with data; invalid `exec-shell-line`, `fs-bad-op`.
2830
2831## 0.165.0 — 2026-10-14
2832
2833- **`watch.resource.control`** (active, first-party, sensitive): OpenVibe.Watch's control API (ADR-048, plan T13 step
2834 10). `POST /api/v1/resources/control` takes a `common.resource-control-request@1` for a watch from a first-party
2835 service acting for the watch's owner: suspend, resume, delete; dry runs; idempotent per (caller, project, key). It is
2836 the first authority behind OpenVibe.Services' control route. The `watch` manifest lists it.
2837- Additive.
2838
2839## 0.164.0 — 2026-10-14
2840
2841- **Planned (plan T13):** `services.recipe.run` (POST /api/v1/recipes/:id/run, sensitive), `services.usage.read`
2842 (GET /api/v1/usage) and `services.cost.read` (GET /api/v1/costs) are project-scoped, first-party capabilities of
2843 OpenVibe.Services. Services does not serve them yet. The `services` manifest lists them.
2844- Additive (Contracts#114, re-applied on 0.163).
2845
2846## 0.163.0 — 2026-10-14
2847
2848- **`sources.source@1`: `extract` on an rss/atom endpoint** (plan T9, Sources#45). It reads the facts an item states in
2849 its own title or summary by the source's patterns: `kind`, `require`, and `fields` (`from` title|summary, `pattern`
2850 with one group, `as: date`). An item that yields every required field is stored as that kind with those fields.
2851 The first user is `dealnews-coupon-codes`: the coupon code, the shop and the stated end date of DealNews deals,
2852 read by OpenVibe.Coupons.
2853- Additive. Fixtures: valid `rss-extract`; invalid `extract-from-body`, `extract-no-require`.
2854
2855## 0.162.0 — 2026-10-14
2856
2857- **`codes.task.start`, `codes.task.read`, `codes.task.cancel`** (plan T16/T17): a first-party service starts a coding
2858 task for a person on OpenVibe.Codes (`POST /api/v1/tasks`, the person in `X-OV-Subject`), reads it and cancels it.
2859 - Codes runs the task on that person's own machine through OpenVibe.Run, in the project of their latest
2860 openvibe.codes/run task. Without one: 409 `codes.no_project`.
2861 - Only the service that started a task, for the same person, sees it.
2862 - OpenVibe.Actor is the first caller: its `codes` agent routes coding work there instead of refusing it.
2863- New contracts: `codes.task-start-request@1`, `codes.task-start-result@1`, `codes.task@1` (state, page URL, and once
2864 ended: ok, summary, files, patch, push, cost on the person's own keys, duration).
2865- Additive. `codes` declares the three capabilities in its service manifest.
2866
2867## 0.161.0 — 2026-10-14
2868
2869- **`platform.resource-offer@1`: `owner` for a user-owned offer** (plan T14, ADR-046). A person's own Node is offered with
2870 `owner` (`usr_…`), and such an offer is eligible only for that person's own workloads: a placer must never put a
2871 user-owned offer without an owner, or with another owner, on anyone's work, and a public projection leaves
2872 user-owned offers out. Until now nothing tied a user-owned offer to its owner, so a job naming `user-owned` could
2873 have been placed on a stranger's machine (no such offer had ever been published). Additive: `owner` is optional in
2874 the schema, and the rule is enforced by the placer (OpenVibe.Run) and the dispatcher (OpenVibe.Bot). The two
2875 user-owned fixtures carry an owner; a new invalid fixture has a malformed one.
2876
2877## 0.160.0 — 2026-10-14
2878
2879- **`bot.robot-profile@1`: `mapping.driver` may be `plugin`** (plan T15 "community-submitted profiles and drivers"): the
2880 robot is driven by a third-party OpenVibe Link plugin, named in `mapping.plugin`, that its owner installs on their
2881 Node. A community driver no longer needs a contract release of its own (as `looi` did); OpenVibe.Bot reviews and signs
2882 community profiles before robots can use them. New valid fixture `community-plugin.json`. Additive only: every
2883 existing profile stays valid.
2884
2885## 0.159.0 — 2026-10-14
2886
2887- **Contracts 0.159.0: sandbox-provider job contracts (plan T14 R4b, ADR-034; planned, internal).** What OpenVibe.Run
2888 sends to and reads from an external sandbox provider such as E2B or Fly Machines, the same shape as the
2889 browser-provider set: `sandbox-provider.job-create-request@1` (`id`, `class` code or linux, `args`, `inputs` pinned by
2890 sha256, `limits`, `egress`; no project, subject, requester or credential), `sandbox-provider.job-state@1` (`state`,
2891 `started_ms`, `finished_ms`, `wall_ms` as the provider's claim only, `exit_reason`, `exit_code`, `result`, `stdout` in
2892 Bot's ring shape) and `sandbox-provider.job-create-result@1` (`{ job, created }`). New capability
2893 `sandbox_provider.job.dispatch` (Run's own outbound call, `planned`, `implementedBy` empty). Additive only.
2894
2895## 0.158.0 — 2026-10-14
2896
2897- **`live.chat_mirror.write` is retired.** The Live read mirror is gone: Chat stopped its capture triggers
2898 (Chat migration 0006) and drops its table (0009), Live keeps no chat tables and reads through Chat's
2899 internal read API, and OpenVibe.Network revokes the grant at boot. The capability manifest stays loadable
2900 with status `retired`; `manifests/services/live.json` no longer lists it. No schema change.
2901
2902## 0.157.0 — 2026-10-14
2903
2904- **`bot.robot-profile@1`: `mapping.driver` may be `phone`** (plan T15 "an Android phone as the robot's brain"). A
2905 phone joins OpenVibe.Bot as a device from its own browser, with nothing to install: it pairs with a one-time code
2906 (or a QR code), publishes its camera over WHIP, speaks, shows a face or text, and reports its battery and tilt. The
2907 driver runs in the page (OpenVibe.Bot `public/phone-device.js`), not as a Link plugin. Additive only: every
2908 existing profile stays valid.
2909
2910## 0.156.0 — 2026-10-13
2911
2912- **OpenVibe.AI's catalog copy says the public API is live.** In `manifests/products/ai.openvibe.services.json`, the
2913 description says the public API and developer console are live, with OpenVibe.Live and OpenVibe.Network calling it
2914 too. `launch` and `relationships.meanwhile` are removed because the product is live and nothing blocks it. Copy only; no schema, capability or event changes. OpenVibe.Sites mirrors this manifest through
2915 `scripts/sync-catalog.js`, so it needs a pin bump and a resync.
2916
2917## 0.155.0 — 2026-10-13
2918
2919- **Contracts 0.155.0: browser-provider job contracts (plan T14 R4a, ADR-034; planned, internal).** What OpenVibe.Run
2920 sends to and reads from an external managed-browser provider: `browser-provider.job-create-request@1` (`id`, `class`
2921 browser, `args`, `inputs` pinned by sha256, `limits`, `egress`; no project, subject, requester or credential, so the
2922 provider never learns who pays), `browser-provider.job-state@1` (`state`, `started_ms`, `finished_ms`, `wall_ms` as the
2923 provider's claim only, `exit_reason`, `exit_code`, `result`, `stdout` in Bot's ring shape; no node, project or class
2924 field) and `browser-provider.job-create-result@1` (`{ job, created }`, 201 or 200 on an idempotent repeat). New
2925 capability `browser_provider.job.dispatch` (Run's own outbound call, `planned`, `implementedBy` empty). Additive only.
2926
2927## 0.154.0 — 2026-10-13
2928
2929- **Contracts 0.154.0: `services.resource.control` capability (ADR-048 control operations)** (first-party, active):
2930 `POST /api/v1/resources/control` on Services takes `common.resource-control-request@1` and answers
2931 `common.resource-control-result@1`. Services forwards the operation to the authority that owns the OVRN through
2932 `openvibe-sdk/resources`, is idempotent on `idempotency_key`, answers `unsupported` for an authority with no control
2933 endpoint, and refuses a sensitive action with `confirmation_required` until its owner confirms (WS-Z2). Permission
2934 `resources:control`; listed in Services' manifest capabilities. Additive only.
2935
2936## 0.153.0 — 2026-10-12
2937
2938- **Project delegation (ADR-003 amendment 2026-10-12).** A first-party service acting for a person (`X-OV-Subject`)
2939 may name one project with `X-OV-Project: prj_…`; the receiver checks with Network that the person is an admin or
2940 owner of the unarchived project (cache at most 60 s), records project, person and `via`, and shows the service only
2941 what it started. Apps, mods and agents never may (403 `project.not_delegated`).
2942- **`network.project.member.read`** (first-party, active): `GET /internal/projects/:project_id/members/:subject` on
2943 Network answers `network.project-member-result@1` (`project_id`, `subject`, `role`, `archived`, `added_at`); a
2944 non-member and an unknown project are the same 404 `project.member_not_found`. New schema with fixtures.
2945- **Watch:** `watch.watch-request@1` takes `project_id` (checked at save with that read). The `run-job` action takes
2946 `run.job-create-request@1` fields (`class`, `artifact`, `args`, `limits`, `egress`, `ttl_ms`) and `firing_arg`; the
2947 draft's `runtime`/`command`/`workload` stay in the schema for compatibility but Watch refuses them.
2948- `run.job-create-request@1`'s description states the delegated form. Additive only (compat vs 0.152.0: no breaking
2949 changes).
2950
2951## 0.152.0 — 2026-10-12
2952
2953- **`video.playlist.read` and `video.playlist.manage` are active.** openvibe.video's playlist API (MediaHub#33) takes a
2954 person's Network token, an app/agent/service token with one of these, or no token for a public or unlisted playlist
2955 by id and a person's public list (`GET /api/v1/video/users/:username/playlists`). An app owns playlists under its own
2956 requester and project and never touches a person's.
2957- New schemas (owner media-hub): `video.playlist@1`, `video.playlist-read-request@1`, `video.playlist-read-result@1`,
2958 `video.playlist-manage-request@1` and `video.playlist-manage-result@1`, with fixtures; the two capabilities name them.
2959 Additive only (compat vs 0.151.0: no breaking changes).
2960
2961## 0.151.0 — 2026-10-12
2962
2963- The media-hub site is named **Video** (tagline "Past streams, clips and your drive"): its public origin is openvibe.video,
2964 which serves the network's watch pages since MediaHub#28, and the network directory showed it as "Media Hub". Its id,
2965 icon and position are unchanged; openvibe.download stays in its description. No contract shape changes.
2966
2967## 0.150.0 — 2026-10-12
2968
2969- OpenVibe.Host removed its copy of the static hosting engine (Host#84); OpenVibe.Space serves it as `space.*` (0.149.0).
2970 The five engine capabilities (`host.site.manage`, `host.deploy.create`, `host.domain.manage`, `host.site.config`,
2971 `host.resource.read`) are retired with no routes, and the fourteen engine schemas (project, site, deploy, domain,
2972 site-config, their request/result pairs and the `host.deploy.activated` payload) are retired but stay loadable, each
2973 deprecated in favour of its `space.*` twin until 1.0.0. The host manifest keeps `host.catalog.manage`,
2974 `host.index_document.*` and `host.release.published`; Host answers the old routes with 410 `host.moved_to_space`.
2975- OpenVibe.Video's first slice is live on openvibe.video (MediaHub#28): the product text and the media-hub manifest say what
2976 it serves (watch pages for Live's recordings and clips, AI chapters and captions) and what is not built. `video.*` stays
2977 planned.
2978
2979## 0.149.0 — 2026-10-12
2980
2981- The static hosting engine moved from OpenVibe.Host to OpenVibe.Space (plan T20 step 2), so its contracts are now
2982 `space.*`: capabilities `space.site.manage`, `space.deploy.create`, `space.domain.manage`, `space.site.config` and
2983 `space.resource.read`; schemas `space.project`, `space.site`, `space.deploy`, `space.domain`, `space.site-config` and
2984 their request/result pairs; events `space.deploy.created`, `space.deploy.activated`, `space.deploy.failed` and
2985 `space.domain.verified`, each with a payload schema (Host only ever had one for `deploy.activated`). Tenant sites are
2986 `<site>.openvibe.website`; a custom domain is verified by `_openvibe-space.<hostname>`. The space manifest owns them
2987 and its catalog text says what is built (staff-only until the public launch).
2988- `space.site` uses the site id pattern the engine has always issued (`sit_`); `host.site` said `site_`.
2989- The `host.*` hosting ids stay until OpenVibe.Host has removed the engine; a later release retires them.
2990
2991## 0.148.0 — 2026-10-12
2992
2993- Catalog text (`site.what`) for rent, food, work and games names what shipped today: Rent's affordable housing from
2994 HUD open data, Food's recipe ideas, Work's application tracker with an Actor agent, Games' Salvage Rush and
2995 leaderboards. No contract shape changes.
2996
2997## 0.147.0 — 2026-10-12
2998
2999- `work.application.manage` (owner work): a person's tracked job applications on OpenVibe.Work, for apps and agents
3000 (`work.application@1`, `work.application-write-request@1`, `work.application-result@1`). Asking the person's
3001 OpenVibe.Actor agent about one is the person's own act and takes no capability. The work manifest lists it.
3002- `food.recipes.suggest` (owner food): recipe ideas from the caller's pantry through OpenVibe.AI's
3003 `food.suggest_recipes`, priced from Food's own food list (`food.recipe-suggest-request@1`,
3004 `food.recipe-suggestion@1`, `food.recipe-result@1`). The food manifest lists it.
3005
3006## 0.146.0 — 2026-10-12
3007
3008- `sources.source@1` and `sources.source-write-request@1`: an `api` endpoint may declare `where` (up to 10 path →
3009 value conditions, a value or a list of values; records that fail are left out before `max_items` counts). Paths may
3010 read the response from its root (`$root.<path>`, with a `{$key}` segment for the record's map key) and step into an
3011 object's single child (`*`), matching OpenVibe.Sources' adapter (Sources#39). This lets one AWS price list file give
3012 each instance bundle its own price.
3013
3014## 0.145.0 — 2026-10-11
3015
3016- `host.index_document.upserted` and `host.index_document.deleted` (owner host, active): the hosting catalog's plan and
3017 provider pages in OpenVibe.Search (types `plan`, `provider`; facets provider, kind, currency), sent through
3018 openvibe-publishing/search-feed. The host manifest produces them.
3019
3020## 0.144.0 — 2026-10-11
3021
3022- `sources.source@1` and `sources.source-write-request@1`: an `api` endpoint may declare `items_shape` (`array`, the
3023 default, or `map`: records keyed by id, the key readable as `$key`), matching OpenVibe.Sources' adapter (Sources#37).
3024
3025## 0.143.0 — 2026-10-11
3026
3027- `watch.watch@1` (and the watch write schemas that list actions): an action of kind `actor-agent` runs one of the watch
3028 owner's personal agents on OpenVibe.Actor (`actor.agent.run`) with the firing as its input after an optional note.
3029
3030## 0.142.0 — 2026-10-11
3031
3032- Games milestone M3 (scripted mods): `games.script.run` and the per-mod script bindings `games.players.read`,
3033 `games.player.message`, `games.world.emit` and `games.storage.kv` (active). A binding is absent from a script unless its
3034 install was granted it; grants travel in the def-set digest. Their schemas: `games.script-call@1`,
3035 `games.script-call-result@1`, `games.script-players@1`, `games.script-message@1`, `games.script-intent@1`,
3036 `games.script-storage-request@1` and `games.script-storage-result@1`.
3037- `games.mod.manage` adds `POST /api/v1/mods/:id/reload` (hot reload of a script mod, storage kept).
3038
3039## 0.141.0 — 2026-10-11
3040
3041- `run`: a `site` block with `tld: run` (openvibe.run serves its own front page since Run#28) and `exposure` live with
3042 its own public site, so the network's navigation, front door and share cards list it; the old
3043 `manifests/products/openvibe.run.json` placeholder entry is removed (the site block is the domain's one home).
3044- `host`: the `site` block describes the hosting catalog (openvibe.host is "hosting compared" since Host#69); OpenVibe's
3045 own static hosting is described as built and opening after review.
3046
3047## 0.140.0 — 2026-10-11
3048
3049- `actor.agent.manage` and `actor.agent.run` (active), with `actor.agent-manage-request@1`, `actor.agent-manage-result@1`
3050 and `actor.agent-run-request@1`: OpenVibe.Actor's personal agents under `/api/v1/me/agents` (standing instructions,
3051 a memory the person controls, a schedule; every run an ordinary task, `platform.task@1`). `/api/v1/agents` stays the
3052 public catalog of agent systems (`actor.agent.read`).
3053
3054## 0.139.0 — 2026-10-11
3055
3056- `host.catalog.manage` (active, staff only) with `host.catalog-manage-request@1` and `host.catalog-manage-result@1`:
3057 OpenVibe.Host's hosting catalog (plan T20 step 3), staff entries for providers (affiliate link and its exact
3058 disclosure), plans (source URL, currency, monthly price, the date it was confirmed) and promotions. The catalog's
3059 reads are public.
3060
3061## 0.138.0 — 2026-10-11
3062
3063- Sources category `hosting` (`sources.source@1`, `sources.item@1`, `sources.source-write-request@1` and the
3064 `sources.item.created|updated|removed` and `sources.fetch.failed` payloads): official provider APIs whose items are
3065 hosting plans, read by OpenVibe.Host's hosting catalog (plan T20 step 3).
3066
3067## 0.137.0 — 2026-10-11
3068
3069- `bot.robot-profile@1`: `mapping.driver` may be `looi`, the community's Generic LOOI driver (a Bluetooth bridge
3070 plugin for the OpenVibe Link; OpenVibe Link `docs/hardware-looi.md`). OpenVibe.Bot ships the matching `looi` profile.
3071- Service manifests name their PostgreSQL databases (no service declares SQLite any more).
3072
3073## 0.136.1 — 2026-10-10
3074
3075- `events.publish-result@1`: `cursor` is required unless the item says `pruned: true`. That answer is a repeat of an
3076 event_id whose stored copy retention already removed, so there is no position to return. Events has answered it this
3077 way since redaction and retention; `pruned` is now described. Fixtures: a pruned repeat (valid) and an item with
3078 neither (invalid).
3079
3080## 0.136.0 — 2026-10-10
3081
3082**No per-event sequence number on the consumer wire** (ADR-042 decision 7, its last step; plan T7). Positions became
3083opaque cursors in 0.132.0; the informational `seq` that stayed beside them goes now, with the "global order" promise.
3084Every client dedupes by `event_id` (openvibe-sdk 0.42.0 realtime, Shared 3.0.1), and no receiver reads `seq`
3085(checked across the estate).
3086
3087- `events.publish-result@1`: `{ event_id, cursor, duplicate }` (single and batch items); `seq` is gone and `cursor` is
3088 required.
3089- `events.read-result@1`: page items and single reads are `{ cursor, event }`. SSE messages carry `{ event }`.
3090- Unchanged: `gap` ranges (`from_seq`, `to_seq`; informational), and the operator delivery list and replay
3091 (`events.delivery-admin-*`), which still page by the hot store's position.
3092- Fixtures follow; ADR-042 records the step.
3093
3094## 0.135.0 — 2026-10-10
3095
3096- **Events, AI and Search get `site` blocks** (name, icon, tagline, what, legal profile, position 31-33). All three
3097 were already live public products with their own homes (openvibe.events, ai.openvibe.services,
3098 search.openvibe.network; `exposure` live/service), but without a site block the network's navigation and front door
3099 (Network's frame sites) never listed them. The copy is each product's own description; the icons already exist in
3100 openvibe-shared.
3101
3102## 0.134.0 — 2026-10-10
3103
3104- `community.resource.read` (owner `community`, first-party, **active**): OpenVibe.Community's resource index, so a
3105 person's pastes and spaces appear in OpenVibe.Services' merged index ("Your resources") beside their robots, rooms,
3106 streams, watches and Actor tasks. Kinds `community.paste` (id the slug, named by its title, state its visibility, owner
3107 its owner; deleted pastes left out) and `community.space` (id the slug, named by its name, state its visibility, owner
3108 its creator). Person-owned, so no project and no OVRN. Implemented by `GET /api/v1/resources` and
3109 `GET /api/v1/resources/:ovrn` (Community ships the index with its pin to this release). Services reads it once
3110 Network grants the `services` principal.
3111
3112## 0.133.0 — 2026-10-10
3113
3114**Actor task webhooks** (plan T17). Additive; OpenVibe.Actor implements them with its pin to this release.
3115
3116- **`actor.task-create-request@1`:** gains `webhooks` (1 to 8 items, each an https `url` and the `events` to deliver, which
3117 are the names of platform.task@1 `state`).
3118- **Signing:** Actor signs each task's deliveries with a secret it mints for that task. `platform.task@1` gains
3119 `webhook_secret` (`whsec_` and 43 characters), present only in the answer that created the task (and an idempotent
3120 repeat), never in a read or a list. It is erased once the task has ended and its deliveries are done.
3121- **New `actor.task-webhook@1`** (the delivery body): `{ type: "actor.task.state", delivery_id: "whd_…", state, task }`.
3122 - `delivery_id` is stable across retries.
3123 - `task` is platform.task@1 as it was then, without the secret.
3124 - Signed exactly like an Events delivery (`X-OpenVibe-Timestamp`, `X-OpenVibe-Signature-V2`), so receivers check
3125 it with openvibe-sdk/events `verifyDeliveryV2`.
3126 - 2xx is delivered; 410 or a URL the egress guard refuses ends it; anything else is retried for about a day.
3127- **Not accepted yet:** a project secret named by reference (`secret_ref`), since project secrets are not built. The
3128 request schema leaves it out, so naming one is a 422.
3129- `lib/ids.js` records `webhook_delivery: 'whd'`; the `actor.task.create` capability says what it now does.
3130- **Fixtures:** a request with webhooks; invalid ones for plain http and `secret_ref`; a delivery; invalid deliveries
3131 carrying the secret or with a bad delivery id.
3132
3133## 0.132.0 — 2026-10-10
3134
3135**An Events position is an opaque cursor and nothing else** (ADR-042 decision 7, plan T7). `events.read-result@1` and
3136`events.read-request@1` drop the numeric positions their own descriptions kept "only until every consumer reads by
3137cursor". Every consumer does now, checked across the estate: Community's relay (Community #56), the SDK's pull,
3138iterate, checkpoints and realtime (openvibe-sdk 0.42.0), Shared's bell and release watcher (3.0.1), Examples (#14)
3139and Chat's e2e test (#64). Services' project archive already read by cursor.
3140
3141- **Pages:** `GET /api/v1/events` answers `{ events: [{ seq, cursor, event }], next_cursor, latest_cursor, gap? }`.
3142 `next_after_seq` and `latest_seq` are gone, and `next_cursor`, `latest_cursor` and each item's `cursor` are required
3143 (Events always sent them). Without `after=`, a page starts at the oldest retained event; `after_seq` is refused.
3144- **Single event:** `GET /api/v1/events/:event_id` requires `cursor` beside `seq`.
3145- **Checkpoints:** `PUT` takes `{ topic, cursor, carrier? }` with `cursor` an opaque cursor string; a number is refused.
3146 `GET`/`PUT` answer `{ consumer, topic, cursor, carrier, updated_at }` with the cursor as stored (null when none is).
3147- **Realtime:** the SSE id is the cursor, and `Last-Event-ID` resumes only from a cursor.
3148- **Per-event `seq`:** stays, documented as informational (not a position). Deleting it, with `X-OpenVibe-Seq` and the
3149 global-order promise, is ADR-042's last step; clients already dedupe by `event_id`.
3150- **Fixtures:** pages and checkpoints with cursors only, plus three invalid ones (a numeric page, a numeric checkpoint
3151 answer, a numeric checkpoint request). ADR-042 records what decision 7 became.
3152
3153## 0.131.0 — 2026-10-10
3154
3155- `openre.resource.read` (owner `openre`, first-party, **active**): OpenRestream's resource index, its stream
3156 definitions as kind `openre.stream`, id `std_<ULID>`, named by the title, owner the stream's owner. Archived
3157 definitions are left out. Person-owned, so no OVRN. Implemented by `GET /api/v1/resources` and
3158 `GET /api/v1/resources/:ovrn` (OpenRestream ships the index with its pin to this release). OpenVibe.Services reads it
3159 once Network grants the `services` principal.
3160- `lib/ids.js` records `stream: 'std'`.
3161- Games characters stay out for now: their rows carry no creation time, which a resource summary requires.
3162
3163## 0.130.0 — 2026-10-10
3164
3165**Four more authorities serve their resource index.** Status changes only; no schema changed.
3166- `watch.resource.read`, `actor.resource.read`, `bot.resource.read`, `chat.resource.read`: active, implemented by
3167 `GET /api/v1/resources` and `GET /api/v1/resources/:ovrn` (Watch #28, Actor #22, Bot #68, Chat #57, all deployed).
3168 OpenVibe.Services adds every active `<id>.resource.read` to its authority registry on boot, so a Services on 0.130.0
3169 merges watches, Actor tasks, robots and rooms beside Network's, Media's, Events' and Host's resources.
3170
3171## 0.129.0 — 2026-10-10
3172
3173**The resource index's next authorities** (ADR-048, plan T13 step 8 phase 2, the Contracts half). Four planned,
3174first-party capabilities, one for each service whose resources belong in OpenVibe.Services' merged index, each naming
3175the kind its index will carry. Additive and inert: four capability manifests, four service capability lists extended
3176and one id prefix recorded. No schema changed, no route named and nothing activated; Services only reads an authority
3177once its capability is active.
3178
3179- `watch.resource.read` (owner `watch`): watches, kind `watch.watch`, `wch_<ULID>`. One made under a project carries
3180 that project and so an OVRN; a person's own watch has neither.
3181- `actor.resource.read` (owner `actor`): tasks, kind `actor.task`, `tsk_<ULID>`, with the project the task was asked
3182 under, when there was one.
3183- `bot.resource.read` (owner `bot`): robots, kind `bot.robot`, `rob_<ULID>`, owner the robot's owner. Person-owned
3184 (Bot holds no projects), so no OVRN, like Network's user-owned node principals.
3185- `chat.resource.read` (owner `chat`): rooms, kind `chat.room`, id the room's slug, owner its owner. Person-owned, so
3186 no OVRN.
3187- **Left out, again:** OpenVibe.Space (its `spaces` table is the forum copy that moved back to Community on
3188 2026-10-08; code hosting and spaces are still to be built). Also Run jobs and Tools jobs: a `job_<ULID>` is what
3189 `common.resource-name@1` refuses. OpenRestream streams and Games characters wait for their own survey.
3190- `lib/ids.js` records `robot: 'rob'`.
3191
3192## 0.128.2 — 2026-10-10
3193
3194- `events.read-result@1` documents `latest_cursor` (OpenVibe.Events#45), the head of a pull as an opaque cursor, and
3195 says to keep `next_cursor` and read on with `after=`. The numeric `after_seq`, `next_after_seq` and `latest_seq`
3196 remain only until every consumer reads by cursor (plan T7; Community, Services and the Examples have moved).
3197 Additive.
3198
3199## 0.128.1 — 2026-10-10
3200
3201- **Descriptions only.** `inventory.index_document.*` name Inventory's real item page, `/items/<id>` on
3202 inventory.openvibe.network, not `/definitions/<id>` (that path is the JSON API). The fixtures carry the real URL.
3203- The `run` manifest's exposure note now says what is there: Run places jobs on people's own Bot nodes, and
3204 openvibe.run is parked (a 302 to openvibe.network) rather than an OpenVibe.Sites placeholder.
3205
3206## 0.128.0 — 2026-10-10
3207
3208- **Record products send their pages to OpenVibe.Search.** `<owner>.index_document.upserted` and `.deleted` (v1) are
3209 declared for Work (`job`, `/jobs/<id>`), Rent (`listing`, `/listings/<id>`), Help (`article`,
3210 `/a/<domain>/<slug>`, id `<domain>:<slug>`), Inventory (`definition`, `/definitions/<id>`) and Quest (`quest`,
3211 `/quests/<id>`), and each service manifest now produces them. The payloads are `search.index-document@1` with the
3212 owner, type and id pattern fixed, plus the usual tombstone. Each product sends them through
3213 `openvibe-publishing/search-feed` (1.4.0): on the write's transaction, and from a sweep that re-sends only what
3214 changed. Search consumes them as `*.index_document.*` once the owners are in `SEARCH_EVENT_OWNERS`.
3215
3216## 0.127.0 — 2026-10-10
3217
3218- **Retired addresses leave the registry.** `ai.openvibe.network` and `events.openvibe.network` are no longer domains
3219 of the `ai` and `events` services or of their repositories; their last service callers stopped on 2026-10-02 and
3220 2026-09-30, and only crawlers reached them since. The `ai.openvibe.network` "moved" product manifest is deleted, and
3221 descriptions now name only `ai.openvibe.services` and `openvibe.events`. The AI repository manifest no longer lists a
3222 domain the network does not hold. The AI service manifest no longer describes a SQLite database (AI runs on
3223 PostgreSQL, ov_ai).
3224- **`lib/service-auth.js`:** `requireCapability` drops the `legacy` option (the X-Internal-Key compatibility hook, plan
3225 T2). Only a Bearer service token opens a route; no consumer passed it any more.
3226
3227## 0.126.0 — 2026-10-09
3228
3229- **OpenVibe Live on by default for OpenRestream.** New capability `live.openre.slot.bind` (active, internal):
3230 `POST /internal/openre/slots` on OpenVibe.Live with `live.openre-slot-bind-request@1` →
3231 `live.openre-slot-bind-result@1`. OpenRestream asks Live for a slot on the person's channel bound to one
3232 OpenRestream stream, ingested by OpenRestream, so the stream's sessions show live on openvibe.live/@username through
3233 Live's mirror. It is idempotent per stream; 409 `live.no_account` when the person has no Live account yet. Additive.
3234- `manifests/services/openre.json`: OpenRestream's site copy says what it is: an open restreaming platform (one stream
3235 to every platform at once, OpenVibe Live on by default, free and open source).
3236
3237## 0.125.1 — 2026-10-09
3238
3239- The product at openre.stream is **OpenRestream** (owner, 2026-10-09): an open restreaming platform. Every name
3240 people read says so: `manifests/services/openre.json` (`name`, `site.name`, copy), the repository manifest (now
3241 `manifests/repositories/OpenRestream.json`, repository `OpenVibers/OpenRestream`, renamed on GitHub the same day),
3242 docs and schema descriptions. Ids are unchanged: service `openre`, `openre.*` capabilities and events.
3243
3244## 0.125.0 — 2026-10-09
3245
3246- OpenVibe.News, OpenVibe.Reviews, OpenVibe.Trade, OpenVibe.Coupons and OpenRe.Stream are live: each serves its own
3247 domain (`exposure.state: live`, `publicSite: service`) after an independent pre-launch security review and its
3248 fixes (News#21, Reviews#22, Trade#24, Coupons#22, OpenRe.Stream#25). They replace OpenVibe.Sites placeholder pages
3249 (plan T11: Sites is deleted).
3250- admin., api., auth. and themes.openvibe.network describe what they are now: redirects to the openvibe.network page
3251 that does their job (Network#107). `manifests/services/sites.json` says what Sites still serves.
3252
3253## 0.124.0 — 2026-10-09
3254
3255- ADR-054 §6 amendment, **the Workshop v1**: Workshop kinds (any person may submit a definition, issued by and
3256 credited to them, published only after staff review); the first is `network.badge` (a small reviewed image before a
3257 person's name, renderer `network.badge.image@1`). Review, free giving within a cap and a daily limit, submission
3258 limits and takedown are all specified there.
3259- `inventory/kind@1` gains `workshop`; an `inventory/equipped@1` slot gains `media_id` (the art image, so a renderer
3260 needs no second read).
3261- New `inventory/review-request@1` (publish, optionally with a rarity, or reject with a reason, with fixtures).
3262 `inventory.definition.review` is active: `POST /api/v1/definitions/:id/review`, staff only. Additive.
3263
3264## 0.123.0 — 2026-10-09
3265
3266- ADR-054 amendment, §3 "Grantors": `inventory/definition@1` and `inventory/definition-request@1` gain an optional
3267 `grantors` list (services or apps, at most 8). They may grant that one item (only grant: origin earned or granted,
3268 idempotent, within the cap, recorded with the grantor as actor), so an item can be earned on one site while another
3269 stays its issuer. This is how OpenVibe.Quest gives some of Live's hats as quest rewards. Additive.
3270
3271## 0.122.1 — 2026-10-09
3272
3273- `manifests/services/inventory.json`: the site's icon is `inventory`. A site's id is its icon (Network's Frame builds
3274 the site list from it), and `games` collided with OpenVibe.Games.
3275
3276## 0.122.0 — 2026-10-09
3277
3278**OpenVibe.Inventory goes live (ADR-054, plan T21 step 2).**
3279- `manifests/services/inventory.json`:
3280 - status alpha, exposure `live` with `publicSite: service`, at site position 30 (Inventory);
3281 - its lifecycle, health, ready and internal origin (127.0.0.1:5030);
3282 - it consumes the two account events and owns `inventory.*`.
3283- Six capabilities are active, each naming its routes: `inventory.item.read`, `inventory.item.list`,
3284 `inventory.equip.manage`, `inventory.item.grant`, `inventory.item.consume` and `inventory.definition.manage`.
3285 `inventory.definition.review` stays planned until creator submissions open.
3286
3287## 0.121.0 — 2026-10-09
3288
3289**The OpenVibe inventory, decided (ADR-054, plan T21 step 1).** A new authority, OpenVibe.Inventory, will own items
3290across the network: kinds, definitions, instances, the equipped set and an append-only ledger.
3291- `docs/adr/ADR-054-inventory-authority.md` (accepted):
3292 - service `inventory`, `ov_inventory`, loopback 5030, `inventory.openvibe.network`;
3293 - issuers grant within their namespace;
3294 - nothing is sold, bought, traded or converted until a later money ADR (ADR-012, ADR-025);
3295 - Live's cosmetics become the first kinds, migrated convert-verify-delete.
3296- `manifests/services/inventory.json` (placeholder), with seven planned capabilities: `inventory.item.read`,
3297 `inventory.item.list`, `inventory.equip.manage`, `inventory.item.grant`, `inventory.item.consume`,
3298 `inventory.definition.manage` and `inventory.definition.review`.
3299- Schemas, with fixtures: `inventory.kind@1`, `inventory.definition@1`, `inventory.instance@1`,
3300 `inventory.inventory@1`, `inventory.equipped@1`, `inventory.equipped-batch@1`, `inventory.grant-request@1`,
3301 `inventory.equip-request@1` and `inventory.definition-request@1`.
3302- Events: `inventory.item.granted`, `inventory.item.consumed`, `inventory.item.revoked`, `inventory.item.equipped`,
3303 `inventory.item.unequipped` and `inventory.definition.published`.
3304
3305## 0.120.0 — 2026-10-09
3306
3307**Account export and deletion everywhere a person has rows.** Nine more services declare the two account events.
3308- `deals`, `trade`, `tips`, `vip`, `watch`, `services`, `wiki`, `blog` and `bot` consume
3309 network.account.export_requested and network.account.deleted (openvibe-sdk/account-data, SDK 0.37.0). Their startup
3310 recovery names the redelivery. Codes holds no personal rows since its console moved to Services, so it declares none.
3311
3312## 0.119.0 — 2026-10-08
3313
3314**OpenVibe.MediaHub goes live: openvibe.download as a private drive.** Account export and deletion are declared for the
3315six services that answer them.
3316- `manifests/services/media-hub.json`: status alpha, exposure `live` with `publicSite: service`, its lifecycle, health,
3317 ready and internal origin (127.0.0.1:4990). It consumes the two account events. openvibe.pics and openvibe.video
3318 answer with coming pages, and the video.*, pics.* and download.* capabilities stay planned.
3319- `food`, `help`, `work`, `quest`, `rent` and `actor` consume network.account.export_requested and
3320 network.account.deleted (openvibe-sdk/account-data, SDK 0.36.0), and their startup recovery names the redelivery.
3321
3322## 0.118.0 — 2026-10-08
3323
3324**The forum returns to OpenVibe.Community** (owner decision 2026-10-08: Space becomes code hosting and "spaces";
3325the vBulletin/phpBB-style forum lives on openvibe.community again, plan T20). The mirror of 0.110.0, which moved it
3326the other way.
3327- `manifests/services/community.json`: the forum is Community's again — `community.space.read`,
3328 `community.space.manage`, `community.thread.read` and `community.post.create` are back in its capability list,
3329 `community.thread.created` and `community.post.created` back in its `eventsProduced`, and its notes, its Discord
3330 relay drain and its Roadmap-space recovery describe the forum it serves.
3331- Those four capabilities are active again with Community's routes (`GET /s`, `GET /s/:space`,
3332 `GET /s/:space/t/:slug`, `GET /s/feed.xml`, `GET /api/v1/spaces/:space/threads`, `POST /api/v1/spaces/:space/threads`,
3333 `PUT /api/v1/spaces/:space/members-only`, …). `community.vote.set` names its thread and comment vote routes again,
3334 guarded by `community.post.create` and `community.comment.write`; `community.space.manage` is the one active grant
3335 without schemas, so `compatibility/capability-schema-gaps.json` lists it where `space.forum.manage` used to be.
3336- The seven `community.*` forum schemas and the two event payloads are active again with their fixtures. The `space.*`
3337 ones (`space.forum-space/thread/post`, `space.forum-read-result`, `space.thread-read-result`,
3338 `space.post-write-request/result`, `space.thread.created`, `space.post.created`, `space.moderation.action`) are
3339 retired and kept loadable, and `compatibility/deprecations.json` names each Community replacement with a window
3340 through 1.0.0. The Community records those replacements had are gone.
3341- `manifests/services/space.json`: no forum capability or event, and the site block and notes say Space is code
3342 hosting, with "spaces" (apps that use your OpenVibe account and the SDK) coming next, and that its former `/s/*`
3343 paths redirect permanently to openvibe.community. Exposure stays live (Space serves a home); its lifecycle drops
3344 the forum's work (Discord relay, Roadmap resync, events outbox) and keeps what runs.
3345- `manifests/services/quest.json` counts `community.thread.created` and `community.post.created` again;
3346 `manifests/services/network.json` consumes `community.moderation.action` and no longer `space.moderation.action`.
3347- Space ends with no active capability, so `generated/openapi/space.json` is gone.
3348- Generated bundles, types and OpenAPI documents are refreshed for 0.118.0.
3349- `manifests/services/space.json` consumes no events: Space's account export and deletion hooks only ever touched the
3350 forum tables (the forum's account data is Community's), so Network stops waiting for Space's part.
3351- `manifests/services/deals.json`: exposure `live` with `publicSite: service` — OpenVibe.Deals serves openvibe.deals
3352 (472 DealNews offers with their links kept verbatim and attributed, community votes and watches).
3353- Product copy for the services that launched this week: OpenVibe.Food, Help, Work, Quest, Rent and Watch describe
3354 what is live now and what comes next, and each gets the common questions OpenVibe.Help shows.
3355
3356## 0.117.0 — 2026-10-08
3357
3358**OpenVibe.Quest and OpenVibe.Rent become services; OpenVibe.Watch goes live with its public site** (plan T18 step 8,
3359T19).
3360- `manifests/services/quest.json` (port 4980, `openvibe.quest` live, site position 27): the shared quest log, counted
3361 from the domain event types it consumes through OpenVibe.Events; badges, and OpenCoins through Network when switched
3362 on. No capabilities: a quest log is a person's own.
3363- `manifests/services/rent.json` (port 5010, `openvibe.rent` live, position 28): listings people post, safety rules,
3364 reports and a staff queue. No capabilities yet.
3365- `manifests/services/watch.json` 0.2.0: exposure `live` with `publicSite: service` (sign-in and watch management on
3366 openvibe.watch), its real lifecycle (25 s shutdown, schedule and outbox recovery), health, ready, internal origin and
3367 site block (position 29).
3368- The three product manifests point at their services.
3369
3370## 0.116.0 — 2026-10-08
3371
3372**OpenVibe.Food, OpenVibe.Help and OpenVibe.Work become services** (plan T19 "flesh the network out"; owner 2026-10-08).
3373- `manifests/services/food.json` (port 4970, `openvibe.food` live, site position 24): food banks and budget grocers
3374 near you from OpenStreetMap (ODbL attribution on every answer), the budget food list, meal plans and a pantry.
3375- `manifests/services/help.json` (port 5020, `openvibe.help` live, position 25): the network's help centre built from
3376 this repository's catalog, and support tickets. No capabilities: a ticket is a person's own.
3377- `manifests/services/work.json` (port 4960, `openvibe.work` live, position 26): job listings from open job boards with
3378 their provenance (excerpt only, original linked), search and saved searches. No capabilities yet.
3379- Capabilities (audience `openvibe.food`): `food.plan.write` (sensitive), `food.plan.read`, `food.pantry.write`
3380 (sensitive), `food.pantry.read`; the place search and the food list are public reads with no capability.
3381- Schemas: `food.plan-create-request@1`, `food.plan@1`, `food.plan-result@1`, `food.pantry-request@1`,
3382 `food.pantry-result@1`.
3383- The three product manifests point at their services.
3384
3385## 0.115.0 — 2026-10-08
3386
3387**OpenVibe.Actor becomes a service** (plan T17, ADR-044; owner direction 2026-10-08: Actor is OpenVibe's own general agent
3388and the router for agent work, "like OpenRouter but for agents").
3389- `manifests/services/actor.json`: `actor`, port 4950, `openvibe.actor` live with `publicSite: service`; site block
3390 "Actor · Your agent for everything" (position 23). The product manifest now points at the service.
3391- Capabilities (audience `openvibe.actor`): `actor.task.create` (POST /api/v1/tasks, cancel; sensitive),
3392 `actor.task.read` (a task and its live stream), `actor.task.list`, and the public `actor.agent.read` (the agent
3393 catalog with rate cards, and a dry-run route that explains which agent a task would go to).
3394- Schemas: `actor.task-create-request@1`, `actor.task-event@1` (the SSE stream: state, output, end, resumable by
3395 seq), `actor.task-list-result@1`, `actor.agent-list-result@1` (kind, trust, what it can do, rate card, availability).
3396- `platform.task@1` is active and Actor implements it. Additive: `project_id` is optional (a person's own task has
3397 none), and a new optional `error` { code, detail } says why a task failed.
3398
3399## 0.114.0 — 2026-10-08
3400
3401**Developer links point at OpenVibe.Services.** Manifest text only; no schema, capability or event changed. The
3402developer console moved from openvibe.codes to openvibe.services in 0.113.0, so these links follow:
3403- the Host site's "Build on OpenVibe" link;
3404- the "meanwhile" links of openvibe.website, api.openvibe.network, openvibe.events (to the Events API reference) and
3405 openvibe.actor;
3406- the "build on it" cards of openvibe.bot and openvibe.actor.
3407
3408openvibe.codes now answers those paths with permanent redirects.
3409
3410## 0.113.0 — 2026-10-08
3411
3412**The developer portal moves from OpenVibe.Codes to OpenVibe.Services; Codes becomes the open coding-agent harness**
3413(owner decision 2026-10-08; plan T13 and T16 notes). Codes' portal data in production is empty, so the names move at once.
3414- New in Services' namespace: `services.release.read` and `services.release.manage` (audience `openvibe.services`), the
3415 schemas `services.app-manifest@1`, `services.release@1`, `services.release-read-result@1`,
3416 `services.release-manage-request@1`, `services.release-manage-result@1`, the event payload `services.moderation.action@1`
3417 and the events `services.app.published|deprecated|revoked`. They are the `codes.*` ones under the new owner and audience.
3418- Retired, kept loadable: `codes.release.read`, `codes.release.manage`, `codes.resource.read` and the six `codes.*` schemas
3419 (`compatibility/deprecations.json` names each replacement). Network consumes `services.moderation.action`.
3420- `manifests/services/services.json`: live with `publicSite: service`; it owns manifests, releases, trust tiers and
3421 playground logs (kinds `services.manifest` `mfs_`, `services.release` `rel_`) besides the merged index; its site
3422 block is the developer platform's. `manifests/products/openvibe.services.json` describes the console and docs.
3423- `manifests/services/codes.json`: no capability or event; the site block describes the harness (position 22).
3424
3425## 0.112.0 — 2026-10-07
3426
3427**Robots driven through the relay plugin.** `bot.robot-profile@1` is 1.1.0: `mapping.driver` gains `relay`, the
3428OpenVibe Link plugin that forwards `button` and `point` commands to an owner's own script in OpenVibe.Live's
3429hardware-client messages (OpenVibe Link #33; plan T15 R9 steps 4-5). Bot's catalogue profile `relay.generic` uses it
3430for the robots converted from Live's stream controls. Additive: every existing profile stays valid.
3431
3432## 0.111.0 — 2026-10-07
3433
3434**Events' public origin is openvibe.events** (plan T7, ADR-042 item 10). Manifest and example changes only; no schema changed.
3435- `manifests/services/events.json`: `publicOrigin` `https://openvibe.events`; `domains` lists `openvibe.events` first and
3436 keeps `events.openvibe.network`, which Events still answers until every client has moved (then it answers 308).
3437 `manifests/repositories/OpenVibe.Events.json` lists the same two names.
3438- `network.realtime-ticket-result@1`: the `stream_url` description and fixtures use
3439 `https://openvibe.events/realtime/stream`. The ticket's audience was already `openvibe.events`.
3440- Product manifests: openvibe.events's launch line names the API and realtime stream there; the realtime notice links
3441 to `https://openvibe.events/`.
3442
3443## 0.110.0 — 2026-10-07
3444
3445**OpenVibe.Space and OpenVibe.AI's public home launch** (plan T10 step 3, T6). It serves the forum at `https://openvibe.space` from
3446loopback :4940. Community keeps pastes, comments, Pulse and submissions; its former `/s/*` forum paths
3447redirect permanently to Space.
3448- `manifests/services/space.json`: `status` alpha, `exposure` live with `publicSite: service`,
3449 health and readiness paths, lifecycle, and the events Space produces and consumes.
3450- `space.forum.read`, `space.forum.manage`, `space.thread.read`, and `space.post.write` are active with
3451 Space's implemented routes. `space.post.write` still guards thread creation; `space.thread.write`
3452 remains planned as a separate grant. `space.pulse.read` remains planned because Space serves no Pulse.
3453- `space.thread.created`, `space.post.created`, and `space.moderation.action` have payload contracts and
3454 valid and invalid fixtures. Space's source is `space`; `space.moderation.action` is
3455 `common.moderation-action@1` (ADR-022) and OpenVibe.Network consumes it into the moderation audit log.
3456- Space's problem codes, including `403 space.blocked`, are documented in
3457 `docs/space-problem-codes.md`; the problem fixture demonstrates the stable URI and code.
3458- The four former Community forum capabilities are retired and removed from its service list. The seven
3459 Community forum schemas remain loadable but retired, with Space replacements and a compatibility
3460 window through 1.0.0. Historical `community.thread.created` and `community.post.created` payloads
3461 also remain loadable as retired types; Community no longer claims to produce them. Community's
3462 planned vote grant now describes its surviving comment route only.
3463- `manifests/services/ai.json`: `exposure` live with `publicSite: service`; `publicOrigin` is
3464 `https://ai.openvibe.services` (the home, `/stats` and the developer-app API, AI #23), and
3465 `ai.openvibe.network`, still listed in `domains`, answers 301 to it.
3466- Generated bundles, types, and OpenAPI documents are refreshed for 0.110.0.
3467
3468## 0.109.0 — 2026-10-07
3469
3470**OpenVibe.Run runs, OpenVibe.Services registers, and Bot learns buttons and points.** Two schemas gained optional
3471shape, Run's job API turned active, and Services registered its first capability and AI its first public one; everything here is
3472additive, so every existing fixture and profile stays valid.
3473- `manifests/services/run.json`: `status` alpha; `exposure` internal (deployed on loopback :4920 on 2026-10-07,
3474 Run #1 and #2); openvibe.run keeps its OpenVibe.Sites placeholder until Run has a product surface.
3475- `run.job.submit`, `run.job.read`, `run.job.list`, `run.job.cancel`, `run.job.stream`, `run.job.admin`: active,
3476 with the routes Run serves (`POST /api/v1/jobs`, `GET /api/v1/jobs`, `GET /api/v1/jobs/:id`,
3477 `POST /api/v1/jobs/:id/cancel`, `POST /api/v1/jobs/:id/stream/ticket` and `GET /api/v1/jobs/:id/stream`,
3478 `GET /api/v1/admin/jobs`).
3479- `manifests/services/services.json`: `status` alpha; `exposure` internal (deployed on loopback :4930 on 2026-10-07);
3480 openvibe.services keeps its placeholder. `services.resource.read` (owner `services`, first-party, active) is
3481 Services' merged resource index over every authority that serves one (ADR-048), readable by a first-party service
3482 token holding the capability or by a person's user token scoped to one project they own or belong to.
3483- `common.resource-list-result@1` is 1.1.0: an optional `partial`, the authorities a merged index could not read for
3484 this page (`{ service, code }`). A slow or failing authority is omitted, never fails the page (ADR-048).
3485- `bot.command@1` gains the kinds `button` (`name`, and an optional `state` `down|up` for a hold button) and `point`
3486 (`x`, `y` in `[0, 1]`). `bot.robot-profile@1` gains `commands.button` (`names`: `label`, optional `key`,
3487 `cooldown_ms` and `hold`) and `commands.point` (optional `cooldown_ms`), the widget types `buttons` and
3488 `video_click` (the widget type pattern now admits `_`), and `button`/`point` as widget command kinds (plan T15 R9).
3489- `ai.app.run` (owner `ai`, public, active; OpenVibe.AI #22): the AI operations as a developer app (ADR-014, plan
3490 T6) — `POST /api/v1/chat`, `/generate`, `/summarize`, `/classify`, `/extract`, `/embed` and `GET /api/v1/runs/:id`
3491 for the app's own runs. Every run is metered to the app's project; metered capacity is spent only under the
3492 project's tier budget, and a sandbox run (or one no tier budget governs) uses only free and local capacity.
3493- `generated/` gains `openapi/run.json` and `openapi/services.json` (their first active capabilities) and stamps
3494 every document with the release version.
3495
3496## 0.108.0 — 2026-10-07
3497
3498**OpenVibe.Watch runs, and four authorities serve their resource index.** Status changes only; no schema changed.
3499- `manifests/services/watch.json`: `status` alpha; `exposure` internal (deployed on loopback :4730 on 2026-10-07, Watch #1);
3500 openvibe.watch keeps its OpenVibe.Sites placeholder until Watch has a product surface.
3501- `watch.watch.read`, `watch.watch.manage`, `watch.observation.read`, `watch.check.run`: active, with the routes Watch
3502 serves (`/api/v1/watches`, `/:id`, pause/resume, `/:id/check`, `/:id/observations`, `/:id/checks`).
3503- `host.resource.read`, `events.resource.read`, `codes.resource.read`, `media.resource.read`: active, implemented by
3504 `GET /api/v1/resources` and `GET /api/v1/resources/:ovrn` (Host #28, Events #17, Codes #20, Media #47, all deployed).
3505
3506## 0.107.0 — 2026-10-07
3507
3508**OpenVibe.Host is live at openvibe.host** (Stage B launched 2026-10-07; Host#26, Sites#11): `manifests/services/host.json` `exposure` becomes `{ state: live, publicSite: service }`, so Network lists Host as an open site.
3509
3510**The resource index's first authorities** (ADR-048, plan T13 step 8, the Contracts half). OpenVibe.Network has served
3511`GET /api/v1/resources` since 0.104.0; this adds the planned, first-party capability each surveyed authority needs to
3512serve its own — `media.resource.read`, `events.resource.read`, `host.resource.read` and `codes.resource.read` — and
3513names in each the kinds that authority's index will carry. Additive and inert: four new capability manifests, four
3514service capability lists extended, six id prefixes recorded in `lib/ids.js`; no schema changed, no route named, nothing
3515activated.
3516
3517- `media.resource.read` (owner `media`, first-party, **planned**, no routes): Media's index carries its objects, kind
3518 `media.object` with a `med_<ULID>` id — the canonical blobs its v1 vods, clips and files are projections of
3519 (`media_objects`, migrations/0001_initial.sql). Vods and clips are projections over objects (bigint ids) and are
3520 never listed. An object in a developer-project tenant carries that project; an object in a first-party app tenant
3521 (`live`, `games`, …) has no project and so no OVRN.
3522- `events.resource.read` (owner `events`, first-party, **planned**, no routes): Events' index carries its
3523 subscriptions, kind `events.subscription` with a `sub_<ULID>` id (`server/api/subscriptions.js`), project-scoped
3524 when a developer app created them and project-less when a service did. Events themselves (`evt_`) are what
3525 `common.resource-name@1` refuses by design, and a project's queue stays out of the index until Events stores a queue
3526 row.
3527- `host.resource.read` (owner `host`, first-party, **planned**, no routes): Host's index carries its static sites
3528 (kind `host.site`, `sit_<ULID>`), the immutable deploys of those sites (kind `host.deploy`, `dpl_<ULID>`) and their
3529 default and custom domains (kind `host.domain`, `dom_<ULID>`), each with its `project_id`. Host renamed its site id
3530 prefix from `site_` (four letters) to `sit_` (three) — zero sites exist in production, so nothing converts — so
3531 `host.site` now composes an OVRN. Host lists no projects: only Network lists projects.
3532- `codes.resource.read` (owner `codes`, first-party, **planned**, no routes): Codes' index carries its validated app
3533 and mod manifests (`codes.manifest`, `mfs_<ULID>`) and its releases (`codes.release`, `rel_<ULID>`), each created
3534 in a Network project. Trust tiers are per-app metadata and playground run logs are audit records, neither a
3535 resource; Codes hosts no repositories, so the ADR-048 catalog's `codes.repo` is gone.
3536- **Step 8 phase 2 — the person-owned resources** (Bot robots and devices, Chat rooms, Community spaces,
3537 OpenRe.Stream streams and Games characters): served like Network's user-owned node principals, no OVRN and
3538 owner = user, in a later phase, so no `*.resource.read` capability yet.
3539- **Surveyed and left out** (not even a person-owned resource, so no `*.resource.read` capability): AI (runs and the
3540 record groups are keyed to requester principals and attribution subjects, never a project) and Tools (a `job_<ULID>`
3541 is exactly what `common.resource-name@1` refuses, and a job expires unless referenced).
3542- **`lib/ids.js` records the chosen prefixes** (`subscription: sub`, `deploy: dpl`, `domain: dom`, `manifest: mfs`,
3543 `release: rel`, `site: sit`); `lib/resources.js` still formats any `<service>.<type>` kind generically, so `nameOf`
3544 needs no new entry, and `common.resource-name@1` is unchanged. `generated/` gains nothing but the release's version
3545 stamp — only active capabilities with routes are emitted, and these are planned with none.
3546
3547## 0.106.0 — 2026-10-07
3548
3549**OpenVibe.Bot is a site** (Bot #34). Bot has served openvibe.bot since 2026-10-02 (`exposure` live, `publicSite`
3550service) and, since Bot #34, its own front page; without a `site` block the network navigation and the
3551openvibe.network home did not list it. Additive: one `site` block, no schema changed.
3552- `manifests/services/bot.json` `site`: name `Bot`, icon `bot`, tagline "An open control panel for robots", the
3553 front page's one-line description, legal profile `games` (accounts and per-account state: robots, devices and
3554 the 30-day command audit), position 21 (after the current entries). The icon id `bot` falls back to the OV
3555 mark until openvibe-shared draws a `bot` glyph. `manifests/products/openvibe.bot.json` stays the catalog entry
3556 (the block carries no `tld`).
3557
3558## 0.105.0 — 2026-10-05
3559
3560**Chat's ticket conversation and DM block-state reads are live** (Chat #26 and #27). `chat.ticket.write` is active
3561and `chat.messages.read` gains Chat's DM block-state route. Additive: one new chat result contract, one capability
3562activated with the routes it names, one route list extended; no existing schema changed.
3563- `chat.ticket.write` (owner `chat`, first-party, **active**): OpenVibe.Chat serves the per-ticket conversation it
3564 names (`server/chat/internal-tickets.js`) — `POST /internal/chat/tickets/:ticket_id/messages` creates the
3565 (ticket id, calling service) conversation on first use and appends one message, and
3566 `GET /internal/chat/tickets/:ticket_id` reads that service's own conversation, paged; both guarded by the
3567 capability, so an app, node or agent token is refused.
3568- `chat.dm-block-state-result@1` (new, owner `chat`, first-party): the answer of
3569 `GET /internal/chat/dm/block-state?a&b` — `{ blocked }`, true when either user blocked the other, in Chat's
3570 `dm_blocks` or as a Network platform block — added to `chat.messages.read`'s route list. It follows the other
3571 `chat.*` internal-read schemas: an `anyOf` of the ok shape and `chat.ingress-ack@1`'s error, with valid and
3572 invalid fixtures.
3573- `chat.ticket-conversation@1` moves from planned to active in the catalog. `generated/openapi/chat.json` gains both
3574 ticket operations (the generator emits an active capability's `implementedBy` routes), and the generated docs move
3575 to 0.105.0.
3576
3577## 0.104.0 — 2026-10-05
3578
3579**Network's resource index is live** (Network PR #62; ADR-048). `network.resource.read` is active: OpenVibe.Network
3580serves the index it names. No schema changed and no route list changed — the two routes the capability already
3581listed are now implemented and guarded.
3582- `network.resource.read` (owner `network`, first-party, **active**): `GET /api/v1/resources` answers a page of
3583 `common.resource-list-result@1` and `GET /api/v1/resources/:ovrn` answers `common.resource-summary@1`, both
3584 guarded by the capability. Network's own resources today are its developer projects, apps, keys and nodes.
3585- `generated/openapi/network.json` gains both operations, since the generator emits an active capability's
3586 `implementedBy` routes; the OpenAPI version line and the other generated docs move to 0.104.0.
3587- The T2 Fabric offer registry's public routes, which shared `/api/v1/resources`, have moved to `/api/v1/offers` in
3588 the same Network release; no Contracts manifest listed those public routes, so no route list changed here.
3589
3590## 0.103.0 — 2026-10-05
3591
3592**Chat's three new internal reads and Network's resource index** (Chat PR #24; ADR-048). Additive: three new chat result
3593contracts and one planned capability, two capability route lists extended, no existing schema broken.
3594- `chat.site-daily-result@1` (new, owner `chat`, first-party): the answer of `POST /internal/chat/stats` with
3595 `kind: "site-daily"` — `{ days: [{ day, messages, chatters }] }`, one UTC day per entry in `[since, until)`,
3596 zero-filled, at most 400 — Live's home series. `chat.stats-request@1` gained `site-daily` in its kind `enum`, with
3597 the per-kind `allOf` rule that both `since` and `until` are required, the way its `user` and `stream` kinds already
3598 express their required field.
3599- `chat.first-chat-result@1` (`{ first }`, Live's welcome check) and `chat.sound-result@1` (`{ sound }`, reusing
3600 `chat.sounds-result@1`'s sound projection) are the answers of the other two reads. All three follow the other
3601 `chat.*` internal-read schemas: an `anyOf` of the ok shape and `chat.ingress-ack@1`'s error, with valid and
3602 invalid fixtures.
3603- Capabilities: `GET /internal/chat/first-chat` joins `chat.analysis.read`'s routes and
3604 `GET /internal/chat/sounds/by-command` joins `chat.sounds.read`'s.
3605- `network.resource.read` (new, owner `network`, first-party, **planned**): OpenVibe.Network's resource index
3606 (ADR-048 section 3) — `GET /api/v1/resources` answers `common.resource-list-result@1` and
3607 `GET /api/v1/resources/:ovrn` answers `common.resource-summary@1`; listed in `manifests/services/network.json`.
3608 The T2 Fabric offer registry's public routes, today sharing `/api/v1/resources`, move to `/api/v1/offers` in
3609 Network's own release; no Contracts manifest listed those public routes, so no route list changed here.
3610
3611## 0.102.0 — 2026-10-05
3612
3613**The Watch contracts** (plan T18). Additive: eight new planned contracts, four planned capabilities and the Watch placeholder manifest, no existing schema changed.
3614- `watch.watch@1` (new, owner `watch`, first-party, **planned**): a user-defined persistent observation — a source (a push event, a
3615 webhook, a conditional HTTP URL, a feed or API, a local Node probe, or a Run check), how a value is extracted, how it is compared with
3616 the last observation, the condition that fires, the actions it wakes (notification, event, webhook, Actor task, Codes run, Run job),
3617 its budget and retention. Valid and invalid fixtures in `fixtures/watch.watch/`.
3618- `watch.watch-request@1` (the create/patch body), `watch.watch-result@1` (the list/watch and pause/resume/delete answers),
3619 `watch.observation@1` (one recorded value, immutable) and `watch.check-run@1` (one check execution, immutable, with the twelve
3620 terminal states the service's `check_runs.state` CHECK allows), each with fixtures. The request reuses `watch.watch@1`'s `$defs`
3621 rather than restating the source and condition shapes.
3622- Events: `watch.observation.recorded` (subject `watch`, internal, low), `watch.watch.triggered` (internal, important; Network turns
3623 it into a `WATCH_TRIGGERED` notification for `payload.recipient`) and `watch.check.failed` (internal, normal, with
3624 `consecutive_failures`). **The dossier's `watch.triggered` is named `watch.watch.triggered` here**: the repo's event-type pattern
3625 (`test/run.js:123`) requires at least three dot-separated segments, as every existing type has.
3626- Capabilities `watch.watch.read`, `watch.watch.manage`, `watch.observation.read` and `watch.check.run` (all planned, first-party),
3627 and `manifests/services/watch.json`, a placeholder like Run's: the OpenVibe.Watch repository does not exist yet, so nothing is
3628 built. `manifests/products/openvibe.watch.json` now names `watch` as its service, as `openvibe.run` names `run`.
3629- `contracts/platform/resource-offer.v1.json`: the `capabilities` description now documents `runtime:<class>` for a kind harness
3630 beside the reserved `worker:<class>` names (a docs-only change; Codes already advertises them). `lib/ids.js` already carried
3631 `watch`/`observation`/`check`, so it is untouched.
3632
3633## 0.101.0 — 2026-10-05
3634
3635**The task contract** (plan T17, ADR-044). Additive: one new planned contract and its ADR, no existing schema changed.
3636- `platform.task@1` (new, owner `network`, public, **planned**): one task at OpenVibe.Actor's router — the resource
3637 `POST /v1/tasks` creates and `GET /v1/tasks/{id}` reads, modelled on Run's `platform.job@1`. It carries `id`
3638 (`tsk_<ULID>`), `project_id`, `requester` (a person or an `agent` subject), the `task` text, `mode`
3639 (`cheapest | balanced | best | fastest | private`), `budget` (`per_task_usd`, `per_day_usd`), `state`
3640 (`queued | running | verifying | succeeded | failed | cancelled`), `created_at`/`finished_at`, `result`, `cost`,
3641 `explanation` (a chain of `platform.placement-result@1`, an escalation appending one), the SSE `progress`
3642 descriptor, the `cancel` record and registered `webhooks` (HTTPS only, secret by reference). Valid and invalid
3643 fixtures in `fixtures/platform.task/`.
3644- `docs/adr/ADR-044-actor-runtime.md` (new, **Proposed**; plan T17, the build-order item after the engine): the task
3645 contract, the adapter interface (capabilities, limits, a reviewed rate card, trust class and BYO keys), modes as
3646 `openvibe-sdk/placement` objectives, live signals with hysteresis and immediate failover, a `verifying` state for
3647 cheap-first cross-family checks and the task's own tests, and the five ADR-046 trust classes with `private`
3648 narrowing to OpenVibe-only. Owner is `network` because no Actor service manifest exists: OpenVibe.Actor is a product
3649 page (`manifests/products/openvibe.actor.json`, `noRepo`), and every other `platform.*` contract is Network's too.
3650- `lib/ids.js`: the `task` prefix (`tsk`), so `ids.newId('task')` mints the contract's id.
3651
3652## 0.100.0 — 2026-10-05
3653
3654**Three small contract fixes** (plan follow-ups). Additive and widening, no contract removed.
3655- `platform.usage-sample@1` now says what `resource` is: the producing service's `platform.rate-card@1` `metric` for
3656 the reading's `provider` (e.g. `tokens`), never a run, job or object id, with a `unit` that is that metric's unit —
3657 which is exactly what Billing looks the card up by (`provider` + `resource`, then a unit that fits the metric).
3658 Without the description AI shipped `resource` as a run id and no card matched. A valid AI reading,
3659 `fixtures/platform.usage-sample/valid/ai-per-metric.json` (service `ai`, provider `openai`, resource/unit `tokens`),
3660 and a matching `fixtures/platform.rate-card/valid/ai-tokens.json` ground it.
3661- `platform.placement-result@1`: `selected` is now `type: [string, null]` and says null means no eligible candidate.
3662 openvibe-sdk/placement `plan()` already answers `{ selected: null, … }` when nothing qualifies; the string-only
3663 schema refused the only shape that is sent, so this is recorded in `compatibility/corrections.json` against
3664 v0.99.0. Valid fixture `fixtures/platform.placement-result/valid/none.json`.
3665- `chat.ticket-conversation@1` (new, owner `chat`, first-party, **planned**) and the planned `chat.ticket.write`
3666 capability on Chat's manifest: one conversation per (ticket id, calling service), with a posted message whose
3667 `author_kind` is `person`, `agent` or `staff`, `author` is the author's subject, `body` the text and `created_at`
3668 when it was written. It gives Help's service tokens a path into Chat without the person-only `POST /api/chat/send`;
3669 until Chat implements the route the capability stays out of `generated/openapi/chat.json`. Valid and invalid
3670 fixtures are in `fixtures/chat.ticket-conversation/`.
3671
3672## 0.99.0 — 2026-10-04
3673
3674**The estate, generated** (plan T1 step 3). `scripts/estate.js` reads every checkout under the estate root (default
3675`~/OpenVibers`) — each one's `package.json` pins, `STATUS.json`, `migrations/`, and this repository's
3676`manifests/services/` and `manifests/products/` — and writes one `manifests/repositories/<name>.json` per repository
3677plus `docs/ESTATE.md`, the plan §1.1 table (repository, product, authority, runtime, database, domain, SDK/Contracts
3678pin, deployment, public/private, current track). `node scripts/estate.js --check` exits 1 when either is stale; with no
3679checkout root (CI) it checks `docs/ESTATE.md` against the checked-in manifests and skips the rest. `docs/ESTATE.md`
3680was a hand-written 2026-09-30 table and is now a projection of those records, never edited by hand. Additive, no
3681contract changes.
3682
3683## 0.98.0 — 2026-10-05
3684
3685**The node-revoked event contract** (plan T2 follow-up; the deferred item in OpenVibe.Network's
3686`docs/t2-cells-and-node-principal.md` section 10, "Revocation latency outside Bot"). Adds
3687`network.link.revoked@1` (owner `network`, first-party, active): a node principal (`lnk_…`), a person's paired
3688machine, was revoked through `POST /internal/node-principals/:id/revoke` (`network.node.manage`, the service that
3689paired it) or `POST /api/v1/me/nodes/:id/revoke` (the owner's session), or with the owner's account. The payload is
3690`{ node_id, principal_id, owner, reason?, at }` (`extra` fields refused): `owner` is the person, project or platform
3691the machine belongs to, `reason` the caller's text when one was given, and the credential and its hash are never
3692carried. Until now a connected machine learned of a revoke only at its next reauth (≤ 330 s); a consumer can stop it
3693at once. Registered in the catalog, in Network's `eventsProduced`, and on `network.node.manage`'s `events`, with valid
3694and invalid fixtures. Network emitting it inside `server/registry/node-principals.js` is a separate follow-up PR and
3695depends on this one; there is no consumer yet. Additive.
3696
3697## 0.97.0 — 2026-10-04
3698
3699**The job contract matches the Link again, and Bot's dispatch answer has a contract** (plan T14 step 6 follow-up).
3700- `platform.job@1`: `artifact` is required for class `code` as well as `function` again — the allOf `if` names both
3701 classes and the `artifact` description says so — and the invalid fixture `code-without-artifact` is back.
3702 OpenVibe Link already refuses a code job without an exact-version artifact (its `internal/protocol/protocol.go`
3703 `JobNoArtifact`), and `run.job-create-request@1` already required it; b88849c had dropped the `code` case from
3704 this contract alone. A correction to match the implementations, not a new rule.
3705- `bot.job-dispatch-result@1` (new, owner bot, ADR-034): what OpenVibe.Bot answers OpenVibe.Run's `bot.job.dispatch`
3706 calls (Bot `server/api/v1.js`, `server/jobs/index.js`). `POST /api/v1/jobs` (201) and `POST /api/v1/jobs/:id/cancel`
3707 answer `{ job, sent }`; `GET /api/v1/jobs/:id` answers `{ job, stdout }`. `$defs.job` is the `run_jobs` row
3708 (`state` queued … expired, device, payer project, timing, exit, `usage_read` and the original `platform.job@1`
3709 body); `$defs.stdout` is the held stdout (the last 1 MiB, or null). `bot.job.dispatch` names it as its
3710 `outputSchema`, so that capability is complete and its row leaves `compatibility/capability-schema-gaps.json`;
3711 `generated/openapi/bot.json` now carries the responses. Additive.
3712
3713## 0.96.0 — 2026-10-04
3714
3715**OpenVibe.Bot's job dispatch for OpenVibe.Run** (plan T14 step 6, R1c): Run hands a job to a paired Link through Bot.
3716Additive, no breaking changes. One new internal, sensitive capability owned by bot, added to
3717`manifests/services/bot.json`: `bot.job.dispatch` (permission `bot:jobs`, resource constraint `project`, input
3718`platform.job@1`, events `run.job.*`). Service-to-service only (Run's service token); never granted to an app or mod and
3719never delegated to people. It names three routes, so `generated/openapi/bot.json` carries them:
3720 - `POST /api/v1/jobs` `{node_id, job, project_id, subject, provider}` dispatches a job (idempotent by job id;
3721 `project_id` is required).
3722 - `POST /api/v1/jobs/:id/cancel` cancels it.
3723 - `GET /api/v1/jobs/:id` returns its state, stdout included.
3724
3725Its `outputSchema` is a recorded gap in `compatibility/capability-schema-gaps.json` until Bot's answer shapes land.
3726
3727## 0.95.0 — 2026-10-04
3728
3729**The Services control plane** (ADR-048, plan T13 step 1). Additive: three new catalog ids at 1.0.0, owner `contracts`.
3730`common.resource-name@1` is the OVRN `ovrn:<service>:<project_id>:<type>/<id>`, with the pattern `common.usage-recorded@1`
3731and `common.resource-summary@1` already use. `common.resource-control-request@1` is one control operation OpenVibe.Services
3732sends to the authority that owns a resource (`action`, `resource` or, for `create`, `resource_kind`, `project_id`,
3733`idempotency_key`, optional `params`, `on_behalf_of`, `confirmation_id`, `dry_run`, `trace_id`), and
3734`common.resource-control-result@1` the authority's answer (`state` done, pending, refused or failed, with `result`,
3735`confirmation_required` or an `errors.problem@1`). New `contracts.resources`: `parse`, `format`, `nameOf`, `checkName`,
3736`checkControlRequest` (the resource's project is `project_id`; `create` names a kind, every other action a resource) and
3737`checkControlResult` (`problem` and `confirmation_required` fit `state`). New test `test/resources.test.js`.
3738
3739**OpenVibe.Chat's internal read API** (plan T3, J4b): OpenVibe.Live stops reading its mirrored copy of Chat's tables.
3740Additive. Six new internal capabilities owned by chat (loopback, Chat service token, Live's principal today; never
3741granted to an app or delegated), added to `manifests/services/chat.json`:
3742 - `chat.stats.read` (`POST /internal/chat/stats`): `chat.stats-request@1` (`kind` site, user, stream or channel-top,
3743 an optional epoch-ms window, `limit` 1-50) → `chat.stats-result@1` (`messages`, `chatters`, `sounds`, `top_chatters`).
3744 - `chat.messages.read` (`GET /internal/chat/messages`) → `chat.messages-page@1` (`chat_messages` rows, `max_id`).
3745 - `chat.analysis.read` (`GET /internal/chat/timeline`) → `chat.timeline-result@1` (`buckets` of `{t, count}`, `max_id`).
3746 - `chat.moderation.queue.read` (`GET /internal/chat/moderation/pending-ip`, `…/relay-users`, `…/relay-users/:id`,
3747 `…/tts-override`) → `chat.moderation-queue-result@1`, one shape per route with Chat's `pending_ip_messages`,
3748 `hidden_relay_users` and `tts_voice_overrides` rows. `chat.moderation.read` is unchanged.
3749 - `chat.sounds.read` (`GET /internal/chat/sounds`) → `chat.sounds-result@1` (`count`, or the `channel_sounds` rows
3750 still without a Media asset).
3751 - `chat.sounds.write` (`POST /internal/chat/sounds/asset`): `chat.sound-asset-request@1` → `chat.ingress-ack@1`.
3752
3753`chat.send-result@1` 1.2.0: the `POST /internal/chat/messages` answer gains optional `first_chat` (boolean).
3754
3755## 0.94.2 — 2026-10-04
3756
3757**`past_due` renewal grace on the billing events** (plan T5 step 11, s1). Additive: no field is required or removed.
3758`billing.entitlement.changed@1` `subscription.status` gains `past_due` (a failed renewal, retried until `grace_until`);
3759new optional `grace_until` (date-time or null) and `renewal_period_end`; `reason` adds `renewal_failed`, `grace_ended`
3760and `credit_refund`. `billing.subscription@1` status lists `past_due`. `billing.transaction.reversed@1` already carried a
3761refund of a credit-paid subscription period (type `refund`, from/to swapped); its description now says so, and a fixture
3762pins it. New test `test/billing-grace.test.js`. Billing and VIP pin this tag.
3763
3764## 0.94.1 — 2026-10-04
3765
3766`community.moderation.action@1` catalog version is `1.1.0` (the additive space-moderator actions of 0.94.0).
3767
3768## 0.94.0 — 2026-10-04
3769
3770`community.moderation.action@1` accepts the audit events of per-space moderators (OpenVibe.Community PR 15): the
3771`action` values `space.moderator_added` and `space.moderator_removed`, and the target type `space` (`id` the space
3772slug, `owner_subject` the moderator). Additive; fixtures for both actions.
3773
3774## 0.93.1 — 2026-10-04
3775
3776**Usage rollups are counts, readings are money** (plan T5 step 8, C1; ADR-031 Counting). Description-only: no schema shape
3777change. `common.usage-recorded@1` says rollups are counts for dashboards and quotas and Billing never consumes a
3778`*.usage.recorded` topic; `platform.usage-sample@1` says `idempotency_key` is the only dedupe key and encodes work identity
3779only, and `service` is the producing service's manifest id; `billing.usage.record` is the only money input to Billing. New
3780test `test/usage-topics.test.js`: only network, codes and zone may list a `*.usage.recorded` topic as consumed.
3781
3782## 0.93.0 — 2026-10-04
3783
3784**OpenVibe.Bot's profiles, device protocol, operator commands, pairing and events** (plan T15 R7; ADR-043). The Bot
3785manifest and its capabilities came in 0.85.0; this adds the contracts Bot's code already speaks, taken from Bot
3786`155accc` and OpenVibe Link `1ebf1a7`. Additive: every contract id is new.
3787- `bot.robot-profile@1` (public): a profile as `server/profiles/*.json` ships it and `GET /api/v1/profiles` serves it
3788 (null vendor, kind, description, variants and camera; defaulted limits; `halt` always in `commands`). The per-kind
3789 `commands` schema is Bot's (`drive`/`ptz` axes, `actuator` number, rgb, tone and bool, `say`, `display`); capability
3790 and widget names stay open strings.
3791- `bot.device-message@1`: one frame on the `/device` WebSocket, `v`, `seq`, `ts` on every frame. Server to device:
3792 `hello`, `config`, `command`, `estop`, `heartbeat_ack`, `error`, `paired`, `rotate`; device to server: `pair`,
3793 `status`, `telemetry`, `ack`, `nack`, `heartbeat`, `reauth`, `estop_state`. Job frames stay `platform.job-frame@1`.
3794 The description names both implementations (Bot `server/realtime.js`, Node `internal/protocol/protocol.go`).
3795- `bot.command@1` and `bot.command-result@1`: the `/control` command frame and its `command_result` answer (`ack`,
3796 `nack`, `refused` with Bot's refusal code, `expired`, `pending`; `cached` for a repeated id).
3797- `bot.robot-read-request@1`: the query of `bot.robot.read` (`owner`, and `limit`/`before` for the audit page); it is
3798 now that capability's input, so its OpenAPI routes list the query parameters.
3799- `bot.pair-request@1` and `bot.pair-result@1`: `POST /api/v1/pair` and `POST /api/v1/devices/bind`. The credential,
3800 the publish key and the WHIP URL are shown once; without OpenRe the answer says `video: not_configured`.
3801- Event payloads for the five events Bot produces: `bot.robot.online` and `bot.robot.offline` (`robot_id`,
3802 `device_id`), `bot.estop.set` and `bot.estop.cleared` (`robot_id`, `by`, `principal_kind`), `bot.command.refused`
3803 (`robot_id`, `kind`, `reason`, `role`; never the value).
3804- `bot.robot.control` lists its `/control` WebSocket bindings (`command`, `estop`, `estop_clear`) as notes, and the
3805 events they emit (`bot.estop.cleared`, `bot.command.refused`); the Bot manifest's notes name both WebSockets' contracts.
3806- New `test/bot-manifest.test.js`: the manifest's capabilities and events equal Bot's `STATUS.json` lists.
3807
3808## 0.92.0 — 2026-10-04
3809
3810`platform.job@1` gains `inputs` (Media objects pinned by sha256) and the `net` values `none`, `public`, `openvibe-only`.
3811Additive; a v1 worker still refuses an unknown `net` with `nack`.
3812
3813## 0.91.0 — 2026-10-04
3814
3815**Chat's service-token ingress** (plan T3 J2, OpenVibe.Chat PR #16). These are the capabilities and request contracts of
3816`/internal/chat/*`, the typed Chat endpoints that replace Live's generic bridge (`POST /internal/live/calls`). All of it is
3817additive.
3818- New active capabilities, owner `chat`, `first-party`, quota class `internal-write`, each with an input and an output
3819 schema. They are loopback only and need a service token. They are never granted to an app or delegated to an agent.
3820 - `chat.event.publish` (`POST /internal/chat/events`, sensitive): transient frames to a stream, a channel, an owner's
3821 streams, global chat, everyone or one person.
3822 - `chat.moderation.write` (`POST /internal/chat/moderation`, sensitive): one typed action per request (deletes,
3823 IP-approval reviews, relay identities, TTS voice overrides, disconnect, log). It emits `chat.message.deleted` and
3824 `chat.moderation.action`.
3825 - `chat.cache.invalidate` (`POST /internal/chat/invalidate`): cache hints for a person, a channel, IP approvals and bans.
3826 Chat's manifest lists all three.
3827- `chat.message.send` also names `POST /internal/chat/messages`, and `chat.presence.read` names
3828 `GET /internal/chat/presence`. Both keep their existing routes.
3829- New contracts under `contracts/chat/`, which follow Chat's validators:
3830 - `chat.event-request@1`: target kinds, the 16 frame types, the per-frame fields and the target each frame needs.
3831 - `chat.moderation-request@1`: one `oneOf` branch per action, each with its own fields only.
3832 - `chat.invalidate-request@1`: at least one hint, and `user_data` needs `user`.
3833 - `chat.moderation-result@1`: deleted `ids`, or `changes` and `id`.
3834 - `chat.ingress-ack@1`: `{ ok: true }`, or the `{ ok: false, error }` refusal every `/internal/chat` route answers.
3835 Every request needs an idempotency `key` of 1–160 characters `[A-Za-z0-9:._-]`. Chat applies it once per caller and
3836 route; a reused key with another body gets 409.
3837- `chat.send-request` 1.1.0 adds the `/internal/chat/messages` body (room line or DM, `mirror`, `tts`, `frame`,
3838 `first_chat_key`). `chat.send-result` 1.1.0 adds its `{ ok, id, … }` answer and the ingress error.
3839- Fixtures: valid and invalid fixtures for every new contract and for the new branches.
3840
3841## 0.90.0 — 2026-10-04
3842
3843**OpenVibe.Run service and job API** (plan T14 R1, ADR-034). The contract OpenVibe.Run is built against; everything is
3844planned (Run's repository does not exist yet) and additive.
3845- New service manifest `manifests/services/run.json`: `run`, status and exposure `placeholder`, domain `openvibe.run`,
3846 lifecycle all `none` (not built). `manifests/products/openvibe.run.json` gains `relationships.service: run` and keeps
3847 `noRepo: true`.
3848- New planned capabilities, owner `run`, each with an input and an output schema: `run.job.submit` (sensitive: it bills
3849 the project), `run.job.read`, `run.job.list`, `run.job.cancel`, `run.job.stream` (public, project-scoped) and
3850 `run.job.admin` (internal operator access to every project's jobs). `run.admin` is spelled `run.job.admin` because a
3851 capability id has three segments.
3852- New contracts under `contracts/run/`: `run.job-create-request@1` (class from `platform.runtime-class@1`, artifact
3853 required for `function` and `code`, `inputs` as Media objects pinned by sha256, `limits` wall/cpu/mem as
3854 `platform.job@1`, `ttl_ms`, `egress` `none | public | openvibe-only` as Node's `worker.egress`,
3855 `requirements` as `platform.workload-requirements@1`, `idempotency_key`), `run.job-create-result@1`,
3856 `run.job-read-result@1` (states `queued | placed | running | succeeded | failed | cancelled | expired`, placement node,
3857 timings, exit, `usage.seconds`, result, error, with per-state rules), `run.job-list-query@1`, `run.job-list-result@1`
3858 (`next_cursor` pages), `run.job-stream-ticket-result@1` (one-use, two-minute ticket, as Events' realtime ticket) and
3859 `run.job-stream-event@1` (SSE `output | state | end`).
3860- New planned events produced by Run: `run.job.queued`, `run.job.started`, `run.job.succeeded`, `run.job.failed`,
3861 `run.job.cancelled` and `run.job.expired`, projections of the job without args, inputs, result or output.
3862- `ids.newId('job')` mints `job_<ULID>`, the `platform.job@1` id Run passes to the node, so the metering key stays
3863 `run:<job id>:<n>`.
3864- Fixtures: valid and invalid for every new contract; `test/platform-run.test.js` pins the Run job id, artifact,
3865 limits and egress to `platform.job@1` and Node, and `usage.seconds` to the sum of the job's readings.
3866
3867## 0.89.0 — 2026-10-03
3868
3869**Agent tokens and confirmations** (plan T2 step 9; OpenVibe.Network `docs/t2-projects-and-grants.md` §2 gaps 1–3,
3870§4 and §5). These are the contracts that Network WS-Z2 slices 7–9 wait on. All of it is additive.
3871- `identity.service-token-claims` 1.3.0: `sub` also accepts `agent:agt_<ULID>` (`ids.principalSub({ type: 'agent' })`)
3872 and `actor_type` gains `agent`. An agent token must carry `project_id`, `env` and `on_behalf_of` (the owner, `usr_`).
3873 It may carry `cap_confirm` (capabilities held in confirm mode: each use needs an approved
3874 `network.confirmation-request@1`, and they never appear in `cap`, so a receiver that does not know agents refuses
3875 them) and `act` (RFC 8693 actor claim: `{ sub: 'svc:<slug>' | 'app:app_<ULID>' }`, the host, nothing else).
3876 `if`/`then` rules tie an `agent:` sub to `actor_type: agent` in both directions. Service, app, mod and node
3877 tokens validate as before.
3878 Fixtures: valid `agent-service-host` and `agent-app-host-auto-only`; invalid `agent-without-owner`,
3879 `agent-sub-as-service`, `agent-actor-with-service-sub` and `agent-bad-actor-claim`.
3880- New capability `network.confirmation.manage` (planned, first-party, listed by `manifests/services/network.json`). It is
3881 the owning service's side of a confirmation: create one (`POST /internal/confirmations`), read it, consume it once
3882 with the action's digest, or cancel it. The owner's inbox (`/api/v1/confirmations`: list, approve, deny) runs on the
3883 owner's own session, and no token holds it. The request and response bodies are Network-local until the routes are
3884 built.
3885- New event `network.confirmation.changed@1` (planned, produced by Network), the shape of Network's proposal
3886 (`docs/contracts-proposal/network.confirmation.changed.v1.json`). Payload: `confirmation_id` (`cnf_`), `agent_id`
3887 (`agt_`), `project_id`, `capability`, `audience` (the owning service), `state` (`pending | approved | denied | expired
3888 | cancelled`, the names of `network.confirmation-request@1`) and `change` (`created | approved | denied | expired |
3889 cancelled | used`), and optional `standing_rule`, `rule_id`, `cancel_reason`, `expires_at` and `changed_at`. `created`
3890 leaves the state pending, or approved when a standing rule covers it; `used` leaves it approved; every other change
3891 names its state. `cancel_reason` is required on cancelled and absent otherwise. The event never carries `summary` or
3892 `details`. Fixtures: valid `requested`, `approved-by-owner`, `approved-by-standing-rule`, `used`, `cancelled` and
3893 `expired`; invalid `requested-state`, `cancelled-without-reason`, `used-not-approved`, `missing-audience` and
3894 `with-summary`.
3895
3896## 0.88.0 — 2026-10-03
3897
3898**The Fabric ADR and the user-owned trust rule** (plan T1 step 3; T14 S2, the Contracts half). ADR-046 "The universal
3899adaptive fabric" (Proposed, for the owner) ties `platform.resource-offer@1`, `workload-requirements@1`,
3900`placement-result@1`, `placement-plan@1`, `provider-state@1`, `rate-card@1`, `cost-snapshot@1`, `telemetry-sample@1`
3901and `usage-sample@1` to one placer (`openvibe-sdk/placement`), names the five trust classes, the `worker:<class>`
3902capabilities a Link advertises (`worker:function`, `worker:code`, …) and the plane rule: the data plane keeps running
3903on the last valid signed plan (`signature`, `epoch`, `expires_at`, checked by `placement.verifyPlan`). It records that
3904`user-owned` is **not** in the default trust set: a user-owned offer is eligible only for a workload whose requirements
3905name `user-owned`, so the SDK's default trust list stays the other four (this replaces the 0.87.0 note that the SDK
3906should route to user-owned nodes by default). Whether a user-owned node may run other users' work, and its consent and
3907revocation rule, are open questions for the owner.
3908- `platform.resource-offer@1` `trust` and `platform.workload-requirements@1` `trust` gain descriptions stating that
3909 rule; the enums (1.1.0 since 0.87.0) are unchanged. Consumers are unchanged.
3910- Fixtures: `user-owned-node` now also advertises `worker:function`; new invalid `unknown-trust` (an offer with
3911 `trust: "stranger"`, refused on `/trust` alone). `owned-node` is unchanged.
3912
3913**Two product manifests** (plan T11 step 1): `manifests/products/openvibe.zone.json` (served by the planned `zone`
3914service) and `manifests/products/openvibe.work.json` (no repository yet), with name, tagline, pillars and launch taken
3915from OpenVibe.Sites `sites.json`. The catalog test's Sites snapshot holds 35 domains.
3916
3917- `network.project.read` is active, implemented by OpenVibe.Network `GET /internal/projects/:project_id`.
3918
3919**Watch ids** (plan T18, ready now):
3920- `lib/ids.js`: `PREFIX.watch = 'wch'`, `PREFIX.observation = 'wco'` and `PREFIX.check = 'ckr'`, so `ids.newId('watch')`
3921 gives the `wch_<ULID>` id the `common.resource-summary` fixture `watch` already carries. None is a subject type or a
3922 principal.
3923
3924**Harness capability vocabulary** (plan T17, ready now):
3925- `platform.harness-offer@1` `capabilities` gains the optional booleans `edit`, `review`, `tools`, `vision`, `browser`
3926 and `computer_use`, and an optional `runtimes` array (unique; `function`, `code`, `browser`, `linux`, `desktop`,
3927 `gpu`, the `platform.runtime-class@1` classes). `capabilities` keeps `additionalProperties: false`, and the entry stays
3928 1.0.0, as it did when 0.86.0 added optional fields. New fixtures `capability-vocabulary` (valid, every new key) and
3929 `unknown-capability` (invalid, a `gpu` key: a runtime class belongs in `runtimes`). Additive.
3930
3931**Resource names in the resource index** (plan T13, ready now):
3932- `common.resource-summary@1` is 1.1.0: an optional `ovrn` (ADR-034 section 2) with the pattern of
3933 `common.usage-recorded@1` `resource`, naming the summary's own service, project and id. New fixtures `with-ovrn`
3934 (valid) and `ovrn-without-project` (invalid). Additive.
3935
3936## 0.87.0 — 2026-10-03
3937
3938**Host git sources** (plan T12 Stage B): a Host site may name a public Git source — provider, repository URL and branch;
3939never a credential — and a site with a source also accepts a CI-built deploy at `/sites/:id/source/deploys` naming the
3940ref and full `commit_sha`. That deploy is always a preview and records the commit as immutable provenance.
3941- `host.site.manage` gains `GET`, `PUT` and `DELETE /api/v1/sites/:id/source`; `host.deploy.create` gains
3942 `POST /api/v1/sites/:id/source/deploys`.
3943- `host.deploy@1`: the `source` enum adds `preview` and `git`, and an optional `git` object carries `provider`,
3944 `repo_url`, `ref` and a 40-hex `commit_sha`. New valid fixture `git`. Additive: every existing deploy stays valid,
3945 and the object is present only on `source: git`.
3946
3947**The Bot service manifest** (plan T15 step 1; ADR-043; supersedes #8). OpenVibe.Bot has run on openvibe-ovh since
39482026-10-02 (`openvibe-bot.service`, `/opt/openvibe.bot`), and `ovhost validate` found no `bot` manifest to read its
3949lifecycle from.
3950- `manifests/services/bot.json`: status `live` on `openvibe.bot`, internal origin `127.0.0.1:4630`, the five `bot.*`
3951 events it produces, and all six lifecycle parts. Shutdown is what Bot's `openvibe-sdk/service` `gracefulStop` does:
3952 stop the job timers and Network key refresh, close the device and operator WebSockets and the outbox relay, drain HTTP
3953 for up to 4 s, close PostgreSQL and Valkey, exit 0, with a 5 s hard deadline inside the unit's 10 s `TimeoutStopSec`.
3954 The contracts range `>=0.85.0 <1.0.0` covers the v0.85.0 Bot installs.
3955- Three active capabilities, each bound to the routes whose guard checks it in the deployed Bot (dae7c59), for a
3956 Network service token: `bot.robot.read` (list by `?owner=`, a robot, its operators and devices), `bot.robot.manage`
3957 (create, update, delete, pairing codes, operators, the command audit, clearing the e-stop, rotating and revoking a
3958 device) and `bot.robot.control` (latching the e-stop, which also needs `bot.robot.read`, and the operator WebSocket,
3959 which acts for `X-OV-Subject` with that person's role). Their resource constraint is `none`: Bot does not check the
3960 acting person against the robot for a service token on the REST routes, and the descriptions say so. All are
3961 first-party, none is a staff capability, and each names an input and an output schema: new `bot.robot@1`,
3962 `bot.device@1`, `bot.robot-read-result@1`, `bot.robot-manage-request@1`, `bot.robot-manage-result@1` (which includes
3963 the audit page and `bot.device-connect-result@1`), `bot.robot-control-result@1` and `bot.device-connect-result@1`,
3964 with valid and invalid fixtures.
3965- `bot.device.connect` is `planned` (the Bot manifest lists it, as owners list their planned capabilities): Bot
3966 declares the name but no route checks it, so it names no routes or schemas until one does.
3967- `openvibe.bot` product: names its service `bot` and repository `OpenVibe.Bot` instead of `noRepo`.
3968- Presence policy: `bot.robot.online` and `bot.robot.offline` are robot connectivity (ADR-043), not a person's presence,
3969 and are allowed. Any other `.online`, `.offline` or presence event type is still refused.
3970
3971**Media placement events** (follow-up of OpenVibe.Media PR #18, "Record placement decisions for replicas and provider
3972transitions"; ADR-026). Media records every replica move and provider transition in its placement outbox, but the two
3973provider events used types starting with `provider.`, which OpenVibe.Events can never accept from source `media`: its
3974prefix gate (`server/config.js` `sourcePrefixes`, `server/api/publish.js`) requires an `event_type` to start with the
3975source key, so both were permanently rejected (`403 events.type_not_allowed`) and piled up in `event_outbox`. The types
3976now live in the media namespace (`media.provider.health_degraded`, `media.provider.capacity_warning`), and all six event
3977types Media emits today gain active payload contracts owned by `media`, listed in its manifest:
3978- `media.replica.requested`, `media.replica.ready`, `media.replica.draining`, `media.replica.evicted` (Media's
3979 `server/objects/tiering.js`: the promote/demote decisions, recorded inside the transaction that starts the copy, upserts
3980 the verified location, starts the delete and removes it).
3981- `media.provider.health_degraded` and `media.provider.capacity_warning` (Media's `server/placement/providers.js`: the
3982 healthy→unhealthy flip and the class loss after a completed probe), each emitted once per transition, not per tick.
3983
3984Each payload is deliberately narrow — the object id and tenant, placement class, action, providers, key/size for a
3985replica, the class set before and after a loss — never the object's bytes, title or metadata. `media.replica.*` was
3986already inside the streamable namespace; only the provider types changed. Valid and invalid fixtures for each, and
3987`test/run.js` asserts every type Media produces starts with `media.`, is owned by `media` and is listed in its manifest.
3988
3989**User-owned trust class and the estate table** (plan T1 step 3; ADR-034 §5 control plane/data plane; the Fabric ADR,
3990ADR-046, is still to write). A person's own node or machine is now a trust class of its own in Contracts, between
3991`first-party` and `partner`. The SDK placement planner's runtime already honours an explicit `trust: ["user-owned"]`
3992requirement, but its default trust list and its TypeScript `Offer` type omit the value, so the SDK needs code and type
3993changes as well as a pin to this release to route to user-owned nodes by default.
3994- `platform.resource-offer@1` 1.1.0 and `platform.workload-requirements@1` 1.1.0 add `user-owned` to their `trust`
3995 enum, ordered `first-party`, `user-owned`, `partner`, `community`, `external`. Additive: a producer or consumer that
3996 knows only the previous four values is unchanged, and no existing offer or requirement is invalidated. New valid
3997 fixtures `user-owned-node` (an offer with `trust: "user-owned"`) and `user-owned-only` (requirements whose `trust` is
3998 `["user-owned"]`); the existing first-party `owned-node` fixture stays.
3999- `platform.usage-sample@1`: `route_epoch` and `trace_id` gain descriptions; their types and shape are unchanged.
4000- `docs/ESTATE.md`: the plan §1.1 estate table as a data-only document (repository, product, authority, runtime,
4001 database, domain, SDK/Contracts pin, deployment, public/private, current track). Step 2 replaces it with the table
4002 generated in CI.
4003
4004**Named object zones for OpenVibe.Zone** (ADR-031 amendment 2026-10-02; plan D37). The amendment maps named Zone buckets
4005onto Media's S3 surface. A zone is a Media namespace, and Media keeps the one object catalog and the only deletion
4006path.
4007- **Ownership:** Zone owns the zone record and Media owns objects, bytes and replicas.
4008- **Names:** zone `zon_<ULID>`, `ovrn:zone:<project_id>:object-zone/<zone_id>` and Media namespace
4009 `<environment root>.<zone_id>`.
4010- **Buckets:** the bucket is the zone name, resolved within the signing key's project and environment. The environment
4011 root is the zone `default`, so no existing object moves.
4012- **Grants and quotas:** grants are scoped to a zone's resource name. A per-zone byte quota sits under the environment
4013 quota.
4014- **Usage:** Media emits per-zone usage rollups that name the zone's resource name in a new optional `resource` field
4015 of `common.usage-recorded@1` 1.1.0 (additive; existing producers are unchanged) and its id as `dimension`.
4016 `contracts.usage.checkUsageRecorded` refuses a rollup whose `resource` names another project than `project_id`, and
4017 `contracts.zones.checkObjectZoneUsage` a usage answer whose `ovrn` names another zone than `zone_id`.
4018- **Deletion:** one lifecycle for every door, the one `media.object.delete` already promises: a held object's deletion
4019 is refused, a tombstone is restorable until the retention period ends, and the purge then erases every replica, B2
4020 file versions included, within 24 hours. Zone deletion tombstones with no restore window and answers `409 zone.held`
4021 while an object is held.
4022- **No name reuse:** a `deleting` or `deleted` zone's name is retired in its environment (`409 zone.name_retired`; `provisioning`
4023 and `active` answer `409 zone.name_taken`), so a signature,
4024 which covers the key and the bucket name, always names one zone id, whatever signing time it carries.
4025 `contracts.zones.checkObjectZoneList` refuses a list in which two zones of one environment share a name.
4026- **List query:** `limit` is 1 to 200 as an integer or as a query-string value.
4027- **Migration:** Media backfills a key derived from each object's namespace and `med_` id, legacy child namespaces
4028 included, before S3 accepts writes. The default zone's access is `per-object`, so existing public and unlisted
4029 objects keep their URLs and cached copies.
4030- **Control API:** a planned Zone service manifest (`manifests/services/zone.json`) with six planned capabilities, one per
4031 route. The capabilities enter `generated/openapi` when they turn active.
4032- **Contracts:** new `zone.object-zone@1` and its create, update, list, list-query, delete-query and usage contracts,
4033 all `planned`, with fixtures. `contracts.zones.checkObjectZone` also checks that a zone's OVRN and Media namespace
4034 name its own project and id. Additive; no active contract changes.
4035
4036**Reserved worker capability names for OpenVibe Link** (plan T14 groundwork, additive): a Link advertises its runtimes
4037as `worker:` capabilities in `platform.resource-offer@1`. The names are reserved in the contract now, not only by the
4038`capabilities` pattern: `platform.resource-offer@1` gains `$defs.reservedWorkerCapabilities`, the six names
4039`worker:function`, `worker:code`, `worker:browser`, `worker:linux`, `worker:desktop` and `worker:gpu` — one per
4040`platform.runtime-class@1` class (`worker:` + the class) — and both the `capabilities` description and
4041`platform.runtime-class@1` say so. A node advertises the name of each class it runs, so `worker:function` today and
4042`worker:code` when the `code` class ships. Additive to validation: every existing offer stays valid, and other
4043`worker:` names (`worker:ffmpeg`, `worker:ai-gpu`) stay ordinary capability names. New valid fixture `worker-classes`
4044(an offer advertising all six reserved names). Four new valid fixtures for `platform.runtime-class@1` (`code`,
4045`browser`, `linux`, `desktop`) complete its six `const` classes.
4046
4047## 0.86.0 — 2026-10-03
4048
4049**Harness offers for Fabric routing** (plan T16 step S5): OpenVibe.Codes publishes its harness catalog as
4050`platform.resource-offer@1` offers of kind `harness` whose `detail` is a `platform.harness-offer@1`; the envelope keeps
4051`trust`, `health`, `latency_ms`, `pricing` and `capabilities`.
4052- `platform.harness-offer@1` gains four optional fields: `task_capabilities` (unique; `edit`, `review`, `browse`,
4053 `run`, `test`, `plan`), `runtime_needs` (unique runtime names such as `git`, `node`, `python`, `docker`; pattern
4054 `^[a-z][a-z0-9.-]*$`, at most 40 characters), `byo_key` (the caller supplies their own provider key) and
4055 `success_rate` (0 to 1, the measured share of routed tasks that finished green). The example carries them; fixtures
4056 `fabric-routing` (valid), `unknown-task-capability` and `success-rate-over-1` (invalid).
4057- `platform.resource-offer@1`: no schema change. The `capabilities` description names the harness convention:
4058 `task:edit`, `task:review`, `task:browse`, `task:run`, `task:test`, `task:plan`, `harness:mcp`, `harness:resume`,
4059 `harness:host-access`, `harness:long-autonomy`. New valid fixture `harness-task-routing`. Additive.
4060
4061**Run jobs and their metering** (plan T14 lane G, follow-up 1 of the Link gap audit):
4062- New `platform.runtime-class@1`: the classes `function`, `code`, `browser`, `linux`, `desktop` and `gpu`, names
4063 only; `function` is the first one implemented.
4064- New `platform.job@1`: `id` (`job_<ULID>`, the idempotency and ack key), `class`, `artifact` {`name`, `version`}
4065 (required for `function`), `args`, `ttl_ms`, `limits` {`wall_ms`, `cpu_ms`, `mem_bytes`} and `net` (only `deny`,
4066 the default).
4067- New `platform.job-frame@1`: the job frames on the device control link, in its `v`/`seq`/`ts` envelope. Server to
4068 device: `job`, `job_cancel`, `job_exit_ack`. Device to server: `job_started`, `job_stdout` (`chunk_seq`, because
4069 `seq` is the envelope's), `job_usage`, `job_exit` (`reason`, `code`, `result`, `usage`).
4070- Metering, documented in `job_usage` and `job_exit`: one `platform.usage-sample@1` reading per wall-clock second,
4071 `run:<job id>:<second>`, service `run`, operation `function.invoke`, unit `s`, quantity 1, or the fraction for the
4072 partial last second, which only `job_exit` reports. Every field comes from the job and the second, so resends and
4073 the `job_exit` backfill replay in Billing instead of being billed twice. The link's terminator (Bot now) writes the
4074 readings. `usage-sample` gains a description sentence, a `function` example and two fixtures; no field changed.
4075- `test/platform-run.test.js` checks the derivation. Additive.
4076
4077## 0.85.0 — 2026-10-02
4078
4079**Billing records usage readings** (plan T5 lane F): the capability `billing.usage.record` (active, internal,
4080`billing:usage`, resource constraint `none`, quota class `ledger-write`), released from OpenVibe.Billing's proposal and
4081listed by `manifests/services/billing.json`. `POST /api/v1/usage` takes one `platform.usage-sample@1` reading (its
4082`inputSchema`) and stores it without moving money; the reading's `idempotency_key` deduplicates retries (same reading:
4083200 with the stored row; a different one under the same key: 409 `billing.usage_key_reused`). Listing all readings
4084(`GET /api/v1/usage`) stays under `billing.ledger.admin`. New `billing.usage-record-result@1` (its `outputSchema`):
4085`{ record }` with the stored row's `id`, `idempotency_key`, `project`, `subject`, `service`, `at`, `received_at`,
4086`principal` and the `reading` itself; fixtures `recorded` (valid) and `reading-without-idempotency-key` (invalid).
4087Network grants for the usage producers follow this release. Additive.
4088
4089**Node principals, node capabilities and per-kind resource offers** (plan T1 lane A, the contracts brief of
4090OpenVibe.Network `docs/t2-cells-and-node-principal.md` §9.1):
4091- `lib/ids.js`: `PREFIX.node = 'nod'`; `principalSub({ type: 'link', id })` gives `link:lnk_<ULID>`. A node is a
4092 principal only: `node` is not a `SUBJECT_TYPES` entry nor an `identity.subject-ref@1` type.
4093- `identity.service-token-claims`: `sub` also accepts `link:lnk_<ULID>` and `actor_type` gains `link`, so
4094 `verifyServiceToken` accepts a node token and still rejects a malformed node id. Fixtures `node-token` (valid) and
4095 `node-bad-id` (invalid).
4096- New capabilities `network.node.manage` (a service mints pairing codes and reads or revokes the node principals it
4097 paired; `nodes:pair`, `nodes:read`, `nodes:revoke`), `network.node.self.manage` (a paired machine presents its own
4098 capabilities and rotates its own credential; `nodes:self`) and `network.resource.report` (a source reports its
4099 complete set of `platform.resource-offer@1`; `resources:write`), all active, internal and listed by
4100 `manifests/services/network.json`. Their bodies are Network-local, so they name no schemas and are recorded in
4101 `compatibility/capability-schema-gaps.json`. `network.node.report` is also implemented by
4102 `POST /internal/registry/instances/report`.
4103- `platform.resource-offer`: `kind` gains `storage`, `delivery`, `runtime`, `agent` and `harness`; the new
4104 optional `detail` is required for those kinds and validated by the kind's own `platform.<kind>-offer@1`, and is
4105 forbidden for `node` and `provider`. Fixtures `storage`, `delivery`, `runtime`, `agent`, `harness` (valid, beside
4106 `owned-node` and `provider`), `storage-without-detail` and `node-with-detail` (invalid).
4107- Optional fields: `platform.service-instance` `route_weight` (integer 0-1000); `platform.node-capabilities`
4108 `capabilities` (resource-offer capability form), `agent_version` (at most 40 characters) and `updated_at`
4109 (date-time); `network.node` `cell` (`^[a-z]{2,8}-[0-9]{1,3}$`). Fixtures `route-weight`, `agent-report` and
4110 `with-cell` (valid), `route-weight-over-1000`, `bad-capability` and `bad-cell` (invalid).
4111
4112Additive.
4113
4114## 0.84.0 — 2026-10-02
4115
4116Add nine public `platform.*@1` schemas: usage and telemetry samples; node capabilities and
4117service instances; runtime, storage, delivery, agent, and harness offers. Each has valid and
4118invalid fixtures. ADR-034 is proposed. Generated types and bundle include all nine.
4119
4120`platform.usage-sample@1` can carry all 15 plan T5 usage fields in one reading (lane F). It gains four optional
4121fields: `free_allowance_used` (non-negative number in the reading's own `unit`, at most `quantity`),
4122`vibes_charged` (non-negative integer count of vibes-bits, Billing's ledger minor unit; absent means not rated),
4123and `route_epoch` and `trace_id` (same types as in `platform.telemetry-sample@1`). Readings without these fields
4124still validate. New fixtures: `all-fifteen-fields` and `minimal` (valid); a fractional or negative `vibes_charged` and
4125a negative `free_allowance_used` (invalid). Additive.
4126
4127The OpenVibe.Sites catalog (`sites.json`, 33 domains) moves into Contracts so Sites can be deleted. Additive.
4128- `registry.service-manifest` 1.1.0: `site` gains the optional `tld`, `accent`, `description`, `pillars`, `faq`,
4129 `keywords`, `vision`, `highlight`, `launch` and `relationships` (`service`, `plannedRepo`, `noRepo`, `linksLead`,
4130 `links`, `meanwhile`, `statusApi`), defined once in `registry.product@1`'s `$defs`. Filled from the catalog for the
4131 ten services whose site presents their catalog domain: news, reviews, tips, vip, trade, host, deals, coupons,
4132 openre (openre.stream) and space.
4133- `registry.product@1` (new) and `manifests/products/<domain>.json` for the other 23 catalog domains, with no
4134 invented service manifests: the Network sub-domains (auth, api, admin, themes), the media-hub brands (video, pics,
4135 download), ai.openvibe.network (moved) and ai.openvibe.services, realtime (closed), status, openvibe.events and the
4136 planned products (food, quest, rent, homes, services, run, website, help, bot, watch, actor).
4137 `relationships.service` names the manifest that serves a domain when one does.
4138- `contracts.products` (`manifests`, `get`, `siteDomain`, `catalog()`); `test/product-catalog.test.js` asserts each
4139 of the 33 snapshotted Sites domains has exactly one home and every home validates.
4140
4141## 0.83.0 — 2026-09-29
4142
4143**Host site configuration** (plan T12 J3): the capability `host.site.config` (active, first-party, `host:write`, project
4144role checked by Host) with `host.site-config@1`, `host.site-config-request@1` and `host.site-config-result@1` and their
4145fixtures, listed by `manifests/services/host.json`. GET, PUT and DELETE `/api/v1/sites/:id/config` read, replace and
4146reset a site's response headers (the platform's security, routing, caching, scope and transport headers and every
4147X-Forwarded-* are refused), its local-only redirects and its SPA fallback. Additive.
4148
4149## 0.82.0 — 2026-09-29
4150
4151**Space and the media hub: the forum moves off Community and the three new products register** (plan T10, D1–D4).
4152- Two service manifests, both `status: placeholder` / `exposure.state: placeholder` (the schema has no `planned`; a
4153 placeholder is "charter only", which is what these are until each serves): `manifests/services/space.json`
4154 (OpenVibe.Space, `openvibe.space`) and `manifests/services/media-hub.json` (OpenVibe.MediaHub). The media hub carries
4155 all three brand domains in one manifest (`domains: [openvibe.video, openvibe.pics, openvibe.download]`, the same list
4156 mechanism Network/Live/OpenRe/Games already use); the per-brand nav entry awaits the ADR-039 brand mechanism (T11).
4157- The forum capabilities are renamed off Community: `community.space.read` → `space.forum.read` (active),
4158 `community.space.manage` → `space.forum.manage` (planned), `community.thread.read` → `space.thread.read` (active),
4159 `community.post.create` → `space.post.write` (active), plus the new planned `space.thread.write` and
4160 `space.pulse.read`. The four old capability manifests stay loadable with `status: deprecated` and are still listed by
4161 `community` until their window closes.
4162- The seven forum contracts are re-owned under `space.*` (`space.forum-space/thread/post`, `space.forum-read-result`,
4163 `space.thread-read-result`, `space.post-write-request/result`) with fixtures; the `community.*` originals go
4164 `deprecated` in the catalog and get a `compatibility/deprecations.json` record naming the replacement and window
4165 (compat vs v0.80.0: no breaking changes). Contracts only exist for the three active capabilities.
4166- The smallest honest set for the media hub, all planned: `video.vod.read`, `video.playlist.read`,
4167 `video.playlist.manage`; `pics.image.read`, `pics.image.upload`, `pics.album.read`, `pics.album.manage`;
4168 `download.file.read`, `download.file.upload`, `download.share.create`. No media-hub capability is active, so none has
4169 a request/result contract yet.
4170
4171## 0.81.0 — 2026-09-29
4172
4173**Opaque cursors beside the global seq** (plan T7, ADR-042, additive).
4174- `events.publish-result@1` gains an optional `cursor` per stored event; `events.read-result@1` gains `cursor` per
4175 event, `next_cursor` per page and `cursor` on a single event. A cursor is opaque (a position plus a retention epoch):
4176 hand it back as `after=` or `Last-Event-ID`, never parse it. Events returns both `seq` and `cursor` for one release,
4177 then `seq`, `next_after_seq`, `latest_seq` and the global-order promise go.
4178- ADR-042 (the events fabric) is recorded in docs/adr.
4179
4180## 0.80.0 — 2026-09-29
4181
4182**`chat.moderation.read`: how Live reads the chat tables Chat owns** (plan T3, the six staged tables).
4183- New internal capability (owner `chat`, active): `GET /internal/moderation/channels/:channelId` (a channel's moderation
4184 settings, every `channel_moderation_settings` column with Live's defaults when there is no row, and its moderator ids),
4185 `GET /internal/moderation/users/:userId/channels` (the channels a person moderates) and
4186 `GET /internal/moderation/channels/:channelId/emote-count`. Loopback only, service token.
4187- Result contracts with fixtures: `chat.channel-moderation-result@1`, `chat.moderated-channels-result@1`,
4188 `chat.emote-count-result@1`. Chat's manifest lists the capability.
4189
4190## 0.79.0 — 2026-09-29
4191
4192**Service-token capabilities for every internal call that still used X-Internal-Key** (plan T2, register C-50–C-58).
4193- New internal capabilities, each with request/result contracts and fixtures: `network.avatar.write` (a site reports an
4194 avatar change to Network), `network.registry.read` (the resolved URL registry), `network.coins.read` (OpenCoins totals,
4195 never balances of named people), `live.avatar.write` (Network pushes an avatar to Live), `live.url_registry.refresh`,
4196 `live.analytics.read` (aggregate totals for Network's navigation), `media.avatar.ingest` (Network asks Media to import
4197 an avatar), `tools.analytics.read` (the Tools gateway's and tool sites' aggregate analytics).
4198- Avatar URLs in the avatar requests must be on `https://openvibe.media/`.
4199- The owning services' manifests list them.
4200
4201## 0.78.0 — 2026-09-29
4202
4203**OpenVibe.Realtime is gone from the estate** (plan T0).
4204- **The `realtime` service manifest is removed** (`manifests/services/realtime.json`). ADR-005 (accepted 2026-09-22) closed OpenVibe.Realtime: browser realtime is a delivery plane inside OpenVibe.Events, and the service was never built, so the estate described something that does not exist. The ADR-005 contracts it did define are unaffected and stay: `identity.realtime-ticket-claims@1`, `network.realtime-ticket-result@1` and `network.notification.created@1` are all first-party Network contracts. No capability, event, namespace or contract referenced the service, so nothing else changes. Reopening it, as ADR-005 says (measured connection counts or fan-out latency that need an independently scaled process), would be a new ADR and a new manifest.
4205
4206## 0.77.0 — 2026-09-28
4207
4208**Agents, confirmations, the adaptive fabric and the resource index** (roadmap section 4C: WS-Z1, WS-Z2, WS-Z3, WS-Z7, WS-Z9).
4209- `identity.subject-ref@1` gains the **agent** subject (`agt_<ULID>`): an agent (OpenVibe.Actor, or a developer app's agent) acting under grants its owner delegated. `ids` knows the `agt` and `cnf` prefixes; `principalSub` accepts agents (`agent:agt_…`).
4210- `events.event-envelope@1`: optional `on_behalf_of`, the person or project an agent or app acted for.
4211- `capabilities.capability@1`: optional `sensitive`. Sixteen capabilities with external side effects are marked (money movement, publishing, sending messages, deleting): an agent needs its owner's confirmation for them unless a standing rule covers it.
4212- `network.confirmation-request@1`: a sensitive action waiting for its owner (pending, approved, denied, expired, cancelled; once, session, until, always).
4213- `events.delivery-policy@1`: an event type's delivery class (realtime_ephemeral … webhook), durability, per-key ordering, latency targets, retention tiers, routing objective, batching, residency and a payload ceiling of 64 KB.
4214- The fabric (`platform.*`, first-party): `resource-offer@1` (a node's or provider's capabilities, multidimensional capacity, latency, health, pricing), `workload-requirements@1`, `placement-result@1` (the explain answer), `placement-plan@1` (signed, expiring route plans), `rate-card@1` (a provider price in its real unit, with its free allowance, source and verification date), `provider-state@1` (usage, forecast, reserve), `cost-snapshot@1` (with counterfactuals), `capacity-snapshot@1`.
4215- The resource index: `common.resource-summary@1` and `common.resource-list-result@1` (GET /api/v1/resources in every service); `common.resource-cost@1` (a charge in weighted cost units with an idempotency key).
4216- Fixtures for each, and the regenerated OpenAPI and JSON Schema bundle.
4217
4218## 0.76.0 — 2026-09-28
4219
4220**The node registry** (ADR-034 section 12; roadmap WS-X1).
4221- `network.node@1`: one machine of the platform as the registry lists it: its roles (web, app, data, media-worker, ingest, edge-probe, edge-relay, edge-cache, gpu, staging, ci), region-level location (region, country, optional city and coordinates), provider, an HTTPS beacon clients time for their round trip, and health. No addresses, capacity or secrets are public.
4222- `network.node-report-request@1` and `network.node.report` (internal, held by Host): `POST /internal/nodes/report` sends the complete set of nodes one inventory knows. A node absent from a later report of the same source is marked down, never silently deleted.
4223- `network.node-list-result@1`: `GET /api/v1/nodes` (public, `?role=`, `?region=`), the input of openvibe-sdk/geo's `nearest()`.
4224
4225## 0.75.0 — 2026-09-28
4226
4227**Per-streamer AI budgets are AI quotas** (roadmap WS-O task 2).
4228- `ai.quota.attribution.manage` (first-party): a service caps what runs attributed to one of its own entities may cost or request per hour or day (`PUT /api/v1/attribution-quotas/{attribution}`, `ai.attribution-quota-put@1`, optionally only for workflows under a prefix). It reads the cap with what the window has used (`ai.attribution-quota@1`) or removes it. The attribution's service must be the caller: Live caps `live:user:<id>`, a streamer's daily AI-viewer budget. A run over the cap is refused 429 `quota.exceeded` before any provider is called.
4229
4230## 0.74.0 — 2026-09-28
4231
4232- `ai.credential-put@1`: `api_key` is optional after the first put. The stored key is kept for a change of models or budget, but must be entered again to change `provider` or `base_url`, so a key never follows a new endpoint on its own (400 `credential.key_required` otherwise). Roadmap WS-O task 2.
4233
4234## 0.73.0 — 2026-09-28
4235
4236**A person's own provider key lives in OpenVibe.AI** (roadmap WS-O task 2).
4237- `ai.credential.manage` (first-party): the service that holds a person's consent (Live, for a streamer's AI viewers) stores their key at `PUT /api/v1/credentials/{subject}` (`ai.credential-put@1`: provider openai or anthropic, an https `base_url`, the key, models per role, and an optional `budget_usd_per_day`). It reads it back without the key (`ai.credential@1`, a four-character hint and today's spend) or deletes it. Only the storing service uses or changes a credential.
4238- `ai.run-request@1` gains the optional `credential { subject }`. The run calls that provider with that key only: no fallback, never cached, the shared paid budget untouched, and the credential's own daily budget enforced. Chat operations only.
4239
4240## 0.72.0 — 2026-09-27
4241
4242**Mod principals in Network** (roadmap WS-M task 3, ADR-013).
4243- `mods.grant.manage` is active. A runtime (OpenVibe.Games) registers an install's principal `mod:<mod_id>` (`POST /internal/mods`, `network.mod-install-request@1`: the manifest, and the subset staff approved at install; the rest stays pending). It then approves or revokes one capability (`POST /internal/mods/{mod_id}/grants`, `network.mod-grant-change@1`) or revokes the install (`POST /internal/mods/{mod_id}/revoke`). It reads them with `GET /internal/mods[/{mod_id}]`. Only the owning runtime or Network staff (`staff.games.manage`) change a mod.
4244- `network.mod-principal@1`: the principal with requested, approved, pending and revoked capabilities, and a revision.
4245- `network.mod.grants_changed@1` (internal): after every change, the complete approved set (by revision), the change, and whether the runtime or staff made it. The owning runtime sets its copy to it. Games lists it as consumed.
4246
4247## 0.71.0 — 2026-09-27
4248
4249**Account export and deletion** (roadmap WS-B task 7, ADR-033).
4250- `network.account.export_requested@1` (internal): a person asked for a copy of their data. Each service that keeps data about people pushes its part to `POST /internal/account-exports/{export_id}/parts` (`network.account-export-part@1`: JSON files of the subject's own rows, at most 20 MB) with the new capability `network.account.export.contribute`, before the deadline (30 minutes).
4251- `network.account.deleted@1` (internal): the 30-day grace ended and Network erased what it owns. Each service erases its rows once per `deletion_id`, as follows:
4252 - authored content goes, except items with others' replies, which stay as authorless tombstones;
4253 - votes go, and counts are recomputed;
4254 - money rows stay, pseudonymised, and held media stays.
4255
4256 It then confirms at `POST /internal/account-deletions/{deletion_id}/confirmations` (`network.account-deletion-confirmation@1`, counts only) with `network.account.deletion.confirm`. `aliases` names subjects merged into the account earlier.
4257- `network.account-export@1` (the job the person sees: pending, ready, partial, expired or failed, with each service's state), `network.account-deletion@1` (scheduled, cancelled or deleted), and `network.account-data-receipt@1` (Network's answer to a part or confirmation).
4258- Live, Chat, Community, Media and Games list both events as consumed.
4259
4260## 0.70.0 — 2026-09-27
4261
4262**Account merge, the revocation reason and module policy** (roadmap WS-B task 5, ADR-029).
4263- `network.user.token_valid_after` gains the reason `account_merged`: a folded-in account's tokens end when it merges (its sessions moved to the survivor). Consumers treat every reason the same.
4264- `modules.namespace@1`'s description follows ADR-029. When both accounts have a record in a namespace, the survivor keeps its own and gains only the top-level fields it lacks; its values always win. Before, the absorbed record was simply dropped.
4265
4266## 0.69.0 — 2026-09-27
4267
4268**Account merge** (roadmap WS-B task 5, ADR-029).
4269- **`network.subject.merged@1`** (event, first-party, visibility internal): `{ merge_id, from, into, merged_at, initiated_by, split_until? }`. `from` is now an alias of `into`. Network has moved what it owns (providers, sessions, OAuth grants, developer projects, OpenCoins, user modules) in the transaction that queues it. Each service repoints its own rows from `from` to `into`; a row it cannot move keeps the survivor's and drops the other, counted. Apply once per `merge_id`. Listed in Network's manifest `eventsProduced`.
4270- **`network.account-merge-result@1`**: the answer of a merge, what Network moved as counts, and `replayed` for a retried merge.
4271- **Staff map 1.2.0: `staff.identity.merge`** (owner, since 1.2.0): an account-recovery merge with a written reason and an audit row. People merge their own accounts without it, signed in to both. An owner token issued from map 1.1.0 holds it by role.
4272
4273## 0.68.0 — 2026-09-26
4274
4275**Creator analytics from events** (roadmap WS-E task 6).
4276- **`live.stream.ended` gains an optional `stats` object:** peak and average viewers, unique chatters, messages and watch minutes. It holds counts only, never who.
4277- **New schema** `network.creator-analytics-result@1`: a creator's daily and per-stream analytics, built on Network from `live.stream.ended`.
4278- **New capability** `network.analytics.creator.read` (first-party): the full figures for Live's creator dashboards. Streams, minutes and peak viewers are public.
4279
4280## 0.67.0 — 2026-09-26
4281
4282**Products write follows on a person's behalf** (ADR-030 step 4).
4283- **New capability** `network.follows.write` (first-party, never for apps): PUT and DELETE `/internal/follows/:type/:target` on Network, with the follower named in the request.
4284- **New schema** `network.follow-write-request@1` (`follower`, `notify_email?`, `notify_push?`). Live's follow buttons use it, and Live keeps its table as a projection of `network.follow.*`.
4285
4286## 0.66.0 — 2026-09-26
4287
4288**Incidents and maintenance on the status page** (roadmap WS-N task 12).
4289- **New schemas** `network.status-incident@1` (an incident or maintenance window: kind, title, severity, state, services, start and end, updates), `network.status-incident-list@1` (public: `active` and the last 30 days' `recent`) and `network.status-incident-request@1` (open one, or add an update).
4290- **New capability** `network.status.incident` (internal, never for apps). It covers POST /api/v1/status/incidents and /:id/updates, for staff admins and the Host principal (`ovhost incident`, `ovhost maintenance`).
4291- ADR-032 (containers for platform services) is accepted: services stay systemd units.
4292
4293## 0.65.0 — 2026-09-26
4294
4295**The follow graph on Network** (roadmap WS-E task 4, ADR-030).
4296- **New event types** `network.follow.created` and `network.follow.deleted` (subject visibility for the follower). Their payloads carry `follower`, `target_type` (`channel` today: a Live channel named by its owner's subject), `target_id`, the notify flags, a per-pair `revision`, and for a delete a `reason`. Products keep projections they can rebuild.
4297- **New schemas** `network.follow-status-result@1` (the public follower count, plus the caller's own follow when signed in) and `network.follow-list-result@1` (a page of follows, never public).
4298- **New capability** `network.follows.read` (first-party, never for apps): who follows a target, for notifications and projections.
4299
4300## 0.64.0 — 2026-09-26
4301
4302**Wiki VIP spaces and pages** (roadmap WS-K task 8).
4303- **`vip` joins Wiki's visibilities** (between `members` and `private`). It covers `wiki.space@1`, `wiki.page@1`, `wiki.space-write-request@1`, `wiki.page-write-request@1` and the `wiki.page.updated`, `wiki.page.published`, `wiki.page.unpublished`, `wiki.page.deleted` and `wiki.space.updated` payloads.
4304- **Who reads it:** a `vip` space or page is read by the space's roles and by the viewers OpenVibe.VIP admits as members of the space owner. OpenVibe.Wiki asks `vip.resource.policy.evaluate` with the resource `wiki/page/<id>` when the page itself is VIP-only (else `wiki/space/<id>`), and the fallback `{ requirement: 'member', binding: 'wiki:gated_page' }`.
4305- **Where it never appears:** in search, sitemaps or feeds (its index document is a tombstone, like `members`).
4306- **Official spaces** have no VIP owner, so Wiki refuses `vip` there.
4307- Widening only: every earlier value stays valid.
4308
4309## 0.63.0 — 2026-09-26
4310
4311**Project usage rollups** (roadmap WS-N task 4, ADR-014): what feeds the per-project dashboards on OpenVibe.Codes.
4312- **New `common.usage-recorded@1`**: one closed window (an hour or a day) of one developer project's use of one capability in one environment, as the owning service counted it: `project_id`, `env`, `capability`, an optional `dimension` (a job type or tool id), `unit`, `window`, `window_start`, `window_end`, `quantity`, `errors`, `error_codes` (up to 20) and `samples` (up to 10 recent failures: time, code, status, trace id and a job, event, run or object id), plus `revision`. Totals, not deltas: a later rollup with the same key replaces the earlier one. It never names who did the work (no subject, app, address, session, input or message), and no producer emits one per request.
4313- **New event types `tools.usage.recorded`** (a Tools satellite's hour of a project's jobs, unit `jobs`, per `tools.job.create` or `tools.tool.run` and job type or tool) **and `events.usage.recorded`** (Events: `events.app.publish` in `events`, refusals as errors; `events.app.subscribe` in `deliveries`, failed webhook attempts as errors). Both payloads are `common.usage-recorded@1`; envelope subject `{ type: project, id: <project_id> }`, visibility `internal`, priority `low`. The Tools and Events manifests produce them; Network consumes both.
4314- **New `network.project-usage-result@1`**: what `GET /api/v1/projects/:project/usage?days=&env=` on Network answers a project's owner, admins and staff: daily rows and range totals per service, capability, unit and environment, the project's recorded quotas with what their current window used, and errors by code with the recent sampled failures.
4315- `npm test` checks that each `<service>.usage.recorded` is the common payload, owned by its service and consumed by Network, and that a rollup carries no identity and at most ten samples.
4316
4317Additive.
4318
4319## 0.62.0 — 2026-09-26
4320
4321**Operator alerts** (roadmap WS-H task 11; the delivery path that Host's Prometheus alerts lacked).
4322- **New capability `network.operator.alert`** (internal, owner network), implemented by `POST /internal/operator/alerts` on OpenVibe.Network and granted to the Host principal. The request is the complete set of alerts firing now at one source (`prometheus`). Network pages the operator (the owner account) as a critical or high `admin` notification when an alert opens, reminds once a day while it stays open, and sends a resolved notice when it drops out of the set. Being an `admin` notification, it reaches the bell, web push and the realtime topic, and no block hides it.
4323- **New schemas** `network.operator-alerts-request@1` (source, sent_at, up to 200 alerts: fingerprint, name, severity, summary, description, service, started_at; no free-form labels) and `network.operator-alerts-result@1` (firing, opened, reminded, resolved, notified).
4324
4325## 0.61.0 — 2026-09-26
4326
4327**A person's realtime topic and realtime tickets** (roadmap WS-E task 3, WS-F task 1; ADR-005 amendment 2).
4328- **New event type `network.notification.created`**, payload `network.notification.created@1`. Network writes it to its outbox in the transaction that stores a notification. Envelope: subject `{ type: user, id: <recipient usr_> }`, visibility `subject`, actor `system:network`. The payload is the id, type, category, priority, service, `created_at` and the recipient's unread count; never the title, message, link or sender. The Network manifest produces it. "`user:<id>`" in the roadmap is this event type plus subject visibility: a browser subscribes to `network.notification.*` and receives its own events only.
4329- **New `identity.realtime-ticket-claims@1`**: the two-minute, single-use RS256 ticket with which a browser opens Events' `/realtime/stream?ticket=…`. Its claims are `iss <network issuer>/realtime`, `sub <usr_>`, `aud [openvibe.events]`, `typ realtime`, `purpose realtime`, `iat`, `exp` and `jti rtk_…`. Three rules each keep it from passing for a session: the issuer, `typ` and the audience.
4330- **New `network.realtime-ticket-result@1`**: what `POST /api/v1/realtime/ticket` answers. That is the ticket, `expires_at`, `expires_in` (at most 300), `stream_url`, `topics` (Events patterns only, never `user:…`) and `subject`.
4331- The Events manifest's notes name the ticket. There are fixtures for all three contracts, and `npm test` checks that the event never carries notification text or the sender, and that a ticket never has a session's issuer or claims.
4332
4333Additive.
4334
4335Also in this release, ADR-007 amendment 2026-09-26: SQLite recorded as the reviewed store for every service, with Events', Chat's and Billing's measured production load and the thresholds that would move a service to PostgreSQL (WS-S task 1). Documentation only.
4336
4337## 0.60.0 — 2026-09-26
4338
4339**Release manifest 1.2.0** (`registry.release-manifest`, roadmap WS-P task 7, ADR-016 amendment 2). Three optional fields:
4340- `client_generation`: the generation of the client this release serves.
4341- `min_client_generation`: a tab below it reloads at the next safe moment (reason `required`).
4342- `shell`: `{ version, components }`. A tab whose shell differs is prompted, never updated in place.
4343
4344Fixtures cover a full 1.2.0 manifest, a negative generation and a bad shell version. Additive.
4345
4346## 0.59.0 — 2026-09-26
4347
4348**Media namespaces and grants** (roadmap WS-G task 2). Media's grants are five verbs, each one capability checked per namespace: read (`media.object.read`), list, write (`media.object.upload`), delete and transform (`media.derivative.create`).
4349- **New capabilities**, public and active, namespace-scoped: `media.object.list` (object, job, namespace and v1 file lists; answers `media.object-list@1`) and `media.object.delete` (soft delete, restore, v1 file delete; answers `media.object@1`, announces `media.object.deleted`). The Media manifest lists them. Media keeps accepting the older ids for them: `media.object.read` lists and `media.object.upload` deletes and transforms, unless a namespace's policy is `strict_verbs`.
4350- **New contracts** `media.object@1` (an object of the v2 object API, with its `namespace`) and `media.object-list@1` (a page of the object list), with fixtures.
4351- `media.derivative.create` stays planned: its description now says Media accepts it as the transform verb (checked for the job's object's namespace), and it lists the cancel route. `media.lifecycle.read` and `media.lifecycle.transition` say which verbs guard their routes today.
4352- `identity.service-token-claims@1` (description only): a developer app token's `ns` carries its `project_id` and `app.<project_id>.*`; on Media `app.<project_id>` and `app.<project_id>.sandbox` are the project's namespaces. New valid fixture `app-project-namespaces`.
4353
4354Additive.
4355
4356## 0.58.0 — 2026-09-26
4357
4358**Release notifications** (roadmap WS-P task 9, ADR-016 amendment 1). A new event type, **`host.release.published`**, with the payload contract `host.release.published@1` (catalog visibility public). It means a network service's release went live.
4359- **Who publishes it.** OpenVibe.Host's operator plane: `ovhost deploy|rollback`, and `ovhost announce` for services deployed by their own scripts.
4360- **Envelope.** Subject `{ type: release, id: <service>:<release> }` and visibility public. Signed-out browsers get it over Events realtime, and openvibe-shared release-watch (1.17.0, `topics=host.release.published`) checks `/release.json` at once.
4361- **Payload.** `service`, `release` (the `/release.json` release id, with the release manifest's pattern), `commit` or null, `origin` (an http(s) origin) or null, `deployed_at`, and optionally `components` (kind and version only, at most 32) and `rollback: true`. Identifiers only.
4362
4363`host.deploy.activated` also gets its payload contract, `host.deploy.activated@1` (first-party), which is what Host's Stage B already emits for a tenant site's activation: `project_id`, `site_id`, `site`, `deploy_id`, `previous_deploy_id`, `rollback`. It has subject `deploy` and visibility internal. The two types never share a payload, and fixtures check that neither passes for the other. The host manifest lists `host.release.published` in `eventsProduced`. Additive.
4364
4365## 0.57.2 — 2026-09-26
4366
4367**Three decisions** (documentation only): ADR-029 account merge (WS-B task 5), ADR-030 follow graph (WS-E task 4), ADR-031 S3-compatible surface for Media (WS-N task 8). Each is accepted with its acceptance tests; the implementations follow in Network, Live and Media.
4368
4369## 0.57.1 — 2026-09-26
4370
4371**ADR-024 amendment 1** (roadmap WS-E task 2): the theme preference stays Network's own data (not a user module); community themes are reviewed before they are public; theme names and values are allow-listed (shared tokens; colours, numbers, lengths and shadows only); themes import and export as `openvibe-theme@1` files. Documentation only.
4372
4373## 0.57.0 — 2026-09-26
4374
4375**Chat rooms on the realtime plane** (roadmap WS-I task 9). Two event types OpenVibe.Chat produces, with payload contracts:
4376- `chat.room.message.created` — a message in a **public** room, visibility public, so browsers subscribed to `chat.room.*` get it over Events realtime (replay capped by the public window). Private rooms and DMs never emit it; they stay on Chat's WebSocket.
4377- `chat.room.message.deleted` — ids only, with `redacts` (subject_type `chat_room_message`), when a public room's messages are deleted or the room turns private or is archived, so the text stops being replayable.
4378
4379## 0.56.1 — 2026-09-26
4380
4381**ADR-005 amendment 1: presence** (roadmap WS-F task 2). Presence is ephemeral and lives in Chat's delivery plane: room user lists over Chat's WebSocket, and `GET /api/chat/online?users=` for other products; no Events topic carries it, and people hidden by `chat.presence_prefs` (or whose preference is unknown) read as offline. `test/presence-policy.test.js`: no presence event type in any manifest. Documentation and a test; no schema change.
4382
4383## 0.56.0 — 2026-09-26
4384
4385**Loyalty summary and the loyalty-is-never-money test** (roadmap WS-K task 9).
4386- New user-module namespace `live.loyalty` (owner live, private): `channel_points_total`, the top ten `channels` by points (`channel`, `points`), `arena_level`, `arena_xp`, `computed_at`. A summary Live writes; Live's `channel_points` and `arena_trash_levels` stay the truth.
4387- `test/loyalty-policy.test.js` (run by `npm test`): loyalty namespaces are private and carry no money-like field; no `network.coins.*` or loyalty capability withdraws, cashes out, converts or prices loyalty; no `billing.*` capability takes or pays loyalty; the OpenCoins request bodies carry no price. The OpenCoins transfer grant stays revoked in Network (`REVOKED_GRANTS`, ADR-012 rule 5).
4388
4389## 0.55.1 — 2026-09-26
4390
4391**Lifecycle declarations follow the shutdown and fencing fixes** (WS-P task 1 follow-ups). Manifest text only; no schema change.
4392- `tools`: every process, the gateway included, stops through a shared graceful stop: timers, pollers and job workers first, then the HTTP drain (4 s, Connection: close, event streams closed), usage flush, databases and pools, exit 0 within the 5 s already declared. The note about the gateway having no SIGTERM handler is gone.
4393- `games`: `deadlineSeconds` 0 → 10 (the unit allows 30). The stop now refuses new connections and upgrades, stops the simulation and timers, closes every game and editor socket with 1012 after announcing the restart (each close saves that character), saves the world, lets requests finish, awaits the mirror, the progress summaries and the outbox, then closes world.db.
4394- `community`: the Pulse subscription retries, the profile and search-document scans, the Discord relay and the events outbox are now stopped (the work in flight awaited) before community.db closes, within 5 s.
4395- `media`: `leases.claims[0].fencing` is a real fence now: a claim's random `lease_token`, matched by renew, checkpoint, succeed, fail and cancel; a stale holder is refused and counted (`media_job_stale_completions_total`).
4396- `network`: the timers, pollers and the event relay are stopped on SIGTERM, analytics and network.db are closed; requests in flight get Connection: close (8 s at most).
4397- `ai`: the ai.run.* outbox relay is stopped after the runs drain, before the database closes.
4398
4399## 0.55.0 — 2026-09-26
4400
4401**Lifecycle declarations** (roadmap WS-P task 1). `registry.service-manifest@1` gains an optional `lifecycle` block, and every one of the 31 manifests fills it from its service's code and systemd units:
4402- `liveness`: the endpoint (the manifest's `health`) and what a 200 from it proves;
4403- `shutdown`: `signal`, `deadlineSeconds` (the longest the process takes from the signal to exiting, as its own forced-exit timer bounds it), `drains` in order, optional `workers` (worker units that drain on their own, OpenRe's) and a `note` for gaps (the Tools gateway has no SIGTERM handler; Games and Community drain almost nothing);
4404- `startupRecovery.resumes`: what the next start picks up, each as outbox, jobs, sessions, consumer, schedule or state;
4405- `rollback`: `conditions` (automatic and manual), `window` and `blockers` (forward-only migrations, table rebuilds, authority switches);
4406- `contracts.range`: the openvibe-contracts versions accepted, the same as `contractRanges`;
4407- `leases.claims`: what is claimed, by whom, when it lapses and how a stale holder is fenced.
4408
4409A part that does not apply is `{ "none": "<why>" }` (libraries, the Examples repository, retired Realtime, static Sites). `npm test` checks that every manifest declares all six, that a running service's liveness endpoint is its `health` and its shutdown is concrete, that a library declares none for liveness, shutdown and recovery, that `contracts.range` matches `contractRanges`, and that every lifecycle field has a description. `ovhost validate` (OpenVibe.Host) refuses a host service whose lifecycle lacks a field or whose deadline exceeds its unit's TimeoutStopSec. Additive.
4410
4411## 0.54.0 — 2026-09-26
4412
4413**`media.moderation.action`** (ADR-022, WS-D task 1): Media's staff actions on someone else's media, which are retention holds placed or released and staff deletions or visibility changes. The payload is common.moderation-action@1, produced by media and consumed by network.
4414
4415## 0.53.0 — 2026-09-26
4416
4417**Moderation audit events for ten more producers** (ADR-022, roadmap WS-D task 1). **`common.moderation-action@1`** (owner network, public) is one staff or moderator action on someone else's content or account, modelled on `community.moderation.action`: `action` (a short verb id such as `post.hidden`), `target { type, id, owner_subject? }` and `actor_subject` are required; `reason` and `details` are optional; it never carries the content. Events requires an event's prefix to match its source, so each producer gets its own type, a thin schema over the shared one: **`tools.moderation.action`**, **`games.moderation.action`**, **`wiki.moderation.action`**, **`blog.moderation.action`**, **`news.moderation.action`**, **`reviews.moderation.action`**, **`deals.moderation.action`**, **`coupons.moderation.action`**, **`trade.moderation.action`** and **`codes.moderation.action`**. Each service manifest produces its type, and the network manifest consumes all ten into the moderation audit log. Fixtures for each; `npm test` checks that every one is the shared payload and that Network consumes every `*.moderation.action`. Additive.
4418
4419## 0.52.0 — 2026-09-26
4420
4421**`common.config-snapshot@1`** (roadmap WS-C task 7, the configuration model): one immutable revision of one service's configuration namespace (`live.site_settings`, `network.site_settings`, `media.storage_tier`), as `openvibe-shared/config` keeps it and `/api/admin/config` shows it. It carries service, namespace, a revision that grows per namespace and the previous one, a state (`proposed`, `active`, `superseded`, `rejected`, `rolled_back`), the values with every secret-class key as `{ redacted: true, fingerprint }` (an HMAC-SHA256 of the value under a secret key the service keeps per namespace: equal fingerprints within a namespace mean the value did not change, and the value cannot be recovered or guessed offline without the key), a `public`/`internal`/`secret` classification per key, a sha256 checksum over the canonical JSON of the values as shown (secrets as their markers, so anyone can check it and it reveals nothing more), who created and activated it and when, a reason, the rejection error, and `copied_from` for a rollback. A rejected revision names its error; an active, superseded or rolled-back one names when it became active. Fixtures for an active revision with a redacted secret, an imported first revision, a rejected tiering change, a rollback and a proposal; an unkeyed `sha256` marker is invalid. Additive.
4422
4423## 0.51.0 — 2026-09-25
4424
4425**OpenAPI 3.1 per service** (roadmap WS-C task 6): `generated/openapi/<service>.json` for each of the 24 services that own an active capability, 450 operations in all, plus `generated/openapi/index.json`. `lib/openapi.js` (`openapi.buildOpenApi()`, `openapi.index()`, `openapi.document(id)`) builds them from each capability's `implementedBy` routes and its input and output schemas:
4426- one operation per route, listing the capabilities it performs (`x-openvibe-capabilities`, visibility and quota class), with a bearer token as its security;
4427- a JSON, multipart or binary request body, or query parameters on reads;
4428- a `2XX` response from the output schema, and `application/problem+json` errors;
4429- every schema reached, as a component.
4430
4431The documents are validated as OpenAPI 3.1 in `npm test` (`test/openapi.test.js`, dev dependency `@seriousme/openapi-schema-validator`), and `generate --check` keeps them current.
4432
4433## 0.50.0 — 2026-09-25
4434
4435Capability schemas (roadmap WS-C task 4), starting with Search: **`search.query@1`** (the query string of `GET /api/v1/search` and `/suggest`: q, owner, type, lang, facets, limit, cursor, `facet.<key>`), **`search.query-result@1`** (a page of hits the caller may see, `next_cursor`, facet counts; never an ACL or a total) and **`search.write-result@1`** (`PUT /api/v1/documents/…`: applied or unchanged; stale and conflicting revisions are 409 problems). `search.query.run` and `search.query.delegate` name the first two; `search.document.write` names the third as its output. Fixtures for each. Two conventions so every capability can name schemas: **`common.no-body@1`** (a request whose parameters are the path and query) and **`common.binary@1`** (a response of bytes); **`media.file-upload@1`** is the multipart body of `POST /api/v1/:app/files`. The Media and Tools capabilities name them. **A ratchet**: `test/capability-schemas.test.js` fails on an active capability without an input or output schema unless it is in `compatibility/capability-schema-gaps.json` (162 today), and on a listed gap that has been filled; the list only shrinks. Additive.
4436
4437Every active capability now names both schemas: **the gap list is empty (162 → 0; 178/178 active capabilities complete)**. 275 new request, result and record schemas, each read from the owning service's routes, with valid and invalid fixtures. By owner: **chat** (2: the `/ws/chat` chat frame and its broadcast, the Live bridge batch), **community** (10: paste record, paste create/write/moderate, forum post writes, discussion moderation, Pulse writes), **billing** (19: transaction, balance, cashout, subscription, entitlement and intent records with each capability's request and result), **ai** (7: provider and model records, provider management, usage, template/workflow/route versions), **events** (8: publish result, pull reads and checkpoints, subscriptions, delivery admin), **network** (9), **vip** (26), **tips** (25), **live** (6), **games** (5, including the mod runtime bindings for props and announcements), **openre** (13), **sources** (2), **wiki** (18), **blog** (20), **codes** (2), **host** (10), **news** (24), **reviews** (23), **deals** (15), **coupons** (12) and **trade** (19). Where one capability covers several routes with different bodies, its schema is an `anyOf` of one branch per body. Requests set `additionalProperties: false` only where the service refuses unknown fields. Capabilities whose routes all take no body name `common.no-body@1`. Additive.
4438
4439Seven older capability schema references are corrected to what the routes take and return. `events.event.read` now answers `events.read-result@1` (was the bare envelope). `codes.release.read` answers the new **`codes.release-read-result@1`** (was `codes.app-manifest@1`). `community.paste.create` answers the new **`community.paste-create-result@1`**. `community.post.create` answers the new **`community.post-write-result@1`**, built on the new **`community.forum-thread@1`** and **`community.forum-post@1`** records (both were `common.entity-ref@1`). `community.pulse.write` takes the new **`community.pulse-write-request@1`** (was `common.entity-ref@1`). `games.mod.manage` takes the new **`games.mod-manage-request@1`**, and `games.mod.read` answers the new **`games.mod-read-result@1`** built on the new **`games.mod-view@1`** (both were `mods.mod-manifest@1`). No contract changes shape; only the capability manifests point elsewhere. Additive.
4440
4441The remaining references that did not match their routes are corrected the same way (29 new schemas):
4442- **codes.release.manage** takes **`codes.release-manage-request@1`** (was `codes.app-manifest@1`: the body wraps the manifest with kind, notes and publish; deprecate and revoke take a reason).
4443- **community.pulse.read**, **community.space.read** and **community.thread.read** answer **`community.pulse-read-result@1`**, **`community.space-read-result@1`** and **`community.thread-read-result@1`**, with the new **`community.pulse-item@1`** and **`community.forum-space@1`** records. Each also covers its HTML pages and RSS feeds. All three were `common.entity-ref@1`.
4444- **community.comment.write** takes **`community.comment-write-request@1`** and answers **`community.comment-write-result@1`**, with the new **`community.comment-thread@1`** and **`community.comment@1`** records. Both were `common.entity-ref@1`.
4445- **sources.item.read** and **sources.source.read** answer **`sources.item-read-result@1`** and **`sources.source-read-result@1`**: one branch per route, lists and single records.
4446- **ai.run.read** answers **`ai.run-read-result@1`**. **ai.run.create** takes **`ai.run-create-request@1`** (a run request, a direct operation's input, citations, or no body) and answers **`ai.run-create-result@1`** (`{ run }` or `{ citations }`, not the bare run), with the new **`ai.run-citation@1`**.
4447- **events.event.publish** and **events.app.publish** take **`events.publish-request@1`**: one envelope, or `{ events: [...] }` of 1 to 100.
4448- **identity.subject.resolve** takes **`identity.resolve-request@1`** and answers **`identity.resolve-result@1`** (**`identity.subject-projection@1`**, or `{ results }` for a batch). They were `identity.legacy-identity-map@1` and `identity.subject-ref@1`.
4449- **network.modules.write** takes **`network.module-write-request@1`** (`{ data }`; the answer stays `modules.module-record@1`).
4450- **media.object.read** takes no body and answers **`media.file-read-result@1`** (the file's metadata, or its bytes on `/f/:key`). **media.object.upload** answers the new **`media.file@1`** (Media answers a file record, not a `media.media-ref@1`).
4451- **search.query.run** and **search.query.delegate** answer **`search.read-result@1`**: search, suggestions, or one document. **search.document.write** takes **`search.document-write-request@1`** and answers **`search.owner-result@1`**: write results, reconciliation pages, the stored document, rejections.
4452- **tools.tool.read** answers **`tools.tool-read-result@1`** (the list, one tool, or its schema document). **tools.job.create** takes **`tools.job-create-request@1`**: retry and references take no body. **tools.job.read** answers **`tools.job-read-result@1`**: the job, or a result file's bytes. The Tools assertions in `test/run.js` name the new ids.
4453
4454No existing contract changes shape; only the manifests point elsewhere. Additive.
4455
4456## 0.49.0 — 2026-09-25
4457
4458Platform blocks (roadmap WS-E task 5). **`network.block.changed`**: a person blocked or unblocked someone (`blocker`, `blocked`, `active`, a per-pair `revision`); Network keeps the blocks, keyed by subjects, and Chat and Community consume the event. New capability **`network.blocks.read`** (first-party, never for apps): `GET /internal/blocks?subject=` lists who a person blocked and who blocked them. Fixtures for a block and an unblock. Additive.
4459
4460## 0.48.0 — 2026-09-25
4461
4462**Correction to 0.47.0.** `network.grant.changed` was already emitted by Network's developer event relay for a developer app's grant, and OpenVibe.Events acts on it (it stops an app's subscriptions when its `events.app.subscribe` grant leaves approved). 0.47.0 gave that event a service-principal payload that does not match. Now `network.grant.changed` describes what is actually sent: `{ project_id, capability, audience, from, to }`, subject `app`. A first-party service principal's grant change is the new **`network.principal_grant.changed`** (the 0.47.0 payload under its own name). Nothing consumed the 0.47.0 shape. The compat gate records this in `compatibility/corrections.json` (accepted against v0.47.0 only).
4463
4464## 0.47.0 — 2026-09-25
4465
4466**`network.grant.changed`** gets a payload contract (roadmap WS-D task 3; corrected in 0.48.0: that shape is `network.principal_grant.changed`): a service principal's capability grant was given, changed (namespaces or expiry), revoked by the owner, or expired, with actor and reason. Network writes it beside an audit row in the transaction that changes the grant; the seeded defaults are not announced. New capability **`network.staff.read`** (active, first-party, never grantable to apps): list the network's staff with their roles and staff-map capabilities, `GET /api/v1/staff/moderators` (WS-D task 4). Fixtures for a grant and an expiry. Additive.
4467
4468## 0.46.0 — 2026-09-25
4469
4470**`live.moderation.action`** (ADR-022, roadmap WS-D task 1): a staff or channel-moderator action taken on OpenVibe.Live outside chat (site, global and IP bans, message deletes and purges from the admin panel, a stream force-ended, relay users hidden, channel moderators added or removed), with the same payload as `chat.moderation.action`. Events requires an event's prefix to match its source, so Live cannot send Chat's event for its own admin actions. OpenVibe.Network consumes it into the moderation audit log. The live manifest produces it and the network manifest consumes it. Fixtures cover a site ban and a force-ended stream. Additive.
4471
4472## 0.45.0 — 2026-09-25
4473
4474**`live.index_document.upserted|deleted`** also carry Live's public VOD and clip pages (types `vod` and `clip`, id = the Media id, canonical `openvibe.live/vod/<id>` and `/clip/<id>`), alongside channels. Live owns those canonical pages (title, channel, AI overview, transcript), so Live sends their Search documents. `media.index_document.*` is only for VODs and clips whose canonical page is on openvibe.media (apps other than Live), the same rule as Media's sitemap. Fixtures for a VOD, an AI clip (noindex) and a VOD tombstone. Additive.
4475
4476## 0.44.0 — 2026-09-25
4477
4478Search 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.
4479
4480## 0.43.0 — 2026-09-25
4481
4482**`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.
4483
4484## 0.42.0 — 2026-09-25
4485
4486The service manifests carry what Network's registry and site list used to hard-code (roadmap WS-C task 1, "manifest-derived registry"):
4487
4488- **`internalOrigin`**: the loopback address a running service answers on, which the registry polls. An `OV_<ID>_INTERNAL_URL` loopback override can still replace it.
4489- **`exposure`**: where the service can be reached today. `state` is live, internal, library, repository, placeholder or retired; `publicSite` says what the public domain answers (the service, a placeholder, or nothing); there is an optional `note`; libraries also give `package` and `repo`. This is separate from `status` (maturity).
4490- **`site`**: how a site is presented, with `name`, `icon`, `tagline`, `what`, `legalProfile` (the legal wording of /terms, /privacy, /dmca), `position`, and `host` for a site without a public origin. A service without `site` is not a site.
4491- **`ready`** is added to the network, media and games manifests (`/api/ready`).
4492
4493The values are exactly what Network hard-coded. A service going public is now one manifest edit here. The test requires every first-party manifest to have an exposure, every running service to have a unique loopback port, libraries to name their package and repository, and site positions to be unique. The additions are optional in the schema, so this release is additive.
4494
4495## 0.41.1 — 2026-09-25
4496
4497Plain-language descriptions for `ai.preferences`, `chat.preferences`, `games.progress.summary` and `live.profile`. my.openvibe.network now shows these descriptions to people on its AI & Data tab. No schema change.
4498
4499## 0.41.0 — 2026-09-25
4500
4501User modules, the rest of D06 (roadmap WS-B task 9):
4502
4503- **Field-level read rules.** A namespace may list `readers`: `{ service: [fields] }`. A service other than the owner that reads a record (with `network.modules.read`) sees only the public fields and the fields listed for it. `modules.serviceView(namespace, service, data)` applies the rule; Network's service read applies it.
4504- **Version migration.** A namespace may list declarative `migrations` (`{ from, to, rename, drop, defaults }`). `modules.upgrade(namespace, data, version)` brings a stored record to the current version. Network upgrades a record when it is read and stores it at the current version on the next write. The contract test requires a path from every earlier version.
4505- **New namespaces:**
4506 - `chat.dm_settings`: new conversations from everyone or nobody, group invites, previews;
4507 - `chat.presence_prefs`: whether the person is named in chat user lists;
4508 - `live.stats`: 30-day streaming summary;
4509 - `ai.usage_summary`: 30-day AI runs on the person's behalf;
4510 - `community.profile`: threads, posts, comments, pastes, first and last activity;
4511 - `wiki.projects`: spaces the person owns or edits, where only public ones are named.
4512- **`chat.tts_defaults` v2**, now owned by Chat. Its fields are the settings Live's chat panel actually has: `send`, `send_while_live`, `volume`, `sounds`, `sound_volume`, `sources`. v1 (voice, rate, muted) was never written, and a v1 record upgrades to an empty v2 record.
4513- **`tools.usage` v2** adds `favorites` (unique tool ids, at most 24). The person may write it; every v1 record is valid v2.
4514- **`ai.preferences`** is readable by `ai` (all five fields).
4515- The chat and ai service manifests list their new namespaces.
4516
4517## 0.40.0 — 2026-09-24
4518
4519The chat manifest names its own domain: **openvibe.chat** (`domains`, `publicOrigin`). OpenVibe.Chat serves the site itself (global chat, messages, settings, sign-in with the Network), and Network's first-party CORS list, which comes from these manifests, now includes it. Additive.
4520
4521## 0.39.0 — 2026-09-24
4522
4523**`network.user.token_valid_after`** (revocation propagation, roadmap WS-B task 4): when a person's tokens stop being good (a password change or reset, sign out everywhere, a ban, an account deletion or staff ending their sessions), Network moves their cutoff and emits this event in the same transaction. Every service that accepts Network user tokens refuses one whose `iat * 1000 < Date.parse(valid_after)` (Network's own rule), drops what it cached for those tokens and closes the sockets they opened. Consumers keep the latest cutoff per subject. Network produces it; Chat, Community, Live, Media, Tools and Games consume it. Fixtures cover valid and invalid payloads. Additive.
4524
4525## 0.38.0 — 2026-09-24
4526
4527Staff map 1.1.0 (ADR-022), so the content products and Games can check staff capabilities instead of comparing role names:
4528
4529- **`staff.content.moderate`** (global_mod): moderate what people publish on Blog, Deals, Coupons, Codes and Host.
4530- **`staff.editorial.manage`** (admin): the network's own publications: the official blog and wiki spaces, News stories, Reviews entities, Trade context, Coupons merchants.
4531- **`staff.games.manage`** (admin): the Games map editor and mod administration.
4532- **`since` and the `staff_map` claim.** Capabilities record the map version that added them, and Network issues `staff_map` with `staff_caps`. `staff.can()` judges a capability newer than a token's map by the token's role, so an addition reaches existing tokens (which live for days) at once. What a token was issued still wins for everything its map knew.
4533
4534Additive.
4535
4536## 0.37.0 — 2026-09-24
4537
4538`network.integration.github.read` (first-party only) lets a service read the network's GitHub API token. The owner sets the token in Network's admin panel, or in `GITHUB_TOKEN`. OpenVibe.Blog's network changelog uses it, so its GitHub calls do not share the host's anonymous rate limit. It is never granted to apps or mods. Additive.
4539
4540## 0.36.0 — 2026-09-24
4541
4542The moderation audit log (ADR-022):
4543
4544- **`chat.moderation.action`** now has a payload contract, matching what OpenVibe.Chat already sends for chat and Live moderation.
4545- **`community.moderation.action`** is new: staff actions on other people's content in Community.
4546
4547OpenVibe.Network's manifest consumes both, plus `tips.interaction.moderated` and `billing.staff.action`, for the audit log staff can read in admin. Fixtures cover valid and invalid payloads. Additive.
4548
4549## 0.35.0 — 2026-09-24
4550
4551- OpenVibe.Community publishes events: `community.paste.created|updated|deleted`, `community.thread.created`,
4552 `community.post.created`, `community.comment.created` (payload contracts with fixtures; the community manifest
4553 0.2.0 lists them). Payloads carry ids, owner or author subject, visibility and the public URL, never a body,
4554 title or content: consumers (Search, Pulse, Live's Content feed) read the item itself.
4555
4556## 0.34.3 — 2026-09-24
4557
4558- `openvibe-contracts-check` skips `*.test.*` and `*.spec.*` files: tests mint tokens carrying other owners'
4559 capabilities on purpose, and repositories that keep tests next to the code (Games) could not run the check.
4560
4561## 0.34.2 — 2026-09-24
4562
4563- Fixture fix: the valid mod-manifest 1.1 example (`market-stall-1.1.json`) asked for the first-party
4564 `vip.entitlement.check`, which is never granted to apps or mods; it now asks for the public `vip.perk.list`.
4565
4566## 0.34.1 — 2026-09-24
4567
4568- `tools.tool.run` and `tools.net.probe` are **active**: the run API (`POST /api/v1/tools/:id/run`) and the gateway
4569 jobs facade shipped in OpenVibe.Tools 5ac8309 and are deployed. The SDK v0.6.0 tools client passes against them.
4570- `tools.run@1` lists the problem codes the run API emits beyond 0.33.1's: tools.input.too_large (413),
4571 tools.run.timeout (504), tools.origin.refused (403), tools.session_required (401), tools.run.file_not_found (404),
4572 tools.run.failed (500). Additive; no schema change.
4573
4574## 0.34.0 — 2026-09-24
4575
4576Additive: `compat.js` reports no breaking change against v0.33.1. Closes the Contracts rows of the
4577roadmap completeness audit (§28.3, §30.2, W1 D7, W12, W22).
4578
4579**51 event payload contracts**, all `active`: every one is emitted by its producer's code today.
4580Each was read from the emitter and its call sites. News, Reviews and Deals were also checked against
4581envelopes captured from their own code, and Trade against its one production outbox row.
4582
4583- News (11): `news.source.ingested|failed`, `news.cluster.updated`,
4584 `news.story.created|flagged|published|updated|unpublished|retracted`, `news.index_document.*`.
4585- Reviews (9): `reviews.entity.merged|split`, `reviews.signal.added|removed`,
4586 `reviews.summary.published|updated|unpublished`, `reviews.index_document.*`.
4587- Coupons (8): `coupons.coupon.created|updated|expired|disabled`, `coupons.report.created`,
4588 `coupons.confidence.changed`, `coupons.index_document.*`.
4589- Deals (6): `deals.offer.created|updated|expired`, `deals.vote.changed`, `deals.index_document.*`.
4590- Trade (5): `trade.observation.created`, `trade.source.stale|recovered`, `trade.index_document.*`.
4591- Games (10): `games.player.joined|left`, `games.skill.leveled`, `games.blueprint.unlocked`,
4592 `games.world.saved`, `games.mod.installed|enabled|disabled|grants_changed|revoked`.
4593- Media (2): `media.object.deleted` and `media.object.visibility_changed` (OpenVibe.Media 039dc48).
4594 Triggers stage them in the transaction that changes the object, and the outbox writes them there.
4595 They carry identity and state only: never the title, owner, storage keys or size. A
4596 visibility change never repeats the value. The media manifest now lists both.
4597
4598Every `*.index_document.upserted` is a `search.index-document@1` with the owner fixed. Every
4599`.deleted` is a `{ type, id, revision }` tombstone.
4600
4601Community lists no `eventsProduced`, because it emits nothing yet, so there is no `community.*`
4602contract. 29 listed events still have no contract:
4603
4604- chat: 3
4605- codes: 3
4606- host: 4
4607- media: `vod.*`, `clip.*`, `object.uploaded` and `storage.*`, 7 in all
4608- network: 5
4609- openre: 7
4610
4611Found while reading the producers (fixes belong in those repos):
4612
4613- **News drops some flag events.** `stories.js:238` sends `priority: 'normal'` for `source_updated`
4614 flags. The envelope allows only `critical|important|low`, so Events refuses them.
4615- **Coupons can publish service notes.** A calling service's note is copied into the public event's
4616 `reason`.
4617- **Deals under-reports changes.** On the importer paths, `changed` can leave out a `product_id` or
4618 `expires_at` change.
4619
4620**ADR amendments** (dated 2026-09-24):
4621
4622- **ADR-003, delegated authorization.**
4623 - Who may name the acting person, and the rule that a call gets the intersection of the app's
4624 grants, the approved scopes and the person's own rights.
4625 - Staff power and money are never delegated. Tokens last 5 minutes and cannot be refreshed. Audit
4626 names both the app and the person.
4627 - The approval UX in force today, and what Network still owes: the capability list on the chooser,
4628 stored authorizations, and connected apps with revoke.
4629- **ADR-006:**
4630 - four placement classes: canonical, hot cache, asset origin, local scratch;
4631 - `local` as the first-class dev provider;
4632 - the infrequent-access tier deferred at 2,839 objects / 481 GB.
4633- **ADR-007:**
4634 - PgBouncer transaction pooling;
4635 - replicas only for reads that tolerate lag;
4636 - SERIALIZABLE plus ordered row locks and 40001 retries on money paths;
4637 - Redis never authoritative.
4638- **ADR-012:**
4639 - The roadmap's ledger names mapped to Billing's transaction types and legs: platform fee,
4640 creator earning, payout hold and release, compensating reversals.
4641 - OpenCoins stays in Network. This supersedes the Wave 8 line "Network's OpenCoins wallet becomes
4642 a Billing client".
4643 - Billing's `cashouts`, reversal transactions and VIP plans replace the roadmap's `payouts`,
4644 `refunds` and `plans` tables.
4645- **ADR-013:**
4646 - Package signing and review are named as open owner decisions.
4647 - Mod monetization goes only through Billing and VIP primitives.
4648 - The manifest 1.1.0 fields (below).
4649- **ADR-021, extraction decided.** There is no analytics service. Analytics stays per service through
4650 `openvibe-shared/analytics`, and the schema stays in Shared. The decision rests on measured volume:
4651 Live has 1.78M raw events in 30 days (58k a day, 502 MB). The ADR names the triggers for a revisit.
4652- **ADR-022, the Wave 12 revisit.** The decision stands. The ADR names the trigger for the next
4653 revisit.
4654
4655**Realtime is `retired`** (ADR-005), not a placeholder. A retired manifest offers no domain,
4656capability, event, namespace or health path.
4657
4658**Staff capability map** (W1 D7, ADR-022): a new contract, `policy.staff-role-map@1` (owner `network`), and the map
4659in force, `manifests/policy/staff-roles.json`.
4660
4661- **Roles:** `user < streamer < global_mod < admin < owner`. `owner` is never a stored role: it is
4662 `role: admin` plus the `is_owner` claim. `user` and `streamer` hold no staff capability.
4663- **32 `staff.<area>.<action>` capabilities**, each with the lowest role that holds it:
4664 - 12 for `global_mod`, including `staff.moderation.chat|calls|channels|bans|ip|logs|bypass|pastes|discussions`,
4665 `staff.content.view_private` and `staff.content.hide`;
4666 - 15 for `admin`, including `staff.users.manage`, `staff.roles.assign`, `staff.site.view|configure`
4667 and `staff.streams.end|manage`;
4668 - 5 for `owner`: `staff.roles.grant_admin`, `staff.secrets.manage`,
4669 `staff.money.freeze|cashouts` and `staff.loyalty.grant`.
4670
4671 Each lists the file:line role checks it replaces in Live (210 sites inventoried), Chat, Community,
4672 Network and Billing.
4673- **Local powers:** channel and self powers stay with the product and are not staff capabilities.
4674 They are listed under `local`.
4675- **Claims** that Network issues: `role`, `is_owner` and `staff_caps`.
4676- **Rules** that a capability alone does not express:
4677 - rank and owner protection;
4678 - no staff power in service, app or mod tokens, and none through delegation;
4679 - vouching only with the moderate capability;
4680 - roles change only in Network;
4681 - every action is reported to the moderation log.
4682- **`contracts.staff`:** `roles`, `effectiveRole`, `atLeast`, `capabilitiesOf` and `can`. Issued
4683 `staff_caps` win over the role. A family grant (`staff.moderation.*`) stays inside one area, and
4684 there is no `staff.*` wildcard.
4685- **Adoption comes later:** Network issuing the claims, and Live, Chat and Community replacing
4686 their raw role checks.
4687
4688**Capability catalog gaps** (roadmap §30.2), 15 capabilities checked against each service's routes
4689and production:
4690
4691- **Active:** public reads that production serves to anyone:
4692 - `live.channel.read`, `live.stream.read` and `live.discovery.read`;
4693 - `community.space.read`, `community.thread.read` and `community.pulse.read`;
4694 - `search.query.run`: the public index query, suggest and document read. Service tokens keep using
4695 `search.query.delegate`.
4696- **Planned:** each names its current routes and the id that guards them today:
4697 - `live.owner.resolve`: there is no public route yet; `live.lineage.resolve` stays internal;
4698 - `media.upload.create`, `media.derivative.create`, `media.derivative.read`,
4699 `media.lifecycle.read` and `media.lifecycle.transition`: Media's guard checks
4700 `media.object.upload` / `media.object.read` until it accepts these ids;
4701 - `community.space.manage`;
4702 - `community.vote.set`: value 0 removes a vote, so there is no `vote.remove`.
4703- **New `publishing` library manifest** (openvibe-publishing v0.2.1, ADR-019), with no `publishing.*`
4704 capability. A package has no grant boundary, and the product capabilities (`wiki.*`, `blog.*`,
4705 `news.*`) already cover those routes. Network's registry-exposure test needs a `publishing` entry
4706 before Network moves to this release.
4707
4708**`mods.mod-manifest@1` 1.0.0 → 1.1.0** (roadmap §28.3 m6). Every 1.0.0 manifest stays valid. The new
4709fields are all optional:
4710
4711- `permissions.readGrants` / `writeGrants` split namespace access into read-only and read-write.
4712- `billingHooks`: `[{ kind: entitlement|checkout, key, description? }]`, never a price.
4713- `dependencies`: `[{ id: mod_…, version: <range>, optional? }]`.
4714
4715Games still validates a local 1.0.0 copy.
4716
4717**Manifests:** the Deals notes now say that Network consumes `deals.watch.matched`.
4718
4719## 0.33.1 — 2026-09-23
4720
4721Additive: `compat.js` reports no breaking change against v0.33.0.
4722
4723Follow-ups to the Tools registry, which OpenVibe.Tools now serves in production (`GET /api/v1/tools`,
4724`/api/v1/tools/:id` and `/api/v1/tools/:id/schema` on openvibe.tools and every satellite).
4725
4726**Capabilities and manifests**
4727
4728- `tools.tool.read` is `active` (it was `planned`). The gateway answers for all 169 tools, and the img,
4729 audio, docs, text, yt, maps and food satellites answer for their own. Its description now says what
4730 the routes answer: CORS for any origin, ETag and 304, `$defs.input: false` for a tool without an API,
4731 `400 tools.query.invalid` and `404 tools.tool.not_found`.
4732- `tools.tool.run` and `tools.net.probe` stay `planned` until Tools serves the run API.
4733- Tools 0.4.1: its notes say the registry is served.
4734
4735**`tools.tool@1` 1.0.0 → 1.1.0.** Two optional fields, so every v0.33.0 descriptor stays valid:
4736
4737- `keywords`: the catalogue's search terms (`GET /api/catalog.json` `tools[].keywords`), which
4738 `GET /api/v1/tools?q=` matches beside the id, name and summary. Unique, trimmed, non-empty phrases.
4739- `examples`: `[{ title?, input, files?: [{ name?, mime, url? }] }]`, sample runs that the docs and the
4740 generated OpenAPI document will publish. Each input is valid against the tool's input schema. The
4741 schema refuses examples on a tool without an API.
4742
4743The descriptions now also say:
4744
4745- `output.schema` describes `result.data` whatever the execution. For a job tool, that is the data of
4746 the run's result and of its job's result, which are the same object.
4747- `GET /api/v1/tools/:id/schema` has `$defs.input: false` when `api` is false.
4748- There is no `planned` status. A planned catalogue entry is not a tool: it has no descriptor and is
4749 not listed. Neither is a mirror (a second build of another tool). Both answer
4750 `404 tools.tool.not_found`, with a detail that says the id is planned or names the tool it mirrors.
4751 `tools.tool-list@1` says the same, and that `family`, `execution` and `status` take comma lists.
4752
4753A consumer that validates descriptors against v0.33.0 refuses `keywords` and `examples`
4754(`additionalProperties: false`). Tools should start serving them only after it moves its pin to this
4755release, and so should any service that validates descriptors it reads.
4756
4757**`contracts.tools.checkDescriptor`** now checks each example:
4758
4759- its input against the tool's input schema, when the schema is embedded (errors point at
4760 `/examples/<i>/input/…`);
4761- its size as JSON against `limits.maxInputBytes`;
4762- its files against `files`: the count within `min` and `max`, and each `mime` allowed by `accept`
4763 (`image/*` takes `image/heic`).
4764
4765An input given as `{ $ref }` (the list form) is not fetched, so its examples are checked where the
4766schema is embedded: `GET /api/v1/tools/:id` and the Tools registry test. When there are examples to
4767check, an embedded input schema that does not compile is reported. All 169 of Tools' current
4768descriptors pass, and so do they with their catalogue keywords and their own example inputs added.
4769
4770**Problem codes Tools emits.** They are listed with the routes that answer them, as every service's are
4771(`errors.problem@1` carries any code).
4772
4773- Registry (`tools.tool@1`, `tools.tool-list@1`, `tools.tool.read`):
4774 - `400 tools.query.invalid`: an unknown `execution` or `status` value, or an `api` that is not
4775 `true` or `false`;
4776 - `404 tools.tool.not_found`: an unknown id, and a planned or mirror id, with a detail saying which.
4777- `tools.run-request@1` and `tools.job-request@1`:
4778 - `503 tools.unavailable`: a program or upstream the tool needs is missing. A job submission is
4779 refused then, rather than failing later. `503 tools.tool.unavailable` is still the run API's
4780 refusal for a tool whose descriptor status is `unavailable`.
4781 - Coming with the shared guard, not emitted yet: `429 tools.quota.exceeded` (the caller's allowance
4782 in the quota class is spent) and `503 tools.busy` (every slot for that kind of work is taken).
4783 Both carry `Retry-After`. The run request still lists `quota.exceeded` beside the new code.
4784- Codes a tool chooses, carried as the error of a failed run or job (`tools.run@1`, `tools.job@1`,
4785 `tools.job.failed`): `413 tools.pdf.too_many_pages` (over `limits.maxPages`) and
4786 `422 tools.pdf.wrong_password`.
4787
4788**Fixtures and tests**
4789
4790- The valid png, dns, jsonminify and port descriptors carry keywords and examples, and the list fixture
4791 carries keywords.
4792- New invalid descriptors: an example whose input the tool's schema refuses, an example file that
4793 `files.accept` does not allow, examples on a page-only tool, and a blank keyword.
4794- `test/run.js` checks the `tools.tool` and `tools.tool-list` fixtures with `checkDescriptor` and
4795 `checkList`, not only the schema, so an invalid fixture can break a rule that JSON Schema cannot
4796 express. It also checks:
4797 - that a v0.33.0 descriptor, without the new fields, is still valid;
4798 - each example rule;
4799 - that `tools.tool.read` is `active` while the run capabilities stay `planned`;
4800 - that there is no `planned` status;
4801 - that each new code is a valid problem code and is listed with its status;
4802 - that `tools.quota.exceeded` and `tools.busy` carry `Retry-After`.
4803
4804## 0.33.0 — 2026-09-23
4805
4806Additive: `compat.js` reports no breaking change against v0.32.0.
4807
4808**Tools platform API** (new ADR-027). The tools on openvibe.tools become one registry and one run API,
4809open to the SDK, with tiered, weighted quotas.
4810
4811- `tools.tool@1`: the **tool descriptor**, one per catalogue tool.
4812 - Identity: `id`, `family`, `name`, `summary`.
4813 - `status`: `stable` | `beta` | `preview` | `unavailable`, with `statusReason`.
4814 - How it runs:
4815 - `execution`: `client` | `sync` | `job`.
4816 - `api`: whether the run API exposes the tool.
4817 - `run`: `{ method: POST, path: /api/v1/tools/{id}/run, job: { type, operation, preset? } | null, legacy? }`.
4818 - Its data:
4819 - `input`: a JSON Schema, embedded or `{ $ref }` to `GET /api/v1/tools/:id/schema#/$defs/input`.
4820 - `files`: `{ min, max, accept, maxBytes }` or null.
4821 - `output`: `{ kind: json|file|files|text, schema?, mime? }`.
4822 - `limits`: `timeoutMs`, and optionally `maxDurationSec`, `maxPixels`, `maxPages`, `maxInputBytes`,
4823 `perTargetPerMinute`.
4824 - Access and cost:
4825 - `auth`: `{ anonymous, capability: tools.tool.run | tools.net.probe }`.
4826 - `quotaClass` and `cost` (the relative weight quotas count).
4827 - `egress`: the server fetches a host the caller chose.
4828 - `hosts` and `docs`.
4829
4830 The schema enforces these rules:
4831 - `api: false` has `run: null`, and `api: true` has a run and an input schema.
4832 - Only job tools name a job, and an API job tool always does.
4833 - File output through the API comes from a job.
4834 - A `tools.net.probe` tool fetches and is never anonymous.
4835 - An anonymous egress tool declares `limits.perTargetPerMinute`.
4836 - A client tool never fetches.
4837 - `unavailable` needs `statusReason`.
4838 - JSON output has a schema.
4839- `tools.tool-list@1`: the `GET /api/v1/tools` answer (`tools`, `count`, `updated_at`, optional `families`).
4840- `tools.run-request@1`: the body of `POST /api/v1/tools/{id}/run`, `{ input, files?, wait_ms?, idempotency_key? }`.
4841 It can be JSON or multipart, like the jobs API. `files` references a Media object (`{ media_id }`)
4842 or a result file of the caller's own job (`{ job_id, index }`), so tools can chain. The refusal
4843 codes are listed in the description.
4844- `tools.run@1`: the answer. Either `{ state: succeeded, tool, result: { data?, text?, files? }, took_ms, job? }`,
4845 or `{ state: failed|cancelled, tool, error, took_ms, job? }`, or `{ state: queued|running, tool, job, location }`
4846 (202).
4847- `tools.job@1`: the jobs API's view of a job, read from `apps/_shared/jobs` `system.view()` today.
4848 It carries state, progress, attempts, times, `expires_at`, result files (`storage`, `media`, `url`),
4849 error, retry links and references. It also has an optional `tool`, set when the job came from a
4850 run. `tools.job-request@1` is the body of `POST /api/v1/jobs`.
4851- `contracts.tools` (`lib/tools.js`) adds three helpers:
4852 - `checkDescriptor(d)` applies the schema plus the rules that depend on the id: `run.path` is the
4853 tool's own, `$ref`s point at its own schema, `files.min <= files.max`, `legacy` never lists the
4854 run API, and the quota class has no tier word.
4855 - `checkList(list)` checks every descriptor, that ids and hosts are unique, and that counts are right.
4856 - `jobInput(d, input)` returns `{ ...input, ...preset, tool: operation }`.
4857
4858**Capabilities**
4859
4860- These are `planned` until Tools serves their routes:
4861 - `tools.tool.read`: public, quota class `tools-read`. `GET /api/v1/tools`, `GET /api/v1/tools/:id`
4862 and `GET /api/v1/tools/:id/schema`.
4863 - `tools.tool.run`: public, quota class `tools-run`, `tools.run-request@1` → `tools.run@1`.
4864 `POST /api/v1/tools/:id/run`.
4865 - `tools.net.probe`: **partner**, quota class `tools-probe`. Network grants it only through a
4866 staff-set project allowance, never a default one. It covers port, ping, traceroute, mtr, latency
4867 and bulk header and TLS checks through the API.
4868- `tools.job.create` adds `POST /api/v1/jobs/:id/retry` and `PUT|DELETE /api/v1/jobs/:id/references/:ref`,
4869 and declares `tools.job-request@1` → `tools.job@1`. `tools.job.read` and `tools.job.cancel` declare
4870 `tools.job@1`.
4871
4872**Manifests and statuses**
4873
4874- Tools 0.4.0:
4875 - lists the three new capabilities;
4876 - gains `ready: /api/ready`;
4877 - its notes now say that job results are in Media and job events reach OpenVibe.Events in
4878 production, that the gateway has no jobs routes yet, and what ADR-027 plans.
4879- `tools.job.created|started|succeeded|failed` are `active` (they were `planned`), because Tools
4880 publishes them. Their descriptions no longer say planned.
4881
4882**Tests.** `test/run.js` checks:
4883- every descriptor fixture with `checkDescriptor`;
4884- that a run endpoint exists exactly when `api` is true;
4885- that only job tools name a job;
4886- the egress, probe and client rules, and tier-free quota classes;
4887- that the run capabilities and the descriptor's `auth.capability` agree;
4888- that a run's result files are exactly the job's, and that runs and jobs share the Idempotency-Key
4889 rule and the job type pattern;
4890- that the `tools.job.succeeded` event carries a subset of the job view;
4891- the list's counts, ids and hosts.
4892
4893## 0.32.0 — 2026-09-23
4894
4895Additive: `compat.js` reports no breaking change against v0.31.0.
4896
4897- **Channel/owner lineage resolver** (roadmap §15.10, requirement D20): one resolver for channel, stream,
4898 VOD, clip, Pulse and creator-UI callers. OpenVibe.Live implements it.
4899 - `lineage.resolve-request@1`: any of `slug` (a channel, or `<channel>/<slot>`), `parent_slug`,
4900 `channel_id`, `stream_id`, `slot_id`, `vod_id`, `clip_id`, `media_object_id` (`med_…` or
4901 `legacy:<app>:<kind>:<id>`), `owner_subject` and `legacy_ids` (`live_user_id`, `network_user_id`).
4902 `display_name` is accepted and never used.
4903 - `lineage.resolution@1`: `status` `resolved` with the canonical `channel` (`id`, `slug`,
4904 `owner_subject`, optional `legacy_ids`), whatever of `stream`, `vod`, `clip` and `media_object`
4905 the inputs reached, `resolved_by` (the deciding input), `rule`, `confidence`
4906 (`exact` | `derived` | `legacy_map`), `via` and `checked`; or `status` `unresolved` with a
4907 `reason` (`no_input`, `display_name_only`, `not_found`, `conflict`, `ambiguous`,
4908 `source_unavailable`) and no channel.
4909 - Precedence, in the roadmap's order: explicit slug, nested or parent slug, channel id, stream
4910 lookup (stream, slot), the record's own lineage (clip, VOD), Media lineage, owner subject, legacy
4911 maps. The first input that resolves decides, and every other input that resolves must name the
4912 same channel or the answer is `conflict`. Inside a record the first link that answers wins: a clip
4913 goes to its stream, then its VOD, then the channel recorded on it, never the clipper; a VOD goes to
4914 its stream, then its slot, then the owner recorded on it. A display name alone resolves nothing.
4915- New capability `live.lineage.resolve` (Live, internal): `GET|POST /internal/lineage/resolve`.
4916- **Event payload contracts for events already emitted**, each read from the producer's code and checked
4917 against payloads it builds:
4918 - `tips.interaction.moderated@1` (a paid message filtered, held, hidden or restored, by role; the
4919 deliveries a hide cancelled; never the supporter, message, reason or moderator) and
4920 `tips.interaction.erased@1` (a supporter erased their data; `redacts` takes back the interaction's
4921 earlier events), from OpenVibe.Tips' drafts. New capability `tips.interaction.moderate` (Tips,
4922 internal): the moderation queue and log, hide and restore. The Tips manifest (0.4.0) lists all three.
4923 - `media.job.proposed|queued|started|retrying|succeeded|failed|cancelled@1`: OpenVibe.Media's job
4924 transitions (`server/events.js` `recordJob`), one contract each like `tools.job.*`. The payload is
4925 an event projection of the job (`queue.jobEvent`), every field always present: `id`, `app_id`,
4926 `object_id`, `type`, `status`, `attempts`, `max_attempts`, `error_code` (the stable code only),
4927 `cancel_requested`, `has_result`, and `run_after`, `decided_at`, `created_at`, `updated_at`,
4928 `started_at`, `finished_at` as ISO 8601 UTC (`…Z`) or null. Deliberately left out, because events
4929 travel beyond the tenant: the tenant's `params`, the caller's `idempotency_key`, the free-text
4930 `error`, the `result` (a thumbnail URL, of a private VOD too), `created_by`/`decided_by` and
4931 `owner_user_id` (tenant-local user ids). A consumer GETs the job with a tenant token for those
4932 (`GET /api/v2/:app/jobs/:id`, unchanged); `has_result` says whether there is a result to fetch.
4933 `retrying` carries status `queued`, `started` status `running`; `finished_at` is set exactly on
4934 `succeeded`, `failed` and `cancelled`, `started_at` on everything that ran, `run_after` always on
4935 `retrying`. No service consumed `media.job.*` before this narrowing. The Media manifest (0.2.0)
4936 lists them.
4937 - `live.stream.started@1` and `live.stream.ended@1` (public: stream id, channel username, display
4938 name, URL and user subject when Live knows it, title, category or null, protocol, NSFW flag,
4939 times; `ended` adds `ended_at` and `duration_seconds`) and `live.release.deployed@1` (internal:
4940 head commit, short release, previous head, up to 40 new commits, `deployed_at`, `notes_url`).
4941 - `network.module.updated@1`: one event per change to a user-module record (write, delete by the
4942 person or the owning service, account removal, account merge), with the revision after the
4943 change, the changed field names and only the new values of changed public fields. A deleted
4944 record carries no values; `merged_into` and `merged_from` mark the two sides of a merge. The
4945 Network manifest (0.3.0) produces it and consumes `live.stream.started` (go-live notifications).
4946- `chat.preferences` is owned by `chat` (OpenVibe.Chat since the Wave 6 cutover); the Chat manifest
4947 (0.4.0) lists it in `namespacesOwned`. `chat.tts_defaults` stays with Live. `modules.namespace@1`'s
4948 description says what account removal and merge do to a person's records, apart from `onOwnerRemoved`.
4949- Routes: `host.site.manage` adds the staff takedowns (`POST|DELETE /api/v1/projects/:id/takedown`,
4950 `POST|DELETE /api/v1/sites/:id/takedown`); `wiki.page.create` adds `POST /api/v1/spaces/:space/import`
4951 and `wiki.revision.publish` adds `POST /api/v1/pages/:id/revisions/:n/review`.
4952
4953## 0.31.0 — 2026-09-23
4954
4955Additive: `compat.js` reports no breaking change against v0.30.2.
4956
4957- `registry.release-manifest` 1.0.0 → 1.1.0 (ADR-016, roadmap Track R). Six optional fields, so a
4958 `/release.json` can say what changed and what it still accepts:
4959 - `components`: `{ <id>: { kind: style|content|script|server, version } }`. A tab applies a release
4960 in place only when every component that changed is `style`, `content` or `server`. `shell` is the
4961 catch-all for client code that no other component lists.
4962 - `assets`: `{ "<logical path>": { url, component, integrity? } }`, the content-addressed URL of each
4963 asset this release serves.
4964 - `schema_generation` and `schema_compatible_from` (integers or null): the database schema generation,
4965 and the oldest generation whose code still runs against it. A rollback below the second is not
4966 data-safe.
4967 - `contract_ranges`: `{ <contract id>: { version, accepts: ">=a.b.c <x.y.z", role?: produces|consumes } }`.
4968 A page from release A works against a server on release B when A's version is in B's `accepts`
4969 and B's version is in A's `accepts`.
4970 - `metrics_url`: where tabs POST their update outcome counts (D46).
4971- A consumer that validates manifests against 0.30.x rejects these fields (`additionalProperties: false`).
4972 openvibe-shared ≥ 1.5.0 therefore serves only the fields the service's installed openvibe-contracts
4973 declares. A service starts serving them by moving its pin to this release.
4974
4975## 0.30.2 — 2026-09-23
4976
4977- New capability `live.follower.read` (Live, internal): `GET /internal/followers`, used by OpenVibe.Network's
4978 go-live notifications from `live.stream.started`.
4979- `chat.message.send` is owned by `chat` (was `live`) and is also implemented by Chat's service API
4980 (`POST /internal/live/calls`); it moves from Live's manifest to Chat's.
4981- Live declares `eventsProduced` (`live.stream.started`, `live.stream.ended`, `live.release.deployed`) and
4982 `eventsConsumed` (`openre.session.*`, `media.vod.*`, `media.clip.*`, `media.storage.*`); Media declares
4983 its seven `media.*` event types.
4984
4985## 0.30.1 — 2026-09-23
4986
4987- `billing.cashout.requested|paid|denied`: `cashout.payout_method` carries the method's `type` only
4988 (`additionalProperties: false`). The address (e.g. a PayPal email) stays in Billing and never
4989 travels on the retained event stream. No producer had emitted a cashout event yet.
4990
4991## 0.30.0 (2026-09-23)
4992
4993Additive: `compat.js` reports no breaking change against v0.29.0. No existing contract changed.
4994
4995**Event payload contracts** (ADR-026). Each event type has a contract named after it, with the envelope
4996`version` as its major: ``contracts.validate(`${env.event_type}@${env.version}`, env.payload)``. The files
4997are `contracts/events/payloads/<event_type>.v1.json`, and every one has valid and invalid fixtures. The
4998shapes come from the producers' code.
4999
5000- Chat: `chat.message.deleted` (`message_ids`, and `redacts: { subject_type: chat_message, subject_ids }`, which is required).
5001- Tips: `tips.interaction.ready|failed|cancelled`, `tips.goal.updated`, `tips.overlay.delivered|failed`.
5002- VIP: `vip.plan.published`, `vip.membership.changed`.
5003- Billing: `billing.transaction.settled|reversed`, `billing.entitlement.changed`,
5004 `billing.subscription.canceled`, `billing.cashout.requested|paid|denied`, `billing.staff.action`,
5005 `billing.receipt.external`.
5006- Wiki: `wiki.space.updated`, `wiki.revision.created`, `wiki.watch.triggered`,
5007 `wiki.page.published|updated|unpublished|deleted`, `wiki.index_document.upserted|deleted`.
5008- Blog: `blog.post.created|published|updated|unpublished|deleted`, `blog.schedule.failed`,
5009 `blog.index_document.upserted|deleted`.
5010- Sources: `sources.item.created|updated|removed`, `sources.fetch.failed`,
5011 `sources.index_document.upserted|deleted`.
5012- Search: `search.document.indexed|removed`.
5013- Deals: `deals.watch.matched`. Trade: `trade.alert.triggered`.
5014- **Planned** (catalog status `planned`, not emitted yet): `ai.run.queued|succeeded|failed|cached` and
5015 `tools.job.created|started|succeeded|failed`. Tools job events carry ids, type, owner, state, times,
5016 result locations and errors, never inputs, output data, file names or the anonymous session.
5017- `*.index_document.upserted` payloads are `search.index-document@1`, with the owner and type fixed.
5018
5019**Redaction** (new ADR-026, linked from ADR-004):
5020
5021- `events.redaction-directive@1` is `payload.redacts` (`event_ids` and/or `subject_type` + `subject_ids`, up to 1000 each).
5022- `events.tombstone-payload@1` is what a redacted event's payload becomes.
5023- The ADR documents 403 `events.redaction_not_allowed`, 422 `events.invalid_redaction` and the realtime
5024 public replay window (`REALTIME_PUBLIC_REPLAY_SECONDS`, default 300, `gap` reason `public_window`).
5025- Delivery signature v2 was already documented (ADR-004, README).
5026
5027**AI** (ADR-015):
5028
5029- `ai.run-request@1` is the body of `POST /api/v1/runs`, and `ai.run@1` is the run resource.
5030- `ai.run.create` now declares both as `inputSchema`/`outputSchema`, and `ai.run.read` declares `outputSchema`.
5031
5032**Manifests**
5033
5034- Service manifests:
5035 - chat 0.3.0 produces `chat.message.deleted`.
5036 - tools 0.3.0 produces `tools.job.*`.
5037 - network 0.2.0 consumes `deals.watch.matched` and `trade.alert.triggered`.
5038 - billing 0.3.0 produces `billing.receipt.external`, and tips 0.3.0 consumes it.
5039 - ai 0.2.0 lists its planned `ai.run.*`.
5040- Capabilities: `chat.live_bridge.write` lists `chat.message.deleted`, `tools.job.create` lists `tools.job.*`
5041 and `ai.run.create` lists `ai.run.*`.
5042- Notes corrected:
5043 - Wiki is deployed and public at openvibe.wiki.
5044 - Reviews, VIP and Tips are deployed internally and not launched publicly. Tips also loses the stale "Proposed manifest" line.
5045- SDK, Shared and Examples are `alpha`, no longer `placeholder`: SDK and Shared are released libraries,
5046 and Examples is a repository with CI. Realtime is the only placeholder left.
5047
5048**Tests**
5049
5050- Every payload contract lives at its event type's path, is listed in its owner's `eventsProduced`, fits in an
5051 envelope and rejects a tombstone.
5052- Every consumed event type (wildcards included) has a producing manifest, and each type has one producer.
5053- The directive's limits are checked.
5054- Generated TypeScript declares every type it references.
5055