openvibers/openvibe.blog Commits

openvibe-contracts v0.338.0 (was v0.312.0) (#226)

OP OpenVibers committed 5 days ago · def72eccd8 · 6 files, +22 −24

* openvibe-contracts v0.338.0 (was v0.312.0)

Opened by scripts/pin-bump.js in OpenVibers/OpenVibe.Shared after the v0.338.0 release.

* openvibe-contracts v0.338.0: blog.review.ai_editor is released, so the local proposal retires

Changes

ddiff --git a/README.md b/README.md
iindex b2f2531..dc542f6 100644
---- a/README.md
++++ b/README.md
@@@ -314,7 +314,7 @@ acts for goes in `X-OV-Subject`, and membership still applies:
- `blog.feed.read`
Browser and app user JWTs are judged by blog membership. The ids and the service manifest are
--released in openvibe-contracts (pinned at v0.97.0; the source proposals stay in
++released in openvibe-contracts (pinned at v0.338.0; the source proposals stay in
[docs/capabilities-proposal/](docs/capabilities-proposal/) and
[docs/service-manifest-proposal.json](docs/service-manifest-proposal.json)); `server/auth/capabilities.js`
decides them with the contracts grant rule.
@@@ -541,7 +541,7 @@ First install (done once; kept for a rebuild):
Part of the [OpenVibe network](https://openvibe.network). Built in the open by [OpenVibers](https://github.com/OpenVibers).
<!-- versions:start -->
--- openvibe-contracts: v0.312.0
++- openvibe-contracts: v0.338.0
- openvibe-sdk: v0.94.0
- openvibe-shared: v4.142.0
- openvibe-publishing: v1.4.1
ddiff --git a/STATUS.json b/STATUS.json
iindex 02ed2e4..d391ca8 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,12 +7,12 @@
"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db, async) + Valkey 9",
"port": 4810,
"domain": "openvibe.blog",
-- "contracts": "openvibe-contracts v0.312.0",
++ "contracts": "openvibe-contracts v0.338.0",
"sdk": "openvibe-sdk v0.94.0",
"shared": "openvibe-shared v4.142.0",
"packages": [
"openvibe-publishing v1.4.1",
-- "openvibe-contracts v0.312.0",
++ "openvibe-contracts v0.338.0",
"openvibe-shared v4.142.0",
"openvibe-sdk v0.94.0"
],
@@@ -55,5 +55,5 @@
"per-actor limits (openvibe-sdk/limits)"
],
"database": "PostgreSQL ov_blog (ADR-035), schema migrations/0001_initial.sql applied at boot",
-- "updated": "2026-11-07"
++ "updated": "2026-11-08"
}
ddiff --git a/package-lock.json b/package-lock.json
iindex 4153ee8..05a017a 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -15,7 +15,7 @@
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.312.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.1",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.142.0",
@@@ -1148,9 +1148,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.312.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.312.0",
-- "integrity": "sha512-2GsD53zuIedL3eW2LBlYQ68ODTHzoZJHrAmVnZCpiL7ZWnAXGwPW9dpQagLI9Zdkh3LQuuU5ae1YJI0K+acXbA==",
++ "version": "0.338.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",
++ "integrity": "sha512-75FD6IxMsXoud3NFXKDs0/D0rhJtF2D+WL8M92ArIyabkUnM/sZvw6E6L97EqwQ3O7M/kB+uwsNSxGudbil+ng==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 76402a3..5b7a653 100644
---- a/package.json
++++ b/package.json
@@@ -27,7 +27,7 @@
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.312.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.4.1",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.142.0",
ddiff --git a/server/auth/capabilities.js b/server/auth/capabilities.js
iindex 80cce04..4929253 100644
---- a/server/auth/capabilities.js
++++ b/server/auth/capabilities.js
@@@ -31,7 +31,9 @@ const CAPABILITIES = Object.freeze({
// The ids above as a local fallback while openvibe-contracts does not define one yet (the same
// rule the library uses: the exact id, or a `prefix.*` grant covering it). An id the library knows
// always goes through the library, so the day a release lands nothing changes here.
--const PROPOSED = new Set(Object.values(CAPABILITIES));
++// openvibe-contracts v0.338.0 (2026-11-08) released the last one, blog.review.ai_editor, so the
++// local fallback is empty and every id above is decided by the library.
++const PROPOSED = new Set();
/** → { allowed, code, reason } like capabilities.check(). */
function checkCapability(claims, capabilityId) {
ddiff --git a/test/capabilities.test.js b/test/capabilities.test.js
iindex 86dd331..4a203e1 100644
---- a/test/capabilities.test.js
++++ b/test/capabilities.test.js
@@@ -1,12 +1,11 @@
'use strict';
/**
* The blog.* capabilities are released by openvibe-contracts, so the service guards delegate to the
-- * library's grant rule rather than deciding a proposed id locally. One id is still a proposal and
-- * waits for a Contracts release — blog.review.ai_editor (the AI editor's review kind) — so it is
-- * decided by the same grant rule locally until then (server/auth/capabilities.js PROPOSED). These
-- * pin that: every guarded id is defined by the installed contracts and the blog service manifest,
-- * except the proposal, which is tracked as one; and checkCapability agrees with capabilities.check
-- * for an exact grant, a prefix grant, no grant, and an id nobody defines.
++ * library's grant rule rather than deciding a proposed id locally. Since openvibe-contracts v0.338.0
++ * every id this service guards is released — blog.review.ai_editor (the AI editor's review kind)
++ * included — so nothing is decided locally any more. These pin that: every guarded id is defined by
++ * the installed contracts and the blog service manifest; and checkCapability agrees with
++ * capabilities.check for an exact grant, a prefix grant, no grant, and an id nobody defines.
*/
const assert = require('assert');
const { capabilities, services } = require('openvibe-contracts');
@@@ -23,21 +22,18 @@ const GRANTED = { cap: ['blog.post.read'], sub: 'svc:openvibe.network' };
assert.deepStrictEqual([...manifest.capabilities].sort(), released.sort());
for (const id of Object.values(CAPABILITIES)) {
const cap = capabilities.get(id);
-- if (!cap) {
-- assert.ok(PROPOSED.has(id), `${id} is not released yet, so it must be a local proposal`);
-- continue;
-- }
++ assert.ok(cap, `${id} is released by openvibe-contracts`);
assert.strictEqual(cap.owner, 'blog', `${id} is owned by blog`);
}
-- // The AI editor's id is the one proposal; when Contracts releases it, this line goes.
-- assert.strictEqual(capabilities.get('blog.review.ai_editor'), undefined);
++ // The AI editor's id is released since openvibe-contracts v0.338.0: no id is a local proposal any more.
++ assert.strictEqual(PROPOSED.size, 0, 'no capability is waiting for a Contracts release');
});
await check('checkCapability follows the contracts grant rule (exact, prefix, denied, unknown)', async () => {
// An exact grant and a `prefix.*` grant the library's matching rule accepts.
assert.deepStrictEqual(checkCapability(GRANTED, 'blog.post.read'), { allowed: true, code: null, reason: null });
assert.deepStrictEqual(checkCapability({ cap: ['blog.*'] }, 'blog.post.read'), { allowed: true, code: null, reason: null });
-- // The proposal is decided with the same rule until Contracts defines it.
++ // Every id is released, so the library's own rule decides it.
assert.deepStrictEqual(checkCapability({ cap: ['blog.review.ai_editor'] }, 'blog.review.ai_editor'), { allowed: true, code: null, reason: null });
assert.deepStrictEqual(checkCapability({ cap: ['blog.*'] }, 'blog.review.ai_editor'), { allowed: true, code: null, reason: null });
assert.strictEqual(checkCapability({ cap: ['blog.post.publish'] }, 'blog.review.ai_editor').code, 'capability.denied');