ConfigNamespace common.config-namespace@1
Generated at from
openvibe-contracts v0.419.0 and
openvibe-sdk v0.161.0.
- Version
- 1.0.0
- Owner
- network
- Visibility
- internal
- Status
- active
- Compatibility
- backward
- Schema
https://openvibe.network/contracts/common/config-namespace.v1.json
common.config-namespace@1 (AI Exchange D11): one service configuration namespace as openvibe-shared/config's summary() returns it (config-pg.js), plus `sealed`, `pins` and `schema`. GET /internal/config lists these for a service and GET /internal/config/:namespace returns one. Values are the active ones over the defaults, with every secret-class value replaced by its marker; a marker never carries the value. `sealed` says whether the service has a KEK so secrets are envelopes (false is the pre-D11 plaintext behaviour). `pins` names the keys whose x-env variable is set, so their effective value is the environment's and a write is 409 config.pinned_in_env. `schema` is the namespace's JSON Schema so a client can draw the form; its annotations are title, description, x-group, x-env, x-danger, x-bind and x-unit (nano_usd, ms, bps, seconds), and for the owner's Setup tab and the clear admin panel (openvibe-shared 4.125.0) x-owner-input ({ group, unlocks, get_it_at, get_it_how, test }: a field only the owner can give), x-required-for (the feature an unset field blocks), x-enum-labels ({ value: { label, description } }), x-advanced (folded under Advanced settings) and x-example (a placeholder; never on a secret).
Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
service | string | yes |
| |
namespace | string | yes | <service>.<name>, e.g. ai.exchange or live.site_settings. |
|
revision | integer | null | yes | The active revision; null before the namespace has one. |
|
values | object | yes | The active values over the defaults, one member per key. A secret-class key's value is a marker, never the value. | |
classification | object | yes | Every key of values, classified. A key the service does not classify is internal. | |
sealed | boolean | yes | True when the service has a KEK: secret-class values are stored as envelopes and only opened for a caller that needs them. False keeps the pre-D11 plaintext-inside-values_json behaviour, and the tab shows it in red. | |
pins | array of string | yes | The keys whose x-env variable is set in the service process: their effective value is the environment's, read-only, and a write answers 409 config.pinned_in_env. |
|
schema | object | null | yes | The namespace's JSON Schema, or null when it has none. Annotations the client may read: title, description, x-group, x-env, x-danger, x-bind (the key whose value the secret is bound to), x-unit (nano_usd, ms, bps or seconds), x-owner-input, x-required-for, x-enum-labels, x-advanced and x-example. | |
active | one of | The active revision as a snapshot (common.config-snapshot@1), or null. | ||
last_known_good | one of | The last revision that activated cleanly (common.config-snapshot@1), or null. |
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: empty-namespace
{
"service": "ai",
"namespace": "ai.exchange",
"revision": null,
"values": {},
"classification": {},
"sealed": false,
"pins": [],
"schema": null,
"active": null,
"last_known_good": null
}Valid: live-site-settings
{
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"values": {
"site_name": "OpenVibe.Live",
"registration_open": true,
"max_bitrate_kbps": 6000,
"youtube_api_key": {
"redacted": true,
"fingerprint": "c61d1b1293d59c54c56624f6d6161b8af976449db60f230ed977dcf3ba4bd31b",
"hint": "a1b2",
"set_at": "2026-11-04T18:34:00.000Z",
"set_by": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
},
"bound_to": "https://www.googleapis.com"
},
"home_banner": {
"text": "Welcome",
"link": "/about"
}
},
"classification": {
"site_name": "public",
"registration_open": "public",
"max_bitrate_kbps": "internal",
"youtube_api_key": "secret",
"home_banner": "public"
},
"sealed": true,
"pins": [
"youtube_api_key"
],
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"site_name": {
"type": "string",
"title": "Site name",
"description": "The name shown in the page header.",
"x-group": "Site"
},
"registration_open": {
"type": "boolean",
"title": "Registration open",
"x-group": "Site"
},
"max_bitrate_kbps": {
"type": "integer",
"title": "Maximum bitrate",
"x-group": "Streaming",
"x-unit": "bps",
"x-danger": true
},
"youtube_api_key": {
"type": "string",
"title": "YouTube API key",
"x-group": "Integrations",
"x-env": "YOUTUBE_API_KEY",
"x-bind": "base_url"
},
"base_url": {
"type": "string",
"title": "Base URL",
"x-group": "Integrations"
}
}
},
"active": {
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"previous_revision": 11,
"state": "active",
"values": {
"site_name": "OpenVibe.Live",
"registration_open": true,
"max_bitrate_kbps": 6000,
"youtube_api_key": {
"redacted": true,
"fingerprint": "c61d1b1293d59c54c56624f6d6161b8af976449db60f230ed977dcf3ba4bd31b"
},
"home_banner": {
"text": "Welcome",
"link": "/about"
}
},
"classification": {
"site_name": "public",
"registration_open": "public",
"max_bitrate_kbps": "internal",
"youtube_api_key": "secret",
"home_banner": "public"
},
"checksum": "29cd8cc21471b306491daa584d01892c05b41e5e51d5bf83aaf5fc6f4a28ca87",
"created_at": "2026-09-25T18:02:11.412Z",
"created_by": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
},
"activated_at": "2026-09-25T18:02:11.530Z",
"activated_by": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
},
"reason": "Raise the bitrate cap for the tournament",
"error": null,
"copied_from": null
},
"last_known_good": {
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"previous_revision": 11,
"state": "active",
"values": {
"site_name": "OpenVibe.Live",
"registration_open": true,
"max_bitrate_kbps": 6000,
"youtube_api_key": {
"redacted": true,
"fingerprint": "c61d1b1293d59c54c56624f6d6161b8af976449db60f230ed977dcf3ba4bd31b"
},
"home_banner": {
"text": "Welcome",
"link": "/about"
}
},
"classification": {
"site_name": "public",
"registration_open": "public",
"max_bitrate_kbps": "internal",
"youtube_api_key": "secret",
"home_banner": "public"
},
"checksum": "29cd8cc21471b306491daa584d01892c05b41e5e51d5bf83aaf5fc6f4a28ca87",
"created_at": "2026-09-25T18:02:11.412Z",
"created_by": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
},
"activated_at": "2026-09-25T18:02:11.530Z",
"activated_by": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
},
"reason": "Raise the bitrate cap for the tournament",
"error": null,
"copied_from": null
}
}Rejected: extra-field
{
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"values": {
"site_name": "OpenVibe.Live"
},
"classification": {
"site_name": "public"
},
"sealed": true,
"pins": [],
"schema": null,
"active": null,
"last_known_good": null,
"secret_values": {
"youtube_api_key": "AIza-example-secret"
}
}Rejected: pins-not-keys
{
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"values": {
"site_name": "OpenVibe.Live"
},
"classification": {
"site_name": "public"
},
"sealed": true,
"pins": [
"not a key"
],
"schema": null,
"active": null,
"last_known_good": null
}Rejected: schema-string
{
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"values": {
"site_name": "OpenVibe.Live"
},
"classification": {
"site_name": "public"
},
"sealed": true,
"pins": [],
"schema": "object",
"active": null,
"last_known_good": null
}Rejected: secret-value
{
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"values": {
"youtube_api_key": {
"redacted": true,
"fingerprint": "c61d1b1293d59c54c56624f6d6161b8af976449db60f230ed977dcf3ba4bd31b",
"value": "AIza-example-secret"
}
},
"classification": {
"youtube_api_key": "secret"
},
"sealed": true,
"pins": [],
"schema": null,
"active": null,
"last_known_good": null
}Rejected: unknown-classification
{
"service": "live",
"namespace": "live.site_settings",
"revision": 12,
"values": {
"site_name": "OpenVibe.Live"
},
"classification": {
"site_name": "private"
},
"sealed": true,
"pins": [],
"schema": null,
"active": null,
"last_known_good": null
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('common.config-namespace@1', value); // { valid, errors: [{ path, message }] }