DataSync projections
A projection is a named view over an object's fields. A client's Access Manager token determines which view it gets when it reads or writes that object. Projections aren't a separate permission system. They live inside the same Access Manager tokens that already authorize the rest of PubNub.
How projections work
A projection is a named tag declared on a property definition, at the class level. A single field can belong to several projections.
The projection names you can grant on an object are the ones its class declares. Set them with Create a new entity class or Create a new relationship class, and read them off the class definition with Get entity class by ID or Get relationship class by name and version.
Each property carries its own list of projections. That list defaults to the built-in __default__ projection alone. A field is broadly visible until you restrict it, and you restrict a field by removing __default__ from its list and tagging it with a named projection instead.
For example, a Product class can tag name and price with both __default__ and admin, and tag cost with admin only. The __default__ view then contains name and price, and the admin view contains name, price, and cost.
Projection limits
A class can declare at most 3 distinct projection names across all of its properties. __default__ counts toward that 3 whenever any property uses it, which is the default, so in practice you have 2 custom names. Each name is at most 64 characters and must match ^[a-zA-Z0-9][a-zA-Z0-9_-]*$. __default__ is the only name allowed to start with __. Exceeding the limit or using an invalid name fails class creation or update with a 400.
Projections overlap rather than partition. A broadly visible field can carry several projection tags. A common pattern is to tag sensitive fields with only the restricted projection, while broadly visible fields carry both __default__ and the restricted projection, making the restricted projection a superset that sees everything plus the sensitive fields.
Projection resolution with a token
Access Manager tokens carry a pn-projections map inside their meta section. The map holds two nested maps: res for exact resource IDs and pat for regular-expression patterns. Each value is the projection name granted for that resource.
Each object kind uses its own key prefix in this map:
datasync:users:for usersdatasync:entities:for generic entitiesdatasync:channels:for channelsdatasync:relationships:for relationshipsdatasync:memberships:for memberships
Resolution follows a fixed order: an exact match in res wins first, then a pattern match in pat, and if neither matches, the token falls back to __default__. A token with no pn-projections map also resolves to __default__.
Patterns are anchored regular expressions matched against the whole resource ID. If several patterns match, which one wins isn't defined, so avoid overlapping patterns. If a token resolves to a projection name that no property on the class declares, the request fails with a 403.
What projections enforce
Projections govern reads and writes, and the two aren't symmetric. __default__ acts as a denylist that lets undeclared payload fields through, while a named projection acts as an allowlist that drops them.
- Reads under a named projection: the response contains only fields tagged with that projection. Anything else is removed, including payload fields with no property definition.
statusis removed unless the class declares a/statusproperty tagged with that projection. - Reads under
__default__: the response removes declared fields not tagged__default__, but keeps payload fields with no property definition. - Writes: naming a field outside the token's resolved projection rejects the whole request with a
403. DataSync never applies a partial write, so the object is left exactly as it was. - Replaces under a named projection: only replace that projection's payload fields. Payload fields outside the projection keep their stored values, so a restricted client can't destroy data it can't see.
- Partial updates: judged on the resulting document, not on the paths they mention. A patch that touches an out-of-projection path but leaves the value unchanged is allowed, while removing an out-of-projection field is rejected.
The 403 response says only that the auth parameter was invalid. It doesn't name the field that was rejected.
Projections and events
Each change fans out to one event per projection declared on the class. The __default__ variant publishes to the object's own ID channel with the __default__ view of the payload. Each named projection publishes to a separate channel named __<projection>__<id> carrying that projection's view.
Projection channels need channel grants
Publishing to __<projection>__<id> is an ordinary channel publish, not gated by the projection entries in a token. Use Access Manager channel grants to control who can subscribe to projection channels. Anyone who can subscribe there receives the restricted fields.
If a class declares no properties at all, there is nothing to filter, so a single unfiltered event publishes to the object's own ID channel.
In an SDK that ships DataSync SDK entities, you select the projection channel with a projection subscription option rather than by naming the prefixed channel directly.
Designing projections
- Tag broadly visible fields with both
__default__and a restricted projection so the restricted projection is a superset. - A class can declare at most 3 projections, including
__default__. Plan which fields go where before you reach the limit. - Projections scope events as well as API responses. Each named projection gets its own event channel. Grant subscribe on those channels as carefully as you grant the projection itself.
- A token holding a named projection can't write payload fields you haven't declared on the class. If a client needs to store free-form data, leave it under
__default__.