openvibers/openvibe.contracts Commits

Add ADR-046 fabric decision, user-owned trust rule and two products (#22)

OP OpenVibers committed 3 Oct 2026 · c7c375a6d6 · 42 files, +320 −62

local checks ✓ 3/3 · CI ✓ 3/3 · review SHIP by OpenCode Glm 5.3 (QUALITY=high)

https://github.com/OpenVibers/OpenVibe.Contracts/pull/22

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex a60dd572..65c41560 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,7 +4,26 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
--## Unreleased
++## 0.88.0 — 2026-10-03
++
++**The Fabric ADR and the user-owned trust rule** (plan T1 step 3; T14 S2, the Contracts half). ADR-046 "The universal
++adaptive fabric" (Proposed, for the owner) ties `platform.resource-offer@1`, `workload-requirements@1`,
++`placement-result@1`, `placement-plan@1`, `provider-state@1`, `rate-card@1`, `cost-snapshot@1`, `telemetry-sample@1`
++and `usage-sample@1` to one placer (`openvibe-sdk/placement`), names the five trust classes, the `worker:<class>`
++capabilities a Node advertises (`worker:function`, `worker:code`, …) and the plane rule: the data plane keeps running
++on the last valid signed plan (`signature`, `epoch`, `expires_at`, checked by `placement.verifyPlan`). It records that
++`user-owned` is **not** in the default trust set: a user-owned offer is eligible only for a workload whose requirements
++name `user-owned`, so the SDK's default trust list stays the other four (this replaces the 0.87.0 note that the SDK
++should route to user-owned nodes by default). Whether a user-owned node may run other users' work, and its consent and
++revocation rule, are open questions for the owner.
++- `platform.resource-offer@1` `trust` and `platform.workload-requirements@1` `trust` gain descriptions stating that
++ rule; the enums (1.1.0 since 0.87.0) are unchanged. Consumers are unchanged.
++- Fixtures: `user-owned-node` now also advertises `worker:function`; new invalid `unknown-trust` (an offer with
++ `trust: "stranger"`, refused on `/trust` alone). `owned-node` is unchanged.
++
++**Two product manifests** (plan T11 step 1): `manifests/products/openvibe.zone.json` (served by the planned `zone`
++service) and `manifests/products/openvibe.work.json` (no repository yet), with name, tagline, pillars and launch taken
++from OpenVibe.Sites `sites.json`. The catalog test's Sites snapshot holds 35 domains.
- `network.project.read` is active, implemented by OpenVibe.Network `GET /internal/projects/:project_id`.
ddiff --git a/contracts/platform/resource-offer.v1.json b/contracts/platform/resource-offer.v1.json
iindex 8dfc66b5..d3681973 100644
---- a/contracts/platform/resource-offer.v1.json
++++ b/contracts/platform/resource-offer.v1.json
@@@ -51,6 +51,7 @@
},
"trust": {
"type": "string",
++ "description": "the offer's trust class (ADR-046): first-party (operated by the OpenVibe network), user-owned (a person's own node, eligible only for workloads whose requirements name user-owned), partner, community or external",
"enum": [
"first-party",
"user-owned",
ddiff --git a/contracts/platform/workload-requirements.v1.json b/contracts/platform/workload-requirements.v1.json
iindex c611ec26..233c79cd 100644
---- a/contracts/platform/workload-requirements.v1.json
++++ b/contracts/platform/workload-requirements.v1.json
@@@ -85,7 +85,7 @@
]
},
"minItems": 1,
-- "description": "trust levels allowed to run it"
++ "description": "trust classes allowed to run it (ADR-046); when absent, first-party, partner, community and external. user-owned is never a default: a user-owned offer is eligible only when this list names it"
},
"region": {
"type": "string",
ddiff --git a/docs/adr/ADR-046-universal-adaptive-fabric.md b/docs/adr/ADR-046-universal-adaptive-fabric.md
nnew file mode 100644
iindex 00000000..edf6052e
---- /dev/null
++++ b/docs/adr/ADR-046-universal-adaptive-fabric.md
@@@ -0,0 +1,120 @@
++# ADR-046: The universal adaptive fabric — offers, requirements, placement, trust classes and signed plans
++
++**Status:** Proposed 2026-10-03 (plan track T1 step 3, for the owner's review). Builds on ADR-034 §5 (control plane
++and data plane; cells) and ADR-042 (the events fabric, the first placed workload class).
++
++## Context and current evidence
++
++- ADR-034 §5 splits the platform into a control plane (identity, projects, grants, registry, billing, deploy) and a
++ data plane (Media bytes, Events streams, Chat rooms, Search indexes, AI runs), and scales the data plane by cells. It
++ does not say how a piece of work is matched to the machine, provider or runtime that runs it.
++- There is one placement implementation, `openvibe-sdk/placement`: `plan()` filters offers by hard constraints
++ (`excluded()`), then ranks the rest by cost and latency with hysteresis, and explains the choice. `signPlan`,
++ `verifyPlan` and `createPlanHolder` sign and check route plans. ADR-042 places event deliveries with it, and Media's
++ fabric uses the same shape. No service is to write its own placer.
++- The Fabric vocabulary already exists as 20 active `platform.*` contracts, all owned by `network`. What was missing
++ was the trust class for a person's own machine (added in 0.87.0) and a written rule tying the contracts together.
++
++## Decision
++
++### 1. Offers, requirements, a result and a plan
++
++- **`platform.resource-offer@1`** — what a capacity holder offers: `kind` (`node`, `provider`, `storage`, `delivery`,
++ `runtime`, `agent`, `harness`), region and cell, `trust`, `capabilities` (`<namespace>:<name>`), capacity, latency,
++ `health`, `pricing`. Offers are facts reported by their holders; they never claim a placement.
++- **`platform.workload-requirements@1`** — what a piece of work needs: `kind` (e.g. `ai.run`, `media.transcode`),
++ `mobility` (`request`, `job`, `session`, `stateful-partition`), `latency_class`, `objective` (`cheapest`,
++ `lowest-latency`, `balanced`, `private`, `local-only`, `first-party-only`, `high-reliability`, `correctness`), and
++ optional limits: latency, deadline, cost, durability, residency, the allowed `trust` classes, region, capabilities.
++- **`platform.placement-result@1`** — one decision: the `selected` offer, the objective, `reasons`, the ranked
++ `candidates` and the `plan_epoch` it was made under. It is the explanation a person or an operator reads.
++- **`platform.placement-plan@1`** — the control plane's routing table for the data plane: `routes` with their targets,
++ a monotonically increasing `epoch`, `issued_at`, `expires_at`, `issuer`, `key_id` and an Ed25519 `signature` over the
++ canonical JSON of every other field.
++
++Every placer is `openvibe-sdk/placement`. A service states requirements and reads results; it does not rank offers.
++
++### 2. Health and cost
++
++- **`platform.provider-state@1`** — a provider's usage in its billing period, forecast, reserve and health.
++- **`platform.rate-card@1`** — a verified price: provider, metric, unit size and price, free allowance and its reset
++ period, region, effective window, `source` and `verified_at`, so every price the placer uses names where it came
++ from and when it was last checked.
++- **`platform.cost-snapshot@1`** — actual cost per target over a window, with the counterfactual cost of the
++ alternatives, so the placer's savings are measured, not assumed (ADR-034 §10).
++
++An offer whose health is neither `up` nor `degraded` is excluded before ranking (`excluded()`); provider state and rate cards then price
++the remaining candidates (`marginalCost`, `forecast`).
++
++### 3. Telemetry and usage
++
++- **`platform.telemetry-sample@1`** — one observation with the universal dimensions (service, project, subject,
++ resource, provider, node, cell, region, operation, latency, queue delay, TTFB, throughput, bytes, status, cache
++ status, cost estimate, `route_epoch`, `trace_id`). It feeds offers' latency and health; it is never billing.
++- **`platform.usage-sample@1`** — one idempotent unit of metered use (`id`, `idempotency_key`, quantity, unit,
++ source), with the same dimensions plus free allowance used and vibes charged. It is the input to metering
++ (ADR-034 §9). Both carry `route_epoch`, so any sample can be traced to the plan that routed it.
++
++### 4. Trust classes
++
++`resource-offer.trust` is one of five classes, in this order; `workload-requirements.trust` lists the classes allowed
++to run the work:
++
++| Class | Meaning |
++| --- | --- |
++| `first-party` | Hosts and accounts the OpenVibe network operates itself (its own servers and provider accounts). |
++| `user-owned` | A person's own node or machine (an OpenVibe.Node they run), offered for their own workloads. |
++| `partner` | An organisation under a written agreement with the network, bound by its data and uptime terms. |
++| `community` | Capacity volunteered by community members, without a contract; best effort, no private data. |
++| `external` | A third-party provider used through its public API under its own terms (a cloud or AI vendor). |
++
++**`user-owned` is not in the default trust set.** When a requirement names no `trust`, the eligible classes are
++`first-party`, `partner`, `community` and `external` (the SDK's `TRUST_ORDER`). A `user-owned` offer is eligible only
++for a workload whose requirements list `"user-owned"` explicitly. Adding the class to the contracts therefore widens
++no existing caller's eligible set, and the SDK must not add it to its default list.
++
++### 5. Worker capability names a Node advertises
++
++An OpenVibe.Node that runs jobs advertises one `worker:<class>` capability in its `resource-offer.capabilities` for
++each `platform.runtime-class@1` class it runs: `worker:function` (a declared function artifact) and `worker:code`
++(submitted code in a sandbox) today, and `worker:browser`, `worker:linux`, `worker:desktop` and `worker:gpu` as Node
++gains them. These six names are reserved for the Node job worker (`$defs.reservedWorkerCapabilities` in
++`platform.resource-offer@1`); every other `worker:` name (`worker:ffmpeg`, `worker:ai-gpu`) is an ordinary capability.
++A requirement asks for a class by listing the same name in its `capabilities`.
++
++### 6. Control plane and data plane
++
++- The **control plane** collects offers, provider state and rate cards, runs the placer, and issues signed
++ `placement-plan@1` documents, each with a higher `epoch` than the last.
++- The **data plane** routes by the plan it holds. It accepts a new plan only when `openvibe-sdk/placement.verifyPlan`
++ passes (known `key_id`, valid signature, `expires_at` in the future) and the plan's `epoch` is newer than the current
++ one (`createPlanHolder`). A plan that fails is rejected and logged.
++- **The data plane keeps running on the last valid signed plan.** A control-plane outage, a bad signature or a stale
++ epoch never stops delivery; it only stops change. A plan past its `expires_at` is never accepted, and a data plane
++ holding one keeps routing by it, reports itself stale, and does not invent routes of its own.
++
++### 7. The reference consumer
++
++T6 (OpenVibe.AI) is the reference consumer: it states `ai.run` requirements, places each run across first-party
++nodes, external AI providers and, when the request names it, the person's own `user-owned` node, and records a
++placement result, telemetry and usage samples for every run. Other services adopt the fabric after it.
++
++## Consequences
++
++- One vocabulary and one placer for every placed workload; a new kind of capacity is a new offer, not new code.
++- Routing survives the control plane: plans are signed, epoch-ordered and verified where they are used.
++- A person can run their own work on their own machine without that machine joining anyone else's default pool.
++- The SDK placer, the T2 resource registry and OpenVibe.Node must agree on the trust rule; this ADR is that rule.
++
++## Open questions for the owner
++
++1. May a `user-owned` node run **other users'** workloads (as a community-style contributor), or only its owner's?
++ Until answered, only its owner's, and only when the requirement names `user-owned`.
++2. What is the consent and revocation rule for a `user-owned` node: how its owner opts each workload class in, how
++ they withdraw (immediately, or after running jobs drain), and what the placer does with work in flight when consent
++ is revoked?
++
++## What this ADR does not claim
++
++- No producer emits `user-owned` offers yet, and no service places across user-owned nodes today.
++- Cells, the plan issuer and its key distribution are not built; ADR-034's phasing (roadmap WS-W) still applies.
ddiff --git a/docs/adr/README.md b/docs/adr/README.md
iindex 92132430..63fac0a4 100644
---- a/docs/adr/README.md
++++ b/docs/adr/README.md
@@@ -40,3 +40,4 @@ Platform-wide decisions from the OpenVibe development roadmap (section 10). Each
| [ADR-034](ADR-034-platform-north-star.md) | Platform north star, an open affordable cloud: boundaries now (projects, `ovrn:` resource names, scoped grants, generated contracts, metering), infrastructure when measured; control/data plane and cells; regions, edge nodes, load balancing and a geo API; pulled, gated deploys; four extension levels under one manifest | Proposed 2026-09-28, for the owner's review |
| [ADR-035](ADR-035-postgresql-and-valkey.md) | PostgreSQL 18 as every service's system of record (database + roles per service, PgBouncer transaction pooling, pgBackRest PITR to B2) and Valkey as the shared non-authoritative store; the SDK data layer; services migrate one at a time, smallest first; supersedes ADR-007's trigger rule; amendment: PostgreSQL dialect only (PGlite in tests), a verified SQLite importer, every service async and migrated | Accepted 2026-09-28 (owner decision), amended the same day |
| [ADR-042](ADR-042-events-fabric.md) | The events fabric: the delivery-policy class is the one vocabulary and TOPIC/QUEUE/STREAM a derived carrier class; PostgreSQL stays the record, carriers are transports that fail open to `pg-v1`; a delivery lease before any second worker; per-key ordering; the SDK planner places deliveries and explains them; JetStream for STREAM only; opaque cursors replace the global seq after one overlap release; hot/replay/archive tiers; amends ADR-004's NATS rejection | Accepted 2026-09-29 (plan T7) |
++| [ADR-046](ADR-046-universal-adaptive-fabric.md) | The universal adaptive fabric: offers, requirements, placement results and signed plans through one placer (`openvibe-sdk/placement`); health, cost, telemetry and usage samples; five trust classes, with `user-owned` eligible only when a workload names it; `worker:<class>` Node capabilities; the data plane keeps running on the last valid signed plan; T6 AI the reference consumer | Proposed 2026-10-03 (plan T1 step 3), for the owner's review |
ddiff --git a/fixtures/platform.resource-offer/invalid/unknown-trust.json b/fixtures/platform.resource-offer/invalid/unknown-trust.json
nnew file mode 100644
iindex 00000000..b6c6d194
---- /dev/null
++++ b/fixtures/platform.resource-offer/invalid/unknown-trust.json
@@@ -0,0 +1,19 @@
++{
++ "offer_id": "off_stranger_1",
++ "kind": "node",
++ "node_id": "stranger-node-1",
++ "provider": "self",
++ "region": "home",
++ "trust": "stranger",
++ "capabilities": [
++ "node:http",
++ "worker:function"
++ ],
++ "health": {
++ "status": "up"
++ },
++ "pricing": {
++ "model": "free-allowance"
++ },
++ "updated_at": "2026-10-03T00:00:00Z"
++}
ddiff --git a/fixtures/platform.resource-offer/valid/user-owned-node.json b/fixtures/platform.resource-offer/valid/user-owned-node.json
iindex 56904110..ae266fe8 100644
---- a/fixtures/platform.resource-offer/valid/user-owned-node.json
++++ b/fixtures/platform.resource-offer/valid/user-owned-node.json
@@@ -7,6 +7,7 @@
"trust": "user-owned",
"capabilities": [
"node:http",
++ "worker:function",
"worker:ai-gpu"
],
"capacity": {
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex defd5d44..82ec5af3 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -58431,6 +58431,7 @@
},
"trust": {
"type": "string",
++ "description": "the offer's trust class (ADR-046): first-party (operated by the OpenVibe network), user-owned (a person's own node, eligible only for workloads whose requirements name user-owned), partner, community or external",
"enum": [
"first-party",
"user-owned",
@@@ -58888,7 +58889,7 @@
]
},
"minItems": 1,
-- "description": "trust levels allowed to run it"
++ "description": "trust classes allowed to run it (ADR-046); when absent, first-party, partner, community and external. user-owned is never a default: a user-owned offer is eligible only when this list names it"
},
"region": {
"type": "string",
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex 9ef013e0..8efaa4e2 100644
---- a/generated/openapi/ai.json
++++ b/generated/openapi/ai.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.AI API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/billing.json b/generated/openapi/billing.json
iindex 45661534..0b907202 100644
---- a/generated/openapi/billing.json
++++ b/generated/openapi/billing.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Billing API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/blog.json b/generated/openapi/blog.json
iindex 8d27bf2d..12675282 100644
---- a/generated/openapi/blog.json
++++ b/generated/openapi/blog.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Blog API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/bot.json b/generated/openapi/bot.json
iindex 569725f5..b04348de 100644
---- a/generated/openapi/bot.json
++++ b/generated/openapi/bot.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bot API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/chat.json b/generated/openapi/chat.json
iindex 42dc8609..cb824a77 100644
---- a/generated/openapi/chat.json
++++ b/generated/openapi/chat.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Chat API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/codes.json b/generated/openapi/codes.json
iindex 8877b798..cae9ca4b 100644
---- a/generated/openapi/codes.json
++++ b/generated/openapi/codes.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Codes API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/community.json b/generated/openapi/community.json
iindex 2b4bf3ff..b051ed13 100644
---- a/generated/openapi/community.json
++++ b/generated/openapi/community.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Community API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/coupons.json b/generated/openapi/coupons.json
iindex 21c02ee1..e583ab79 100644
---- a/generated/openapi/coupons.json
++++ b/generated/openapi/coupons.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Coupons API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/deals.json b/generated/openapi/deals.json
iindex 271b9f65..7f55238e 100644
---- a/generated/openapi/deals.json
++++ b/generated/openapi/deals.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Deals API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/events.json b/generated/openapi/events.json
iindex 3c6ecc4a..c006bfe2 100644
---- a/generated/openapi/events.json
++++ b/generated/openapi/events.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Events API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/games.json b/generated/openapi/games.json
iindex 2873c008..663cd708 100644
---- a/generated/openapi/games.json
++++ b/generated/openapi/games.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Games API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/host.json b/generated/openapi/host.json
iindex 12575d62..b4f9f489 100644
---- a/generated/openapi/host.json
++++ b/generated/openapi/host.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Host API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/live.json b/generated/openapi/live.json
iindex 4b7fb7c5..89f9c676 100644
---- a/generated/openapi/live.json
++++ b/generated/openapi/live.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Live API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/media.json b/generated/openapi/media.json
iindex 6814edf7..7580d0c2 100644
---- a/generated/openapi/media.json
++++ b/generated/openapi/media.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Media API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/network.json b/generated/openapi/network.json
iindex 8243283b..ac635b1b 100644
---- a/generated/openapi/network.json
++++ b/generated/openapi/network.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Network API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/news.json b/generated/openapi/news.json
iindex cb58c087..eae2ef0d 100644
---- a/generated/openapi/news.json
++++ b/generated/openapi/news.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.News API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/openre.json b/generated/openapi/openre.json
iindex 39524671..8d3feda6 100644
---- a/generated/openapi/openre.json
++++ b/generated/openapi/openre.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenRe.Stream API",
-- "version": "0.87.0",
-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/reviews.json b/generated/openapi/reviews.json
iindex 29e83655..a25cf159 100644
---- a/generated/openapi/reviews.json
++++ b/generated/openapi/reviews.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Reviews API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/search.json b/generated/openapi/search.json
iindex b7ab487d..a8d83a32 100644
---- a/generated/openapi/search.json
++++ b/generated/openapi/search.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Search API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/sources.json b/generated/openapi/sources.json
iindex 20f3cada..e8cf049a 100644
---- a/generated/openapi/sources.json
++++ b/generated/openapi/sources.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Sources API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/space.json b/generated/openapi/space.json
iindex f16199af..ab6284cf 100644
---- a/generated/openapi/space.json
++++ b/generated/openapi/space.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Space API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/tips.json b/generated/openapi/tips.json
iindex 0793638d..335cc336 100644
---- a/generated/openapi/tips.json
++++ b/generated/openapi/tips.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tips API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/tools.json b/generated/openapi/tools.json
iindex cd2f09e2..4c06db00 100644
---- a/generated/openapi/tools.json
++++ b/generated/openapi/tools.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tools API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/trade.json b/generated/openapi/trade.json
iindex 5cb91988..c51cb0ed 100644
---- a/generated/openapi/trade.json
++++ b/generated/openapi/trade.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Trade API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/vip.json b/generated/openapi/vip.json
iindex 6bdd16e2..264c7853 100644
---- a/generated/openapi/vip.json
++++ b/generated/openapi/vip.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.VIP API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/wiki.json b/generated/openapi/wiki.json
iindex a17587c2..f468ccfb 100644
---- a/generated/openapi/wiki.json
++++ b/generated/openapi/wiki.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Wiki API",
-- "version": "0.87.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.87.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.88.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.88.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/typescript/index.d.ts b/generated/typescript/index.d.ts
iindex 13815090..5c2175d4 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -50970,6 +50970,9 @@ export type ResourceOffer = {
adapter?: string;
region: string;
cell?: string;
++ /**
++ * the offer's trust class (ADR-046): first-party (operated by the OpenVibe network), user-owned (a person's own node, eligible only for workloads whose requirements name user-owned), partner, community or external
++ */
trust: "first-party" | "user-owned" | "partner" | "community" | "external";
/**
* e.g. node:http, worker:browser, worker:ffmpeg, worker:ai-gpu, events:gateway, events:durable, object:r2. Kind harness: task:edit, task:review, task:browse, task:run, task:test and task:plan for the task kinds it takes (its detail's task_capabilities), and harness:mcp, harness:resume, harness:host-access and harness:long-autonomy for its detail's capabilities that are true. The `worker:<class>` names that map to platform.runtime-class@1 values are reserved for OpenVibe.Node's job worker, one per class: worker:function, worker:code, worker:browser, worker:linux, worker:desktop and worker:gpu ($defs.reservedWorkerCapabilities). A node advertises the name of each class it runs (Node's status.capabilities.worker); every other `worker:` name (worker:ffmpeg, worker:ai-gpu) is an ordinary capability name.
@@@ -51074,7 +51077,7 @@ export interface WorkloadRequirements {
*/
residency?: string;
/**
-- * trust levels allowed to run it
++ * trust classes allowed to run it (ADR-046); when absent, first-party, partner, community and external. user-owned is never a default: a user-owned offer is eligible only when this list names it
*
* @minItems 1
*/
ddiff --git a/manifests/products/openvibe.work.json b/manifests/products/openvibe.work.json
nnew file mode 100644
iindex 00000000..cb42054a
---- /dev/null
++++ b/manifests/products/openvibe.work.json
@@@ -0,0 +1,39 @@
++{
++ "domain": "openvibe.work",
++ "tld": "work",
++ "name": "OpenVibe.Work",
++ "icon": "fa-briefcase",
++ "accent": "#34d399",
++ "tagline": "Find work, with an agent on your side.",
++ "description": "OpenVibe.Work will gather job listings from open sources with their provenance, let you search them and watch for new ones that fit, and let an agent help you prepare and apply — with your approval at every step. Part of the OpenVibe network, with one account for every site.",
++ "pillars": [
++ {
++ "title": "Every listing sourced",
++ "text": "Where it came from and when, always shown."
++ },
++ {
++ "title": "Watch for fits",
++ "text": "Get told when a job that matches appears."
++ },
++ {
++ "title": "An agent that helps",
++ "text": "Drafts, tailors and tracks applications — you approve."
++ },
++ {
++ "title": "Yours to control",
++ "text": "Your profile and history stay yours, exportable any time."
++ }
++ ],
++ "keywords": "openvibe work, job search, job listings, job alerts, ai job application assistant",
++ "launch": "job listings and alerts",
++ "relationships": {
++ "noRepo": true,
++ "meanwhile": [
++ {
++ "label": "OpenVibe.Network",
++ "url": "https://openvibe.network",
++ "note": "One free account for every OpenVibe site, ready today."
++ }
++ ]
++ }
++}
ddiff --git a/manifests/products/openvibe.zone.json b/manifests/products/openvibe.zone.json
nnew file mode 100644
iindex 00000000..9d516d1c
---- /dev/null
++++ b/manifests/products/openvibe.zone.json
@@@ -0,0 +1,40 @@
++{
++ "domain": "openvibe.zone",
++ "tld": "zone",
++ "name": "OpenVibe.Zone",
++ "icon": "fa-box-archive",
++ "accent": "#2dd4bf",
++ "tagline": "Your data, in zones.",
++ "description": "OpenVibe.Zone will keep your data and files in zones — S3-style buckets for persistent storage that every OpenVibe service and agent can use with your permission, also offered to developers through OpenVibe.Services. Part of the OpenVibe network, with one account for every site.",
++ "pillars": [
++ {
++ "title": "An S3-style API",
++ "text": "Buckets, objects and signed links that existing tools already speak."
++ },
++ {
++ "title": "Durable storage",
++ "text": "Files and data that stay put, with copies kept safe."
++ },
++ {
++ "title": "Access you control",
++ "text": "Decide which services, agents and people can read or write each zone."
++ },
++ {
++ "title": "Used across the network",
++ "text": "The same zones back your streams, media, agents and apps."
++ }
++ ],
++ "keywords": "openvibe zone, object storage, s3 compatible storage, buckets, persistent storage, file storage api",
++ "launch": "zones for data and files",
++ "relationships": {
++ "service": "zone",
++ "plannedRepo": "OpenVibe.Zone",
++ "meanwhile": [
++ {
++ "label": "OpenVibe.Network",
++ "url": "https://openvibe.network",
++ "note": "One free account for every OpenVibe site, ready today."
++ }
++ ]
++ }
++}
ddiff --git a/package-lock.json b/package-lock.json
iindex 9d553b84..cf9e3e86 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-contracts",
-- "version": "0.87.0",
++ "version": "0.88.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-contracts",
-- "version": "0.87.0",
++ "version": "0.88.0",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 6a53173e..0488ec57 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.87.0",
++ "version": "0.88.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
ddiff --git a/test/fixtures/sites-domains.json b/test/fixtures/sites-domains.json
iindex aeae5f9d..74d964fe 100644
---- a/test/fixtures/sites-domains.json
++++ b/test/fixtures/sites-domains.json
@@@ -1,5 +1,5 @@
{
-- "_about": "The 33 domains of OpenVibe.Sites sites.json (origin/main c2fda6c, 2026-09-29), snapshotted for the catalog home test (plan T11 lane D). Each has exactly one home: a service manifest site with a tld, or manifests/products/<domain>.json.",
++ "_about": "The 35 catalog domains of OpenVibe.Sites sites.json: the 33 of origin/main c2fda6c (2026-09-29), snapshotted for the catalog home test (plan T11 lane D), plus openvibe.work and openvibe.zone (plan T11 step 1). Each has exactly one home: a service manifest site with a tld, or manifests/products/<domain>.json.",
"source": "OpenVibers/OpenVibe.Sites@c2fda6c:sites.json",
"domains": [
"openvibe.news",
@@@ -34,6 +34,8 @@
"openvibe.bot",
"openvibe.watch",
"openvibe.actor",
-- "openvibe.events"
++ "openvibe.events",
++ "openvibe.work",
++ "openvibe.zone"
]
}
ddiff --git a/test/platform-fabric.test.js b/test/platform-fabric.test.js
iindex b550be53..e1884710 100644
---- a/test/platform-fabric.test.js
++++ b/test/platform-fabric.test.js
@@@ -84,4 +84,16 @@ checks++;
assert.strictEqual(contracts.validate('platform.workload-requirements', { ...userRequirement, trust: ['other'] }).valid, false, 'an unknown requirement trust is refused');
checks++;
++// The fixtures (ADR-046): a user-owned node advertises the Node job worker's worker:function, and the
++// unknown-trust offer is refused for its trust alone.
++const fixture = (p) => require(`../fixtures/platform.resource-offer/${p}.json`);
++const userNode = fixture('valid/user-owned-node');
++assert.ok(userNode.trust === 'user-owned' && userNode.capabilities.includes('worker:function'), 'user-owned-node advertises worker:function');
++checks++;
++const unknownTrust = contracts.validate('platform.resource-offer', fixture('invalid/unknown-trust'));
++assert.strictEqual(unknownTrust.valid, false, 'the unknown-trust fixture is refused');
++checks++;
++assert.ok(unknownTrust.errors.length && unknownTrust.errors.every(e => e.path === '/trust'), `unknown-trust fails on /trust only: ${JSON.stringify(unknownTrust.errors)}`);
++checks++;
++
console.log(`platform fabric: ${checks} assertions passed`);
ddiff --git a/test/product-catalog.test.js b/test/product-catalog.test.js
iindex 27eb96e5..291799ac 100644
---- a/test/product-catalog.test.js
++++ b/test/product-catalog.test.js
@@@ -29,7 +29,7 @@ for (const row of products.catalog()) homes.set(row.domain, [...(homes.get(row.d
for (const [domain, list] of homes) ok(list.length === 1, `${domain} has one home, not ${list.join(', ')}`);
const snapshot = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures/sites-domains.json'), 'utf8')).domains;
--ok(snapshot.length === 33 && new Set(snapshot).size === 33, 'the Sites snapshot holds 33 distinct domains');
++ok(snapshot.length === 35 && new Set(snapshot).size === 35, 'the Sites snapshot holds 35 distinct domains');
for (const d of snapshot) ok((homes.get(d) || []).length === 1, `${d} (OpenVibe.Sites) has exactly one Contracts home: ${(homes.get(d) || ['none']).join(', ')}`);
for (const p of products.manifests) {