---
title: "network.dock-state@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/network.dock-state"
updated: null
---

# network.dock-state@1 · OpenVibe.Services

HTML: [network.dock-state@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/network.dock-state)

# NetworkDockState `network.dock-state@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.1.0
- Owner: network
- Visibility: public
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/network/dock-state.v1.json`](/docs/contracts/network.dock-state.json)

network.dock-state@1 (the Dock plan 2026-10-30, K-D1): the state of one person's Dock — the little floating surface every OpenVibe site draws. It lives in the Network, not in the browser, because localStorage is per site and the Dock follows the person across every domain. GET /api/v1/me/dock and PUT /api/v1/me/dock on OpenVibe.Network.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `open` | boolean | yes | Whether the Dock is open (a sheet on a phone, a floating card on a desktop) or collapsed to its pill. |  |
| `tab` | enum | yes | Which of the Dock's tabs shows: Vibe (the person's AI, plan L48 V2), the agents, the chats, the activity. | - `one of "vibe", "agent", "chats", "activity"` |
| `pinned` | boolean | yes | Keep the pill on screen even when nothing runs and nothing waits. |  |
| `agent` | object \| null | yes | The agent the Agent tab follows, or null when it follows none. |  |
| `chat` | string \| null | yes | The conversation the Chats tab has open, or null. | - `minLength 1`<br>- `maxLength 80` |
| `vibe` | one of |  | The Vibe conversation selected across sites, and when the person last opened it. An older selection opens the list instead. |  |
| `agent_filter` | enum |  | The last Agents list filter chosen by this person. | - `one of "all", "running", "waiting", "scheduled", "done", "failed"` |
| `timer` | one of |  | The person's timer (plan L48 R2): it counts down in the Dock's pill on every site and rings at its end. Absent or null: none. A focus timer of rounds alternates focus and break by itself. |  |
| `place` | object | yes |  | - `no other fields` |
| `place.phone` | object | yes | Where the Dock sits on a phone. | - `no other fields` |
| `place.phone.corner` | enum | yes |  | - `one of "bottom-right", "bottom-left", "top-right", "top-left"` |
| `place.desktop` | object | yes | Where the Dock sits on a desktop, and how big it is (null: the site's own default size). | - `no other fields` |
| `place.desktop.corner` | enum | yes |  | - `one of "bottom-right", "bottom-left", "top-right", "top-left"` |
| `place.desktop.width` | integer \| null | yes |  | - `minimum 320`<br>- `maximum 720` |
| `place.desktop.height` | integer \| null | yes |  | - `minimum 360`<br>- `maximum 900` |
| `updated_at` | string | yes | When the state was last written. | - `format date-time` |

## Examples

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

 Valid: both-places

~~~~
{
  "open": false,
  "tab": "chats",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "top-right"
    },
    "desktop": {
      "corner": "top-right",
      "width": 320,
      "height": 360
    }
  },
  "updated_at": "2026-10-30T12:00:00Z"
}
~~~~

Valid: default

~~~~
{
  "open": false,
  "tab": "activity",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "bottom-right"
    },
    "desktop": {
      "corner": "bottom-right",
      "width": null,
      "height": null
    }
  },
  "updated_at": "2026-10-30T12:00:00Z"
}
~~~~

Valid: focus-timer

~~~~
{
  "open": false,
  "tab": "activity",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "bottom-right"
    },
    "desktop": {
      "corner": "bottom-right",
      "width": null,
      "height": null
    }
  },
  "updated_at": "2026-10-30T12:00:00Z",
  "timer": {
    "kind": "focus",
    "label": "Write the post",
    "started_at": "2026-11-01T09:00:00Z",
    "ends_at": "2026-11-01T09:25:00Z",
    "round": 1,
    "rounds": 4,
    "focus_min": 25,
    "break_min": 5
  }
}
~~~~

Valid: pinned

~~~~
{
  "open": true,
  "tab": "agent",
  "pinned": true,
  "agent": {
    "service": "actor",
    "id": "tsk_01JAB2C3D4E5F6G7H8J9K0MNPQ"
  },
  "chat": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "place": {
    "phone": {
      "corner": "top-left"
    },
    "desktop": {
      "corner": "bottom-left",
      "width": 420,
      "height": 640
    }
  },
  "updated_at": "2026-10-30T12:00:00Z"
}
~~~~

Valid: vibe-tab

~~~~
{
  "open": true,
  "tab": "vibe",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "bottom-right"
    },
    "desktop": {
      "corner": "bottom-right",
      "width": null,
      "height": null
    }
  },
  "updated_at": "2026-10-30T12:00:00Z"
}
~~~~

Rejected: extra-key

~~~~
{
  "open": false,
  "tab": "activity",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "bottom-right"
    },
    "desktop": {
      "corner": "bottom-right",
      "width": null,
      "height": null
    }
  },
  "updated_at": "2026-10-30T12:00:00Z",
  "theme": "neon-tokyo"
}
~~~~

Rejected: timer-kind

~~~~
{
  "open": false,
  "tab": "activity",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "bottom-right"
    },
    "desktop": {
      "corner": "bottom-right",
      "width": null,
      "height": null
    }
  },
  "updated_at": "2026-10-30T12:00:00Z",
  "timer": {
    "kind": "nap",
    "started_at": "2026-11-01T09:00:00Z",
    "ends_at": "2026-11-01T09:25:00Z"
  }
}
~~~~

Rejected: unknown-tab

~~~~
{
  "open": false,
  "tab": "profile",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "bottom-right"
    },
    "desktop": {
      "corner": "bottom-right",
      "width": null,
      "height": null
    }
  },
  "updated_at": "2026-10-30T12:00:00Z"
}
~~~~

Rejected: width-2000

~~~~
{
  "open": false,
  "tab": "activity",
  "pinned": false,
  "agent": null,
  "chat": null,
  "place": {
    "phone": {
      "corner": "bottom-right"
    },
    "desktop": {
      "corner": "bottom-right",
      "width": 2000,
      "height": 640
    }
  },
  "updated_at": "2026-10-30T12:00:00Z"
}
~~~~

## Validate

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