---
title: "connect.policy@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/connect.policy"
updated: null
---

# connect.policy@1 · OpenVibe.Services

HTML: [connect.policy@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/connect.policy)

# ConnectPolicy `connect.policy@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: connect
- Visibility: first-party
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/connect/policy.v1.json`](/docs/contracts/connect.policy.json)

connect.policy@1: the grants, routes and exit-node settings of one private Connect tenant. It is deliberately tenant-scoped: a rule never names a device, person or tag from another tenant, and default\_action is deny unless the owner opens a path. It describes intent, not the control plane's internal ACL file or keys.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `id` | string | yes |  | - `pattern ^pol_[0-9A-HJKMNP-TV-Z]{26}$` |
| `owner` | [identity.subject-ref](/docs/contracts/identity.subject-ref) | yes |  |  |
| `project_id` | string \| null |  |  | - `pattern ^prj_[0-9A-HJKMNP-TV-Z]{26}$` |
| `tenant` | one of | yes | The one tenant this policy can affect; a rule or route naming another tenant's id is invalid. |  |
| `name` | string |  |  | - `minLength 1`<br>- `maxLength 80` |
| `version` | integer | yes | Bumped on every change; a device keeps the version it last applied. | - `minimum 1` |
| `default_action` | enum | yes | deny unless the owner explicitly opens a path. | - `one of "allow", "deny"` |
| `rules` | array of object | yes |  | - `maxItems 200`<br>- `items: no other fields` |
| `rules[].action` | enum | yes |  | - `one of "allow", "deny"` |
| `rules[].sources` | `https://openvibe.network/contracts/connect/policy.v1.json#/$defs/selector` | yes |  | - `minItems 1`<br>- `maxItems 50` |
| `rules[].destinations` | `https://openvibe.network/contracts/connect/policy.v1.json#/$defs/selector` | yes |  | - `minItems 1`<br>- `maxItems 50` |
| `rules[].ports` | `https://openvibe.network/contracts/connect/policy.v1.json#/$defs/port` |  | TCP/UDP ports or ranges; omit for all ports. | - `maxItems 50` |
| `rules[].description` | string |  |  | - `maxLength 200` |
| `exit_node` | object \| null |  | Exit nodes are usable only by this tenant's devices; no public share may target one. |  |
| `subnet_routes` | array of object |  |  | - `maxItems 100`<br>- `items: no other fields` |
| `subnet_routes[].device_id` | string | yes |  | - `pattern ^dev_[0-9A-HJKMNP-TV-Z]{26}$` |
| `subnet_routes[].cidr` | string | yes |  | - `minLength 2`<br>- `maxLength 64` |
| `updated_by` | [identity.subject-ref](/docs/contracts/identity.subject-ref) |  |  |  |
| `created_at` | string | yes |  | - `format date-time` |
| `updated_at` | string | yes |  | - `format date-time` |

## Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

 Valid: home-mesh

~~~~
{
  "id": "pol_01J8Z3Q4R5S6T7V8W9X0Y1Z2A4",
  "owner": {
    "type": "user",
    "id": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A6"
  },
  "project_id": null,
  "tenant": {
    "type": "user",
    "id": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A6"
  },
  "name": "Home mesh",
  "version": 2,
  "default_action": "deny",
  "rules": [
    {
      "action": "allow",
      "sources": [
        "device:dev_01J8Z3Q4R5S6T7V8W9X0Y1Z2A8"
      ],
      "destinations": [
        "device:dev_01J8Z3Q4R5S6T7V8W9X0Y1Z2A8"
      ],
      "ports": [
        "443",
        "8000-8100"
      ],
      "description": "The owner's own devices reach each other."
    }
  ],
  "exit_node": {
    "enabled": false,
    "device_ids": []
  },
  "subnet_routes": [
    {
      "device_id": "dev_01J8Z3Q4R5S6T7V8W9X0Y1Z2A8",
      "cidr": "192.168.1.0/24"
    }
  ],
  "updated_by": {
    "type": "user",
    "id": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A6"
  },
  "created_at": "2026-10-29T08:00:00.000Z",
  "updated_at": "2026-10-29T09:00:00.000Z"
}
~~~~

Rejected: bad-port

~~~~
{
  "id": "pol_01J8Z3Q4R5S6T7V8W9X0Y1Z2A4",
  "owner": {
    "type": "user",
    "id": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A6"
  },
  "tenant": {
    "type": "user",
    "id": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A6"
  },
  "version": 1,
  "default_action": "deny",
  "rules": [
    {
      "action": "allow",
      "sources": [
        "*"
      ],
      "destinations": [
        "*"
      ],
      "ports": [
        "http"
      ]
    }
  ],
  "created_at": "2026-10-29T08:00:00.000Z",
  "updated_at": "2026-10-29T09:00:00.000Z"
}
~~~~

Rejected: bad-selector

~~~~
{
  "id": "pol_01J8Z3Q4R5S6T7V8W9X0Y1Z2A4",
  "owner": {
    "type": "user",
    "id": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A6"
  },
  "tenant": {
    "type": "user",
    "id": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A6"
  },
  "version": 1,
  "default_action": "deny",
  "rules": [
    {
      "action": "allow",
      "sources": [
        "everyone"
      ],
      "destinations": [
        "*"
      ]
    }
  ],
  "created_at": "2026-10-29T08:00:00.000Z",
  "updated_at": "2026-10-29T09:00:00.000Z"
}
~~~~

## Validate

~~~~
const contracts = require('openvibe-contracts');
contracts.validate('connect.policy@1', value);   // { valid, errors: [{ path, message }] }
~~~~
