---
title: Web Component Permissions
description: The declared-permission vocabulary for third-party web components — every scope, what it forwards, and how it maps to project roles
date: 2026-07-22
order: 2
tags:
  - web-components
  - permissions
  - security
---

A web component declares at registration time which data it wants. End users see
these scopes in the [consent overlay](./consent.md) before any third-party code
runs, and the platform forwards **only** data covered by a declared scope — nothing
else ever crosses into the sandbox. Grants are resolved server-side,
**deny-by-default**: the component can never widen its own access.

## Scope vocabulary

| Scope | Forwards | Notes |
| --- | --- | --- |
| `user-profile:read` | The requesting user's `{ id, email, displayName }` under the `userProfile` data key | Never other users' data; anonymous visitors yield no profile |
| `collection:{configurationProperty}:read` | The documents of the bound datatype, under the `{configurationProperty}` data key | Granted only when the viewing user holds the mapped read permission |
| `collection:{configurationProperty}:create` | Nothing (grant only) | Reserved for write flows; no documents are pushed |
| `collection:{configurationProperty}:update` | Nothing (grant only) | Reserved for write flows; no documents are pushed |
| `collection:{configurationProperty}:delete` | Nothing (grant only) | Reserved for write flows; no documents are pushed |

`{configurationProperty}` is an identifier path (letters, digits, `_`, `$`, dot
notation for nesting) — for example `orders` or `settings.contactTypeId`.

## Collection scopes bind at placement time

As a component author you know neither the customer's project nor its datatypes.
A collection scope therefore names a **property of your component's widget
configuration**, not a datatype: when an editor places your component, they bind
that configuration property to a concrete datatype of their project. The platform
then maps the scope onto its regular row-level-security permission for that
datatype — the component receives documents only if the *viewing user* could
already read them in the platform itself.

Declaring a datatype configuration property **without** a matching `collection:`
scope grants no data access.

## Reading granted data with the SDK

```ts
const { grantedScopes } = await client.whenInitialized();

const profile = client.getUserProfile();      // undefined unless user-profile:read granted
const orders = client.getCollection("orders"); // undefined unless collection:orders:read granted and bound
```

Design for the denied state: a scope the user's role does not cover is simply
absent from `grantedScopes`, and the matching accessor returns `undefined`. The
framework samples in the starter repository all render an explicit
"permission not granted" state.

## Related

- [Consent behavior](./consent.md) — how scopes are disclosed to end users
- [Security model](./security.md) — why data flows only over the bridge
- [Building Web Components](/web-components) — the authoring guide
