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

# vision.consent@1 · OpenVibe.Services

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

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

vision.consent@1: one consent record on OpenVibe.Vision. It says whose face or voice it is (\`subject\`), the modality, the purpose-scoped feature and scope (a channel or a library), who signed which text version, when it was granted, when it expires, and how and when it was revoked. Face matching tools refuse without an active record for that person, with the same answer whether or not the person exists. Templates are deleted when the purpose ends and at the latest three years after the last use (BIPA); a revoked audit record is deleted one year after the purpose ends (CUBI).

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `id` | string | yes |  | - `pattern ^fco_[0-9A-HJKMNP-TV-Z]{26}$` |
| `subject` | string | yes | The person whose face or voice this consent covers. | - `pattern ^usr_[0-9A-HJKMNP-TV-Z]{26}$` |
| `modality` | enum | yes |  | - `one of "face", "voice"` |
| `feature` | enum | yes |  | - `one of "verify", "find", "cast", "library", "voice"` |
| `scope` | string | yes | Empty means the person's own account; a cast grant names one channel, a library grant the library it applies to. | - `maxLength 160` |
| `purpose` | string | yes |  | - `maxLength 200` |
| `text_version` | string | yes |  | - `maxLength 80` |
| `granted_by` | string | yes | The person who signed; the subject themself, or a guardian where the law allows. | - `pattern ^usr_[0-9A-HJKMNP-TV-Z]{26}$` |
| `granted_at` | string | yes |  | - `format date-time` |
| `expires_at` | string \| null | yes | When the consent stops applying on its own; null when it lasts until revoked. | - `format date-time` |
| `last_used_at` | string | yes |  | - `format date-time` |
| `revoked_at` | string \| null | yes |  | - `format date-time` |
| `revoked_by` | enum | yes | How it was revoked: by the person, by the retention job, or with the account. | - `one of "subject", "retention", "account_deletion", null` |
| `purpose_ends_at` | string \| null | yes |  | - `format date-time` |
| `retention_until` | string | yes | The outer limit the record and derived data may exist: three years after last use, or one year after the purpose ended. | - `format date-time` |
| `status` | enum | yes |  | - `one of "active", "revoked", "expired"` |
| `erased` | boolean | yes | True once the template and derived results this consent covered are gone. |  |

## Examples

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

 Valid: one

~~~~
{
  "id": "fco_01J8Z3Q4R5S6T7V8W9X0Y1Z2A4",
  "subject": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A4",
  "modality": "face",
  "feature": "cast",
  "scope": "live:one",
  "purpose": "tag on named streams",
  "text_version": "face-cast-2026-10-28",
  "granted_by": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A4",
  "granted_at": "2026-10-29T10:00:00.000Z",
  "expires_at": "2027-10-29T10:00:00.000Z",
  "last_used_at": "2026-10-29T10:00:00.000Z",
  "revoked_at": null,
  "revoked_by": null,
  "purpose_ends_at": null,
  "retention_until": "2029-10-29T10:00:00.000Z",
  "status": "active",
  "erased": false
}
~~~~

Rejected: one

~~~~
{
  "id": "fco_1",
  "subject": "ana",
  "modality": "face",
  "feature": "cast",
  "scope": "live:one",
  "purpose": "x",
  "text_version": "v1",
  "granted_by": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A4",
  "granted_at": "2026-10-29T10:00:00.000Z",
  "expires_at": null,
  "last_used_at": "2026-10-29T10:00:00.000Z",
  "revoked_at": null,
  "revoked_by": null,
  "purpose_ends_at": null,
  "retention_until": "2029-10-29T10:00:00.000Z",
  "status": "active",
  "erased": false
}
~~~~

## Validate

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