NetworkMeConsentAppsResult network.me-consent-apps-result@1

Generated at from openvibe-contracts v0.419.0 and openvibe-sdk v0.161.0.

Version
1.0.0
Owner
network
Visibility
public
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/network/me-consent-apps-result.v1.json

network.me-consent-apps-result@1 (the consent plan's C4, 2026-11-07): "Apps you allowed" on the signed-in person's account page. GET /api/v1/me/consent/apps on OpenVibe.Network. It lists every app the person granted a purpose to on its sign-in screen (consent:<purpose>, network.consent-claim@1), with the purposes granted and those refused in the last 30 days. It also carries the words the app consent screen shows for each purpose. Only the person's own session reads it; an app never sees this list, its own entry included.

Fields

FieldTypeRequiredDescriptionConstraints
purposesarray of objectyesThe purposes an app may ask for, with the exact words the app consent screen shows.
  • maxItems 8
  • items: no other fields
purposes[].idenumyes
  • one of "ai.train", "data.public", "face.recognize", "app.data"
purposes[].titlestringyes
  • minLength 1
  • maxLength 80
purposes[].allowsstringyesWhat ticking it allows the app, in one plain line.
  • minLength 1
  • maxLength 300
purposes[].cannot_undostringyesWhat turning it off later cannot undo (empty when nothing).
  • maxLength 300
purposes[].adults_onlybooleanyesTicking it asks the person to confirm they are 18 or older.
purposes[].text_versionstringyes
  • pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]{1,3}$
appsarray of objectyesOne entry per app with a purpose granted or refused, apps with an active grant first, then by name.
  • maxItems 200
  • items: no other fields
apps[].clientstringyesThe app's OAuth client id.
  • pattern ^[A-Za-z0-9][A-Za-z0-9_.:-]{0,79}$
apps[].namestringyesThe app's name as its developer (or OpenVibe, for its own sites) registered it.
  • minLength 1
  • maxLength 120
apps[].third_partybooleanyesTrue for a developer's app (app_<ULID>), false for an OpenVibe site.
apps[].grantedarray of objectyesThe purposes the app holds now (active network.consent@1 records with this client).
  • maxItems 4
  • items: no other fields
apps[].granted[].consent_idstringyes
  • pattern ^cns_[0-9A-HJKMNP-TV-Z]{26}$
apps[].granted[].purposeenumyes
  • one of "ai.train", "data.public", "face.recognize", "app.data"
apps[].granted[].granted_atstringyes
  • format date-time
apps[].granted[].text_versionstringyes
  • pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]{1,3}$
apps[].quietarray of objectyesThe purposes the person refused this app in the last 30 days: the app does not ask for them again until quiet_until. DELETE /api/v1/me/consent/:purpose/:client/refusal ends that early, so the next sign-in asks.
  • maxItems 4
  • items: no other fields
apps[].quiet[].purposeenumyes
  • one of "ai.train", "data.public", "face.recognize", "app.data"
apps[].quiet[].refused_atstringyes
  • format date-time
apps[].quiet[].quiet_untilstringyes
  • format date-time

Examples

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

Valid: none
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": []
}
Valid: two-apps
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
Rejected: bad-client
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "not an app id!",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
Rejected: extra-key
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ],
      "refused": [
        "face.recognize"
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
Rejected: quiet-without-end
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
Rejected: retired-purpose
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.looks",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}

Validate

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