Capabilities

Generated at from openvibe-contracts v0.218.0 and openvibe-sdk v0.65.0.

A capability is an action a principal may invoke, checked at the owning service against the token's grants. Highlighted rows can be granted to apps: only active capabilities whose visibility is public (or partner, when staff put one in a project's allowance). first-party and internal capabilities are never granted to apps.

CapabilityOwnerVisibilityStatusDescriptionQuota class
actor.agent.manage grantableactorpublicactiveKeep your personal agents on OpenVibe.Actor: create, read, change and delete an agent (standing instructions, mode, a budget per run, a daily run cap and a schedule), read, add, edit and delete what it remembers, or forget everything, and read what it suggested adding to its instructions and apply, dismiss or undo a suggestion. A person's agents are theirs alone; another person's agent is 404.actor-task
actor.agent.read grantableactorpublicactiveThe agent systems Actor routes to, with what each can do, its trust class, its rate card and whether it is available now (GET /api/v1/agents, actor.agent-list-result@1), and which one a task would go to in a mode, with the reason for every candidate (POST /api/v1/route { task, mode }, a platform.placement-result@1; nothing runs). Public; no token needed.actor-read
actor.agent.run grantableactorpublicactiveRun one of your personal agents now, and list its runs. A run is an ordinary Actor task (platform.task@1) under the same routing, checking, metering, free tier and budgets as a task you give directly, plus the agent's own daily run cap; scheduled runs use the same path.actor-task
actor.task.create grantableactorpublicactiveGive OpenVibe.Actor a task: POST /api/v1/tasks with the task in plain words, a mode (cheapest, balanced, best, fastest, private) and a budget. Actor picks the agent system for it with openvibe-sdk/placement, runs it, has a second model family check the result, and records the result, the cost to the cent and the explanation on the task (platform.task@1, answered 201 with state queued). POST /api/v1/tasks/:id/cancel stops a task that has not ended. A person's tasks are theirs; a token that names a project puts the task in that project. Each person has a daily free allowance; a task whose cheapest eligible agent would cost more than its budget fails with actor.budget.exceeded instead of running. A task may register webhooks: Actor POSTs actor.task-webhook@1 to each on the state changes it asked for, signed with a secret minted for the task and returned once, as webhook_secret, in the answer that created it.actor-task
actor.task.list grantableactorpublicactiveList your latest tasks, newest first (GET /api/v1/tasks?limit=&before=): each as platform.task@1, with a cursor for the next page.actor-read
actor.task.read grantableactorpublicactiveRead one of your tasks (platform.task@1: state, result, cost, explanation) with GET /api/v1/tasks/:id, and watch it live with GET /api/v1/tasks/:id/events: text/event-stream of actor.task-event@1 (state changes, the agent's steps, the end), resumable with Last-Event-ID. Only the task's requester (or its project's tokens) can read it.actor-read
ai.app.run grantableaipublicactiveRun the AI operations as a developer app (ADR-014): POST /api/v1/chat, /generate, /summarize, /classify, /extract, /embed and GET /api/v1/runs/:id for the app's own runs. The app token (sub app:app_<ULID>, project_id prj_<ULID>, env sandbox|production, audience openvibe.ai) runs as its project: every run is metered (platform.usage-sample@1 to OpenVibe.Billing, subject project:prj_<ULID>) against the project's bounded free allowance, and metered capacity is spent only under the project's tier budget; a sandbox run, and every run no tier budget governs, uses only free and local capacity. An app runs only these operations (never a workflow by key), never reads another project's runs, and never uses a person's BYO provider key.ai-app-run
blog.feed.read grantableblogpublicactiveRead a blog's JSON Feed through the API (public, published, listable posts only; the same items as /@handle/feed.json). Browsers and crawlers read the public RSS, Atom and JSON Feed URLs without any capability.blog-read
blog.post.create grantableblogpublicactiveCreate a draft post (revision 1) on a blog the acting member belongs to. With X-OV-Origin: ai the draft is AI-generated output (OpenVibe.AI blog.draft_post; authorship.workflow { id, runId } required): never attributed to the person, noindex, and not publishable until a person reviews it.blog-write
blog.post.delete grantableblogpublicactiveDelete a post: readers get 410, Search a tombstone, the Community thread is hidden; immutable revisions are kept. Editors, owners, the author, and staff (moderation).blog-write
blog.post.publish grantableblogpublicactiveMake a revision the published one (idempotent). AI-generated revisions are refused (409 post.review_required) until a person has recorded an approving review.blog-write
blog.post.read grantableblogpublicactiveRead posts that are not public (drafts, scheduled, members-only, private), their revisions and diffs, for the member in X-OV-Subject. Published public posts need no capability.blog-read
blog.post.schedule grantableblogpublicactiveSchedule a publish of a revision (or an unpublish) at a future time, or cancel it. Idempotent per (post, action, time, revision); applied by Blog's worker with leases, so a restart never publishes twice; a job that cannot succeed emits blog.schedule.failed.blog-write
blog.post.unpublish grantableblogpublicactiveTake a published post down (readers get 404, Search a tombstone, feeds and sitemaps drop it). Editors, owners, the author, and staff (moderation).blog-write
blog.post.update grantableblogpublicactiveEdit a post: content becomes a new immutable revision (expected_revision required; 412 revision.conflict when someone saved first), slug changes leave 301 redirects, visibility, taxonomy, series, media attachments (OpenVibe.Media object ids) and revert as a new revision. Authors edit their own posts; editors and owners every post of the blog.blog-write
chat.inbox.manage grantablechatpublicactiveSet up support inboxes for the person on OpenVibe.Chat: make one (it is theirs), and as its owner change it (name, greeting, colour, Vibe and its instructions and pages, allowed sites, hours, routing, retention), add and remove its people, keep saved replies, and connect webhooks, actions (endpoints Vibe may call) and verified visitors. Secrets are shown only on the answer that made them. Deleting an inbox archives it.chat-inbox-manage
chat.inbox.read grantablechatpublicactiveRead the support inboxes the person works in on OpenVibe.Chat (docs/platform.md): the inboxes, each one's conversations (waiting first) and messages, and its saved replies; the owner also exports every conversation (JSON or CSV). Visitors' messages are people's words to a team, so an app sees only inboxes its person works in, and the person's own role decides the rest (the export is the owner's).chat-inbox-read
chat.inbox.reply grantablechatpublicactiveAnswer visitors for the person in a support inbox they work in on OpenVibe.Chat: reply in a conversation (it becomes open, Vibe stays quiet in it), resolve, reopen or give it back to Vibe, assign it to one of the inbox's people, mark it read, and translate a visitor's message or a reply. The reply is the person's, under their name.chat-inbox-reply
community.paste.create grantablecommunitypublicactiveCreate a paste (text or screenshot). A service token creates it for the acting subject named in X-OV-Subject, or as origin "ai" for derived pastes (roadmap 33).community-write
community.post.create grantablecommunitypublicactiveForum writes as a service: create threads and replies in a space, vote on threads, and edit or delete one's own posts, as the acting subject (X-OV-Subject) or as origin "ai" (no author, labelled as AI). Space visibility (public, members, staff), locks and limits are checked by Community.community-write
community.pulse.read grantablecommunitypublicactiveRead the network's public activity feed (Pulse): entity reference, title, URL and origin (user, ai or system), newest first with a cursor. Only public items are ever stored. Served to anyone (CORS allow-list for browsers). Live's /api/home/pulse is a different, Live-only feed.community-read
community.space.read grantablecommunitypublicactiveList the spaces the caller can open and read one space's metadata (roadmap §30.2 community.space.*). Anonymous callers see public spaces, signed-in people also members spaces, moderators also staff spaces; members-only (VIP) spaces are flagged. Served to anyone; Community checks space visibility itself.community-read
community.thread.read grantablecommunitypublicactiveRead a space's threads (hot, new or top, paged) and one thread with its posts, plus the RSS feeds. Community checks space visibility and the VIP gate (403 vip.members_only). Creating threads and replies stays community.post.create.community-read
coupons.coupon.lookup grantablecouponspublicactiveRead a merchant's active codes (status, confidence, report aggregates, restrictions, expiry or unknown, evidence) or one code. Public data only, the same response for every caller; anonymous callers may use the routes with tighter rate limits. The charter's coupons.lookup.coupons-lookup
coupons.coupon.submit grantablecouponspublicactiveSubmit a coupon code for a merchant (by merchant id, host or URL) on behalf of a person (X-OV-Subject) or as AI output (X-OV-Origin: ai, held for staff review). The code starts with status unknown; a status, confidence or 'verified' field is refused. A site no merchant covers becomes a pending merchant for staff review. The charter's coupons.submit.coupons-write
coupons.merchant.resolve grantablecouponspublicactiveResolve a hostname to an active merchant (normalized host, eTLD+1 from a bundled public-suffix subset, subdomain rules; path rules never match host-only lookups). Public data only; anonymous callers may use the route with tighter rate limits.coupons-lookup
coupons.report.create grantablecouponspublicactiveReport that a code worked or failed, on behalf of a person (X-OV-Subject). One report per person, code and UTC day; only the latest per person counts; rate-limited per person; AI output (X-OV-Origin: ai) is refused. The response carries aggregates only, never a reporter. The charter's coupons.report.coupons-report
deals.flag.create grantabledealspublicactiveReport a problem with an offer for the acting person (expired, price_wrong, duplicate, spam, other). One open report per person and offer; rate-limited. Flags never change an offer by themselves.deals-write
deals.offer.submit grantabledealspublicactiveSubmit a deal for the acting person (X-OV-Subject): a link, title and what the person sees now (price with its currency, shipping, condition, availability — each optional, never defaulted). The first observation is recorded with its time. A link already posted answers 409 offer.duplicate with the existing offer. With X-OV-Origin: ai the text is AI-assisted: disclosed and noindex until a person reviews it. Rate-limited per person.deals-write
deals.offer.update grantabledealspublicactiveEdit an offer the acting person submitted (title, description, category, stated expiry, product link), or record a new observation of any active offer for the acting person (POST …/observations: price with currency, shipping, condition, availability, with the time it was observed). Prices are never edited in place; each observation is a new row. Services may state observed_at (never in the future).deals-write
deals.vote.remove grantabledealspublicactiveRemove the acting person's vote on an offer (kept as a removed row for history). Same abuse controls as deals.vote.set.deals-vote
deals.vote.set grantabledealspublicactiveSet the acting person's vote (+1 / -1) on an offer. Server-authoritative: weight and hotness are computed by Deals (hot@1), never taken from the request. Rate-limited per person, per IP hash and per offer; no votes on one's own offer; vote-ring detection flags moderators.deals-vote
deals.watch.create grantabledealspublicactiveCreate a keyword, product or price-below watch, or a saved search (never notifies), for the acting person. A watch notifies at most once per observation (deals.watch.matched, internal; Deals never emails).deals-write
deals.watch.delete grantabledealspublicactiveDelete one of the acting person's watches or saved searches.deals-write
deals.watch.read grantabledealspublicactiveList the acting person's watches and saved searches with their notification counts.deals-read
events.app.publish grantableeventspublicactivePublish durable events (events.event-envelope@1) as a developer app (ADR-014). The app token (sub app:app_<ULID>, project_id prj_<ULID>, env) may publish only event types app.<project_key>.<name>[.<more>], where project_key is 'p' followed by the project's ULID in lowercase (prj_01JAB... -> p01jab...). source must be 'app-' followed by the app's ULID in lowercase; actor is the app (or the on_behalf_of user). Events stores the token's env with each event: sandbox events are never delivered to production subscriptions nor shown to production apps. Rate and retained bytes are limited per project and environment by OpenVibe.Events.events-app-publish
events.app.read grantableeventspublicactivePull events as a developer app (ADR-014): only the app's own project's events (app.<project_key>.*, same environment as the token) plus first-party platform events with visibility public. Topic patterns must start with a literal segment; app.* patterns must name the caller's own project_key. Checkpoints are stored per app.events-app-read
events.app.subscribe grantableeventspublicactiveManage webhook subscriptions as a developer app (ADR-014). Topic patterns are limited to the scope of events.app.read (own project's app.<project_key>.* events in the token's environment, plus public platform events). Endpoints must be https URLs whose host resolves only to public IP addresses; OpenVibe.Events re-checks the resolved address when it delivers and never follows redirects. Deliveries are signed with the subscription secret (X-OpenVibe-Signature: sha256=<HMAC of the raw body>). Subscriptions carry project_id and env; sandbox events reach sandbox subscriptions only.events-app-subscribe
food.pantry.read grantablefoodpublicactiveRead a caller's pantry with the suggestions matched against it: GET /api/v1/pantry → { items, foods, suggestions: { can_make, almost }, note }. The suggestions are deterministic matches against basic recipes, not dietary advice.food-read
food.pantry.write grantablefoodpublicactiveReplace a caller's pantry with exactly this list: PUT /api/v1/pantry with { items: [food slug, …] } (at most 200, each one in the food list; GET /api/v1/foods lists them). Answers like a read.food-write
food.plan.read grantablefoodpublicactiveRead the plans a caller saved: GET /api/v1/plans (newest first, ?limit to 50) → { plans }, and GET /api/v1/plans/:id → one plan. Only the person who saved a plan (or their tokens) can read it.food-read
food.plan.write grantablefoodpublicactivePlan a shop for a household and a budget and save it: POST /api/v1/plans with { people, days, budget?, title? }. Food picks budget items from its food list to cover each food group for every person and day, splits them by the cheapest store and lays out a menu; the saved plan (201, Location /api/v1/plans/:id) is the caller's own.food-write
food.recipes.suggest grantablefoodpublicactiveRecipe ideas from the caller's saved pantry: POST /api/v1/recipes/suggest runs OpenVibe.AI's food.suggest_recipes workflow for the caller (up to three recipes; ingredients from the pantry or cited to Food's food list; what is still to buy priced from Food's own typical prices), 10 a person a day; GET /api/v1/recipes lists the last 20. A person acting for themself needs no capability; an app or agent token needs this one.standard
games.mod.read grantablegamespublicactiveRead the browser game's installed mods: manifest, content pack, status, trust tier, requested and granted capabilities. Public; no token needed.games-read
games.player.message grantablegamespublicactiveScript binding for mods (games-quickjs@1): game.message, a validated private announcement to one player in the mod's current place, prefixed with the mod's name. Absent unless granted.games-mod-runtime
games.players.read grantablegamespublicactiveScript binding for mods (games-quickjs@1): game.players and game.player, read-only views of the players in the mod's current place. Absent from the script's game object unless the install was granted it; checked against the install's approved capabilities, which travel in the def-set digest.games-mod-runtime
games.prop.place grantablegamespublicactiveRuntime binding for mods (games-content@1): place and remove inert props (existing content items without health, storage, shop, machine or vehicle-part capabilities) in the world, owned by the mod so players cannot pick them up or move them. The props exist only while the capability is granted and the install enabled: revoking either despawns them on the next tick.games-mod-runtime
games.script.run grantablegamespublicactiveRun a staff-installed script mod (games-quickjs@1, one or more module files in its content pack, imports resolved inside the pack only) in its own QuickJS sandbox per place, under the pack's CPU and memory budgets; a staff hot reload replaces the code and keeps its storage, and a reload that fails to start keeps the previous version running. The script sees only the bindings its install was granted.games-mod-runtime
games.storage.kv grantablegamespublicactiveScript binding for mods (games-quickjs@1): game.storage get/set/delete/keys, key/value storage per mod per place on the Games database: keys up to 128 bytes, values up to 8 KB of JSON, at most 1000 keys and 1 MB per mod per place, writes counted against the mod's CPU budget; a refusal is an error inside the mod. Absent unless granted.games-mod-runtime
games.world.announce grantablegamespublicactiveRuntime binding for mods (games-content@1): broadcast a short server announcement to every player in the world, prefixed with the mod's name, at most once a minute per announcement. Checked at call time against the install's approved capabilities; a revoked grant stops it on the next tick.games-mod-runtime
games.world.emit grantablegamespublicactiveScript binding for mods (games-quickjs@1): game.emit, which queues world intents that the server validates like any player intent before applying them; a mod never mutates state directly. Absent unless granted.games-mod-runtime
inventory.equip.manage grantableinventorypublicactiveEquip or clear a slot with an instance the person owns (PUT /api/v1/me/equipped with inventory.equip-request@1 → inventory.equipped@1). One item per slot. Refuses an instance not owned or not in state owned (409 inventory.not_owned).inventory-write
inventory.item.list grantableinventorypublicactiveThe person's own full inventory, consumed and revoked instances included (GET /api/v1/me/items → inventory.inventory@1). A service may read it acting for the person (on_behalf_of).inventory-read
inventory.item.read grantableinventorypublicactiveRead a person's public inventory (GET /api/v1/people/:subject/items → inventory.inventory@1: owned instances of published definitions), their equipped set (GET /api/v1/people/:subject/equipped, GET /api/v1/equipped?subjects=… up to 100 → inventory.equipped-batch@1), definitions and kinds.inventory-read
live.channel.read grantablelivepublicactiveRead a channel's public profile by username (the /@username page's data): metadata, owner display fields, follower count, live streams with playback endpoints, slots, and its public VODs and clips from Media. The owner and staff also see private listings; ingest keys are never returned. Anonymous callers are served (optionalAuth); no grant is checked at Live's boundary, and /api allows only OpenVibe origins for browsers. There is no public lookup by channel id yet (roadmap §30.2, sdk-live).live-read
live.discovery.read grantablelivepublicactiveRead Live's discovery surfaces (roadmap §30.2 live.discovery.*): the featured rotation, "watch instead" picks, the star of the day, the digest, home numbers, recently online streamers, recent VODs, and the content and AI-moments feeds. Public items only. There is no category directory and no channel search route yet; channel search belongs to OpenVibe.Search once Live publishes index documents.live-read
live.stream.read grantablelivepublicactiveRead broadcasts: who is live now with viewer counts, one stream with its endpoint, cameras and controls, recently ended streams with their public VOD, a slot's current session, and the went-live stream (/api/live-events, open CORS). Stream keys and the home ZIP are redacted. Anonymous callers are served; no grant is checked at Live's boundary (roadmap §30.2, sdk-live).live-read
media.object.delete grantablemediapublicactiveDelete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that period (checked against the namespace's quotas); refused while the object is under a retention hold. The same verb guards the v1 file delete (DELETE /api/v1/:app/files/:key). media.object.upload also grants it, for tokens issued before the verbs were split, unless the namespace's policy is strict_verbs.media-write
media.object.list grantablemediapublicactiveList the objects of a namespace (the list verb of Media's namespace grants, WS-G task 2): a Network token sees only the namespaces its ns covers, and ?namespace= narrows the list to one namespace and those below it. The same verb guards the job list (GET /api/v2/:app/jobs), the namespace list with quotas and usage (GET /api/v2/:app/namespaces) and the v1 file list (GET /api/v1/:app/files). media.object.read also grants it, for tokens issued before the verbs were split, unless the namespace's policy is strict_verbs.media-read
media.object.read grantablemediapublicactiveRead object metadata / bytes in a namespace.media-read
media.object.s3 grantablemediapublicactiveOpenVibe.Media's S3 surface (ADR-031), path style at https://s3.openvibe.media/<zone name>/<key>: PutObject (one request, aws-chunked bodies included, Content-MD5 and x-amz-checksum-* checked), GetObject (ranges), HeadObject, DeleteObject, DeleteObjects, ListObjectsV2 and ListObjects (prefix, delimiter, pages), ListBuckets, HeadBucket, GetBucketLocation, and presigned GET and PUT (SigV4 query, 7 days at most). multipart uploads (CreateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUpload, ListParts, ListMultipartUploads; every part but the last at least 5 MiB, parts of 256 MB and objects of 20 GB at most by default, 10000 parts, an upload expiring after a day). CopyObject and UploadPartCopy, server-side within the key's environment: the source (x-amz-copy-source) is read with the same key, COPY keeps its type and metadata and REPLACE takes the request's, the x-amz-copy-source-if-* conditions hold, a part may be a byte range (x-amz-copy-source-range), and the destination is written through the same commit path (quota, holds, the previous object's deletion). Everything else answers NotImplemented (ACLs, policies, versioning, a versionId copy source; buckets are made and deleted only through OpenVibe.Zone). It is reached with a media.access-key@1 rather than a Network token: the key fixes the project and environment, so a bucket name names one zone of that environment, and a key scoped to zones reaches only those. A request is authorised as the project's app would be: the same quotas (the zone's and the environment's), the same objects as the native API, and Media's one deletion path (a held object is neither deleted nor overwritten). Responses carry a sandbox Content-Security-Policy.standard
media.object.upload grantablemediapublicactiveUpload a file object into an app namespace.media-upload
play.player.read grantableplaypublicactiveRead one player's unlocked achievements in a title the caller manages (GET /api/v1/titles/:title/players/:player/achievements): how a game shows a guest or a person what they have. The boards and titles themselves are public reads that need no capability.standard
play.result.write grantableplaypublicactivePost what players did in a title the caller manages: scores for a round to one of its boards (POST /api/v1/titles/:title/scores, up to 100 entries, idempotent by ref), achievements unlocked by a player (POST /api/v1/titles/:title/unlocks, answering the new ones), and a guest's progress moved to the person who signed in (POST /api/v1/titles/:title/players/:guest/adopt). A player is a person's subject (usr_) or a guest the title names (guest:<opaque>).play-write
play.title.manage grantableplaypublicactiveRegister or update a title the caller manages on OpenVibe.Play (PUT /api/v1/titles/:title): its name, address and summary, its achievements (id, name, description, hidden) and its leaderboards (id, name, kind best or sum). The principal that registers a title is its only writer; another one is told it does not exist (404) or, registering it, 409 play.title_taken. A definition left out is retired, never deleted: what players earned stays. A board's kind never changes (409 play.board_kind_fixed).play-define
quest.app_quest.manage grantablequestpublicactiveDefine your app's own quests on OpenVibe.Quest (the SDK's moddable quests): PUT /api/v1/app-quests/:slug with quest.app-quest-request@1 creates or replaces one (at most 20 per project), GET /api/v1/app-quests lists your project's, DELETE /api/v1/app-quests/:slug retires one (its completions and badges stay). Steps count the project's own events app.<project_key>.<name> at OpenVibe.Events whose actor is a person; only production events count. The reward is a badge named for your app; app quests never pay OpenCoins.quest-app-write
reviews.correction.submit grantablereviewspublicactiveSend a correction (about an entity, alias, signal, summary or aggregate, with an optional evidence URL) to the editors' queue on behalf of the person named in X-OV-Subject. Corrections are read by editors and not published.reviews-corrections
reviews.entity.resolve grantablereviewspublicactiveResolve a name, URL, GTIN/SKU/MPN, source binding or external id to an entity (deterministic rules; a name alone yields candidates, never a match), read entity pages as JSON (aggregate with inputs, signals with provenance, summary), their history and summary revisions, and — for an editor named in X-OV-Subject — read the resolution queue and confirm or ignore an ambiguous source item.reviews-read
run.job.cancel grantablerunpublicactiveCancel one of the token project's jobs: POST /api/v1/jobs/:id/cancel. A queued or placed job never starts; a running one is killed (platform.job-frame@1 job_cancel); cancelling an ended job changes nothing and answers it as it is.run-control
run.job.list grantablerunpublicactiveList the token project's jobs, newest first and cursor-paged: GET /api/v1/jobs?state=&limit=&cursor=.run-read
run.job.read grantablerunpublicactiveRead one of the token project's jobs: GET /api/v1/jobs/:id (state, placement, timings, exit, usage seconds, result).run-read
run.job.stream grantablerunpublicactiveWatch a job's live output: POST /api/v1/jobs/:id/stream/ticket mints a one-use, two-minute stream ticket (run.job-stream-ticket-result@1) and GET /api/v1/jobs/:id/stream?ticket= (or with a Bearer token) is text/event-stream of run.job-stream-event@1, resumable with Last-Event-ID.run-stream
run.job.submit grantablerunpublicactiveSubmit a job to OpenVibe.Run: POST /api/v1/jobs. The job belongs to the token's project, which is billed per wall-clock second it runs (service run, operation function.invoke, unit s). An idempotency_key makes a retry return the first job.run-submit
search.query.run grantablesearchpublicactiveQuery the network index as anyone (roadmap §30.2 search.query, search.suggest, search.facets.read): anonymous callers get public, published documents only, and a signed-in person's Network token adds the documents whose access list names them or their role. Covers title suggestions, facet counts (facets=, facet.<key>=) and reading one document; a document the caller may not see is the same 404 as a missing one. Served publicly at search.openvibe.network. A first-party service asking for a person uses search.query.delegate (today Search requires that id for any service token).search-query
services.release.manage grantableservicespublicactiveAn app manages release metadata for ITSELF with its own token (audience openvibe.services): create a release from a validated app or mod manifest, publish, deprecate (with a reason and an optional replacement) and revoke it. The token's sub must be app:<the app in the path>; people manage releases in the console at openvibe.services with their project role instead. Trust tiers are not part of this capability (staff metadata only).services-release-write
services.release.read grantableservicespublicactiveRead public release metadata: an app's published, deprecated and revoked releases with their manifests, compatibility ranges and the app's trust tier (metadata only; it never grants anything). Drafts are never returned. Public; no token needed.services-read
space.deploy.create grantablespacepublicactiveUpload an immutable static deploy (tar/tar.gz or multipart files; validated for path traversal, links, special and hidden files, server-side code, file types and quotas; never executed), list deploys and their upload logs, activate a deploy and roll a site back to any earlier ready deploy (one atomic pointer switch). Also judged by the acting principal's project role (deployer or above); an app principal added to a project as deployer can deploy from CI. A site with a Git source also accepts a CI-built deploy at /sites/:id/source/deploys naming the ref and full commit_sha; it is always a preview and records that commit as immutable provenance.space-deploy
space.domain.manage grantablespacepublicactiveAdd a custom domain to a static site (never an OpenVibe domain; not in sandbox projects), read its DNS TXT verification and routing records, trigger a verification check, and remove it. A custom domain is served only after its TXT record is verified; TLS certificates are issued by an operator and never pass through this capability.space-manage
space.site.config grantablespacepublicactiveRead, set and reset a Host site's serving configuration: response headers, local-only redirects and the SPA fallback (extensionless paths serve index.html). A capability holder must also hold the acting principal's project role (maintainer or owner to change, any role to read). Reserved headers (Content-Security-Policy, Strict-Transport-Security, Set-Cookie, X-Forwarded-*, caching, scope, transport and the platform's own) are refused, and a redirect target must be a local path, so a site can never become an open redirect.space-manage
space.site.manage grantablespacepublicactiveManage OpenVibe.Space tenant projects and static sites: create a project (owned by the person named with X-OV-Subject; apps cannot own projects), read projects, quotas and usage, manage members (owner role), create and delete sites, delete a deploy that is not active. Also judged by the acting principal's project role; a sandbox token (env=sandbox) is refused on production projects. Quota changes and takedowns (stop serving a site or a whole project while keeping its content for review; lift) additionally need a Network staff user. Read, set or remove a site's Git source (provider, public repository URL and branch; never a credential).space-manage
tools.job.cancel grantabletoolspublicactiveCancel a queued or running job the calling principal created.tools-job
tools.job.create grantabletoolspublicactiveSubmit an asynchronous tool job (img.process, audio.process, docs.process) with its input files (tools.job-request@1, JSON or multipart); the job is owned by the calling principal. Idempotency-Key supported. Also the owner's other writes on a job: retry a failed job as a new one (idempotent: asking again returns that retry), and keep a succeeded job's result while a reference such as community:paste:p_123 points at it (PUT), or let it expire again (DELETE, after the last reference).tools-job
tools.job.read grantabletoolspublicactiveRead a job the calling principal created: state, progress, result (Media object references or local files), SSE progress with Last-Event-ID resume, result files.tools-read
tools.net.probe grantabletoolspartneractiveRun the network probe tools through the run API (ADR-027): the tools whose descriptor names auth.capability tools.net.probe (port checks, ping, traceroute, mtr, latency, bulk header and TLS checks), which send traffic to a host the caller chose. Only app and service principals holding this capability run them through the API or the SDK: partner visibility, so Network grants it to a developer project only when staff add it to that project's allowance by hand, and first-party services hold it through their own grants. People keep using the probe pages, which have a per-target throttle. Every run is throttled per target across all callers (limits.perTargetPerMinute) and written to the pseudonymous abuse log. Planned until the gateway serves the route.tools-probe
tools.tool.read grantabletoolspublicactiveRead the tool registry (ADR-027): every tool's descriptor (tools.tool@1: execution, whether the run API exposes it, how to call it, input and output schemas, files, limits, auth, quota class, cost, egress, hosts, docs), filtered by family, execution, api, status or text. GET /api/v1/tools answers tools.tool-list@1 with schemas as { $ref }; GET /api/v1/tools/:id has them embedded; GET /api/v1/tools/:id/schema answers { $schema, $id, $defs: { input, output } }, with $defs.input false for a tool without an API. The gateway (https://openvibe.tools) answers for every tool, and each satellite for its own tools with its own live status. Open to everyone, anonymous callers included, from any origin (CORS *); cacheable (ETag, 304). A bad filter value is 400 tools.query.invalid; an unknown, planned or mirror id is 404 tools.tool.not_found, whose detail says which.tools-read
tools.tool.run grantabletoolspublicactiveRun a tool through the uniform run API (ADR-027): POST /api/v1/tools/:id/run with tools.run-request@1 (JSON, or multipart with uploaded files), answered inline (tools.run@1 succeeded or failed) or, for a job tool that has not finished within wait_ms, with its job (202 + Location). Every tool whose descriptor has api true and auth.capability tools.tool.run. Callers are tiered, anonymous < session < user < app/service: tools with auth.anonymous true take anonymous callers (keyed by IP, IPv6 by /64); the others need a browser session, a signed-in person or a token. An app or service token needs this capability; people and browser sessions do not. Quotas count each tool's cost within its quota class, per caller. A job tool's run creates a job owned by the caller, like tools.job.create. Planned until the gateway serves the route.tools-run
trade.alert.create grantabletradepublicactiveCreate an alert rule for the person in X-OV-Subject: threshold (a crossing of a metric in a unit), filing_type or new_document. Deliveries are unique per (rule, triggering observation or document) and are sent as trade.alert.triggered (visibility subject); no email.trade-write
trade.alert.delete grantabletradepublicactiveDelete an alert rule of the person in X-OV-Subject.trade-write
trade.alert.read grantabletradepublicactiveRead the alert rules and recent deliveries of the person in X-OV-Subject.trade-read
trade.instrument.resolve grantabletradepublicactiveResolve a ticker, SEC CIK or exact company name to an instrument, deterministically (CIK, then ticker, then exact normalised name; several name matches are "ambiguous" and none is chosen). Browsers and anonymous readers need no capability.trade-read
trade.watchlist.create grantabletradepublicactiveCreate a private watchlist for the person in X-OV-Subject.trade-write
trade.watchlist.delete grantabletradepublicactiveDelete a watchlist of the person in X-OV-Subject.trade-write
trade.watchlist.read grantabletradepublicactiveRead the watchlists of the person in X-OV-Subject (never anyone else's: another person's watchlist is 404).trade-read
trade.watchlist.update grantabletradepublicactiveRename a watchlist of the person in X-OV-Subject, or add and remove instruments on it.trade-write
video.playlist.manage grantablemedia-hubpublicactiveCreate, rename, describe, change the visibility of, reorder, add items to, remove items from and delete playlists on openvibe.video that the caller owns. An app, agent or service owns a playlist under its own requester (app:app_..., agent:agt_..., service:<slug>) and the playlist records its project; it can never touch a person's playlist. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download) needs this one.video-write
video.playlist.read grantablemedia-hubpublicactiveRead playlists on openvibe.video: the ones the caller owns (a person, or an app, agent or service under its own requester) and any public or unlisted playlist by id, with its ordered items (vod or clip ids from OpenVibe.Live). A private playlist answers 404 to anyone but its owner. A person acting for themself needs no capability; an app, agent or service token (audience openvibe.download, the media hub's) needs this one.video-read
vip.perk.list grantablevippublicactiveList a creator's perks (and the network perks) with product bindings. Active perks are public; the grant adds retired ones.vip-read
vip.plan.list grantablevippublicactiveList a creator's plans with their current and draft versions and the full version history. Published plans are public without a grant; the grant adds drafts and archived plans.vip-read
wiki.page.read grantablewikipublicactiveRead pages, revisions, diffs, citations and AI proposals as the person named in X-OV-Subject sees them (without a subject: public, published content only). Members-only and private pages follow the space's roles; drafts and history of unpublished pages need the editor role.wiki-read
wiki.search.query grantablewikipublicactiveSearch published pages by title and text, returning only pages the person named in X-OV-Subject may read (without a subject: public pages only). Network-wide discovery goes through OpenVibe.Search, which Wiki feeds with wiki.index_document.* events.wiki-read
work.application.manage grantableworkpublicactiveManage the caller's tracked job applications on OpenVibe.Work: list (GET /api/v1/me/applications), add from a listing or by hand (POST), read with its status history, edit status, notes, dates and next step (PATCH), and delete (DELETE). A person acting for themself needs no capability; an app or agent token needs this one. Asking the person's OpenVibe.Actor agent (POST …/assist) is the person's own act and takes no capability.standard
zone.usage.read grantablezonepublicactiveRead an object zone's usage: GET /api/v1/zones/:zone_id/usage. It answers Media's live-object snapshot and the month's hourly rollups. Zone never counts. Callers: a developer app of the project with this capability, or a person who administers the project, signed in on openvibe.zone.zone-control
zone.zone.create grantablezonepublicactiveCreate a named object zone in one environment of a project. POST /api/v1/projects/:project_id/zones with an Idempotency-Key header answers 201 with the zone. A name held by a provisioning or active zone of that environment answers 409 zone.name_taken, a name held by a deleting or deleted one answers 409 zone.name_retired, and going over the project's zones quota answers 403 zone.quota_exceeded. Zone provisions the zone in Media before it becomes active. Callers: a developer app of the project with this capability, or a person who administers the project, signed in on openvibe.zone.zone-control
zone.zone.delete grantablezonepublicactiveDelete an object zone: DELETE /api/v1/zones/:zone_id answers 202 with the zone in state deleting. A zone with objects needs recursive=true (else 409 zone.not_empty), a zone with a held object answers 409 zone.held, and the default zone answers 409 zone.default. Media tombstones every object at once, with no restore window, and erases every copy within 24 hours. A hold placed after the request delays only that object's purge. The name is retired, never reused. Callers: a developer app of the project with this capability, or a person who administers the project, signed in on openvibe.zone.zone-control
zone.zone.list grantablezonepublicactiveList a project's object zones: GET /api/v1/projects/:project_id/zones, filtered by env and paged. Callers: a developer app of the project with this capability, or a person who administers the project, signed in on openvibe.zone.zone-control
zone.zone.manage grantablezonepublicactiveChange an object zone's quota_bytes or description: PATCH /api/v1/zones/:zone_id. Name, environment and access are immutable. A quota change takes effect once Media acknowledges it. Callers: a developer app of the project with this capability, or a person who administers the project, signed in on openvibe.zone.zone-control
zone.zone.read grantablezonepublicactiveRead one object zone: GET /api/v1/zones/:zone_id. Callers: a developer app of the project with this capability, or a person who administers the project, signed in on openvibe.zone.zone-control