MediaUsageRecordedPayload media.usage.recorded@1
Generated at from
openvibe-contracts v0.177.0 and
openvibe-sdk v0.44.0.
- Version
- 1.0.0
- Owner
- media
- Visibility
- first-party
- Status
- active
- Compatibility
- backward
- Decision
- ADR-014
- Schema
https://openvibe.network/contracts/events/payloads/media.usage.recorded.v1.json
media.usage.recorded v1 (ADR-031 amendment 2026-10-02, section 8). One closed hour of one zone's use on OpenVibe.Media's S3 surface: resource is the zone's OVRN (ovrn:zone:<project_id>:object-zone/<zon_id>) and dimension the zone id in lowercase, on every rollup. The series: stored bytes (media.object.upload, unit byte_hours: the live objects' bytes summed over the hour, sampled each minute), writes (media.object.upload and media.object.delete, unit requests), lists (media.object.list, unit requests), reads (media.object.read, unit requests) and egress (media.object.read, unit egress_bytes). errors counts the operations refused or failed in the hour, by S3 error code mapped to media.s3.<code>. Media counts as it answers and stores the rollup as its own event after the hour closes, in the same transaction that marks the hour sent; a corrected hour is re-sent with a higher revision. Rollups are counts for dashboards and quotas, never money. The payload is common.usage-recorded@1. Envelope: source media, subject { type: project, id: <project_id> }, visibility internal, priority low, actor service:media.
Fields
This schema has no named fields.
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: egress
{
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"resource": "ovrn:zone:prj_01JAB2C3D4E5F6G7H8J9K0MNPQ:object-zone/zon_01JAB2C3D4E5F6G7H8J9K0MNPR",
"dimension": "zon_01jab2c3d4e5f6g7h8j9k0mnpr",
"window": "hour",
"window_start": "2026-10-15T10:00:00.000Z",
"window_end": "2026-10-15T11:00:00.000Z",
"capability": "media.object.read",
"unit": "egress_bytes",
"quantity": 104857600,
"errors": 0,
"revision": 2
}Valid: reads-with-errors
{
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"resource": "ovrn:zone:prj_01JAB2C3D4E5F6G7H8J9K0MNPQ:object-zone/zon_01JAB2C3D4E5F6G7H8J9K0MNPR",
"dimension": "zon_01jab2c3d4e5f6g7h8j9k0mnpr",
"window": "hour",
"window_start": "2026-10-15T10:00:00.000Z",
"window_end": "2026-10-15T11:00:00.000Z",
"capability": "media.object.read",
"unit": "requests",
"quantity": 420,
"errors": 3,
"error_codes": {
"media.s3.no_such_key": 2,
"media.s3.access_denied": 1
},
"samples": [
{
"at": "2026-10-15T10:42:10.000Z",
"code": "media.s3.no_such_key",
"status": 404
}
]
}Valid: stored-byte-hours
{
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"resource": "ovrn:zone:prj_01JAB2C3D4E5F6G7H8J9K0MNPQ:object-zone/zon_01JAB2C3D4E5F6G7H8J9K0MNPR",
"dimension": "zon_01jab2c3d4e5f6g7h8j9k0mnpr",
"window": "hour",
"window_start": "2026-10-15T10:00:00.000Z",
"window_end": "2026-10-15T11:00:00.000Z",
"capability": "media.object.upload",
"unit": "byte_hours",
"quantity": 5368709120,
"errors": 0
}Rejected: carries-an-object-key
{
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"resource": "ovrn:zone:prj_01JAB2C3D4E5F6G7H8J9K0MNPQ:object-zone/zon_01JAB2C3D4E5F6G7H8J9K0MNPR",
"dimension": "zon_01jab2c3d4e5f6g7h8j9k0mnpr",
"window": "hour",
"window_start": "2026-10-15T10:00:00.000Z",
"window_end": "2026-10-15T11:00:00.000Z",
"capability": "media.object.upload",
"unit": "requests",
"quantity": 1,
"errors": 0,
"object_key": "photos/me.jpg"
}Rejected: resource-of-a-person
{
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"resource": "ovrn:network:prj_01JAB2C3D4E5F6G7H8J9K0MNPQ:account/usr_01JAB2C3D4E5F6G7H8J9K0MNPS",
"dimension": "zon_01jab2c3d4e5f6g7h8j9k0mnpr",
"window": "hour",
"window_start": "2026-10-15T10:00:00.000Z",
"window_end": "2026-10-15T11:00:00.000Z",
"capability": "media.object.read",
"unit": "requests",
"quantity": 1,
"errors": 0
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('media.usage.recorded@1', value); // { valid, errors: [{ path, message }] }