Permissions and projection
Declare visibility while the server decides which document and field values reach each member.
Permission is server authority, not a visual state. Aether resolves a document-level ladder of
None, Limited, Observer, and Owner; a world GM has full authority. Ownership is derived from
the document owner, while named grants and defaultPermission cover other members.
#Declare field visibility
Schema visibility rules name the minimum reader level for a subtree:
const character: DocumentSchema = {
type: "my-system.character",
label: "Character",
data: characterData,
makeDefault: makeCharacter,
visibility: [
{ path: ["system", "publicBio"], level: "limited" },
{ path: ["system", "notes"], level: "owner" },
{ path: ["system", "gmNotes"], level: "gm" },
],
};Fields are observer by default. A Limited reader receives document metadata plus only subtrees
declared limited. An Observer receives ordinary fields, an Owner also receives owner fields,
and a GM receives every field.
#Projection happens before broadcast
The server applies the same projection to snapshots and live patches. A field above the viewer's level is removed before it leaves the server. Permission maps are also reduced for members who do not manage access. GM annotations and wall geometry are always GM-only engine slices.
Page visibility uses the same ladder. A page that is not visible keeps a blank slot so array indices stay stable, but its title and content are not sent. GM-only drawing entries are removed for players.
#Creation and writes
initialPermission may be None, Limited, or Observer. It cannot declare table-wide Owner
access because ownership comes from identity. A client can optimistically request a patch, but the
server resolves the member, document permission, capability write policy, revision, and schema
before accepting it.
For a mod, grants are a second boundary. documents.read returns only the caller's projected
documents; requesting that capability never grants access to hidden data.
The source contracts are packages/core/src/document.ts, packages/core/src/projection.ts, and
packages/core/src/schema.ts. Their tests are the right place to verify a new visibility rule.