---
title: "common.config-namespace@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/common.config-namespace"
updated: null
---

# common.config-namespace@1 · OpenVibe.Services

HTML: [common.config-namespace@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/common.config-namespace)

# ConfigNamespace `common.config-namespace@1`

Generated at 2026-11-13 06:25:48 UTC from [`openvibe-contracts v0.419.0`](https://github.com/OpenVibers/OpenVibe.Contracts/tree/v0.419.0) and [`openvibe-sdk v0.161.0`](https://github.com/OpenVibers/OpenVibe.SDK/tree/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`](/docs/contracts/common.config-namespace.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 |  | - `pattern ^[a-z][a-z0-9-]{1,39}$` |
| `namespace` | string | yes | <service>.<name>, e.g. ai.exchange or live.site\_settings. | - `pattern ^[a-z][a-z0-9-]{1,39}(\.[a-z0-9_-]+)+$`<br>- `maxLength 120` |
| `revision` | integer \| null | yes | The active revision; null before the namespace has one. | - `minimum 1` |
| `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. | - `unique items`<br>- `items: pattern ^[A-Za-z0-9_][A-Za-z0-9_.:-]{0,127}$` |
| `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 }] }
~~~~
