{
"$type": "com.atproto.lexicon.schema",
"defs": {
"adminAccess": {
"description": "Operations on unsaved editor content. Read and patch are independent authorities.",
"properties": {
"editorDraftPatch": {
"description": "Plugin may propose selected unsaved field changes for host validation and review.",
"ref": "#adminEditorDraftPatchConstraints",
"type": "ref"
},
"editorDraftRead": {
"description": "Plugin may receive selected unsaved field values after an explicit editor interaction.",
"ref": "#adminEditorDraftReadConstraints",
"type": "ref"
}
},
"type": "object"
},
"adminEditorDraftPatchConstraints": {
"description": "Constraint object for admin.editorDraftPatch. Extension declarations provide enforced field and collection narrowing.",
"type": "object"
},
"adminEditorDraftReadConstraints": {
"description": "Constraint object for admin.editorDraftRead. Extension declarations provide enforced field and collection narrowing.",
"type": "object"
},
"bylinesAccess": {
"description": "Operations under bylines. Read-only: there is no plugin-facing byline write operation.",
"properties": {
"read": {
"description": "Plugin may read public byline profiles and the bylines credited on content entries.",
"ref": "#bylinesReadConstraints",
"type": "ref"
}
},
"type": "object"
},
"bylinesReadConstraints": {
"description": "Constraint object for bylines.read. No constraint keys are normatively defined here.",
"type": "object"
},
"commentsAccess": {
"description": "Operations under comments. Reading exposes personal data: author names and email addresses, comment bodies, pseudonymous IP hashes, user agents, and moderation metadata. It does not expose the linked user-account ID.",
"properties": {
"moderate": {
"description": "Plugin may change comment status with an expected-state precondition. Implies `read`.",
"ref": "#commentsModerateConstraints",
"type": "ref"
},
"read": {
"description": "Plugin may read non-trashed comments and their personal and moderation data.",
"ref": "#commentsReadConstraints",
"type": "ref"
}
},
"type": "object"
},
"commentsModerateConstraints": {
"description": "Constraint object for comments.moderate. No constraint keys are normatively defined here.",
"type": "object"
},
"commentsReadConstraints": {
"description": "Constraint object for comments.read. No constraint keys are normatively defined here.",
"type": "object"
},
"contentAccess": {
"description": "Operations under content. Each operation value is a constraint object; an empty object grants the operation with no constraints applied.",
"properties": {
"policy": {
"description": "Plugin may inspect and reject publication, scheduling, and unpublication. Does not imply content read or write access.",
"ref": "#contentPolicyConstraints",
"type": "ref"
},
"publish": {
"description": "Plugin may publish, unpublish, schedule, and unschedule content. Implies `read`.",
"ref": "#contentPublishConstraints",
"type": "ref"
},
"read": {
"description": "Plugin may read content records.",
"ref": "#contentReadConstraints",
"type": "ref"
},
"restore": {
"description": "Plugin may read and restore trashed content.",
"ref": "#contentRestoreConstraints",
"type": "ref"
},
"revisionsRead": {
"description": "Plugin may read retained content revision history. Implies `read`.",
"ref": "#contentRevisionsReadConstraints",
"type": "ref"
},
"write": {
"description": "Plugin may create, update, or delete content records. Implies `read`.",
"ref": "#contentWriteConstraints",
"type": "ref"
}
},
"type": "object"
},
"contentPolicyConstraints": {
"description": "Constraint object for content.policy. No constraint keys are normatively defined here; the operation grants only registration of synchronous publication policy hooks.",
"type": "object"
},
"contentPublishConstraints": {
"description": "Constraint object for content.publish. No constraint keys are normatively defined here.",
"type": "object"
},
"contentReadConstraints": {
"description": "Constraint object for content.read. No constraint keys are normatively defined here; the object is open to additional unrecognised keys that future runtimes may interpret.",
"type": "object"
},
"contentRestoreConstraints": {
"description": "Constraint object for content.restore. No constraint keys are normatively defined here.",
"type": "object"
},
"contentRevisionsReadConstraints": {
"description": "Constraint object for content.revisionsRead. No constraint keys are normatively defined here.",
"type": "object"
},
"contentWriteConstraints": {
"description": "Constraint object for content.write. No constraint keys are normatively defined here; the object is open to additional unrecognised keys that future runtimes may interpret.",
"type": "object"
},
"declaredAccess": {
"description": "Map of access category to a per-category block of named operations. Categories not enumerated here cannot be declared today; clients MUST reject release records that include unrecognised top-level fields. Within a known category, an unrecognised operation key is also a hard reject. Within an operation's constraint object, unrecognised keys are advisory and surfaced verbatim in install-consent UI. Note that the bundled manifest may use boolean `true` as sugar for an empty constraint object; on-PDS records canonicalise this to `{}` because Lexicon validation does not accept boolean values for typed object fields.",
"properties": {
"admin": {
"description": "Access to selected unsaved content in the authenticated editor.",
"ref": "#adminAccess",
"type": "ref"
},
"bylines": {
"description": "Read access to public byline profiles and the bylines credited on content entries.",
"ref": "#bylinesAccess",
"type": "ref"
},
"comments": {
"description": "Access to comment text, author contact and request metadata, and moderation state.",
"ref": "#commentsAccess",
"type": "ref"
},
"content": {
"description": "Access to site content (posts, pages, custom collections).",
"ref": "#contentAccess",
"type": "ref"
},
"email": {
"description": "Sending mail through the host's mail service, and participating in its delivery pipeline.",
"ref": "#emailAccess",
"type": "ref"
},
"media": {
"description": "Access to uploaded media assets.",
"ref": "#mediaAccess",
"type": "ref"
},
"network": {
"description": "Outbound HTTP requests.",
"ref": "#networkAccess",
"type": "ref"
},
"page": {
"description": "Participation in rendered page output.",
"ref": "#pageAccess",
"type": "ref"
},
"redirects": {
"description": "Access to visitor redirect rules.",
"ref": "#redirectsAccess",
"type": "ref"
},
"schema": {
"description": "Read access to collection and field definitions.",
"ref": "#schemaAccess",
"type": "ref"
},
"taxonomies": {
"description": "Access to taxonomy definitions and terms.",
"ref": "#taxonomiesAccess",
"type": "ref"
},
"users": {
"description": "Access to site user records.",
"ref": "#usersAccess",
"type": "ref"
}
},
"type": "object"
},
"emailAccess": {
"description": "Operations under email.",
"properties": {
"events": {
"description": "Plugin observes and may mutate every outgoing message (before and/or after send), including mail from the host and other plugins.",
"ref": "#emailEventsConstraints",
"type": "ref"
},
"send": {
"description": "Plugin may send mail.",
"ref": "#emailSendConstraints",
"type": "ref"
},
"transport": {
"description": "Plugin becomes the host's mail transport; every message the site sends is delivered through it. Exclusive: installing replaces the current transport.",
"ref": "#emailTransportConstraints",
"type": "ref"
}
},
"type": "object"
},
"emailEventsConstraints": {
"description": "Constraint object for email.events. No constraint keys are normatively defined here; phase scoping (beforeSend/afterSend) is reserved for a follow-on RFC and surfaced advisorily until then.",
"type": "object"
},
"emailSendConstraints": {
"description": "Constraint object for email.send. No constraint keys are normatively defined here; vocabulary for rate limits and recipient allow-lists is reserved for a follow-on RFC.",
"type": "object"
},
"emailTransportConstraints": {
"description": "Constraint object for email.transport. No constraint keys are normatively defined here. Exclusivity is a property of the host extension point: clients treat email.transport as exclusive regardless of record contents.",
"type": "object"
},
"main": {
"description": "Typed embedded object carrying the EmDash plugin's structured access manifest. Lives under the release record's `extensions` map keyed by this NSID. The `$type` field is required when embedded; clients use it to dispatch to this schema.",
"properties": {
"declaredAccess": {
"description": "Structured per-category access manifest. The sandbox enforces every operation declared here at runtime.",
"ref": "#declaredAccess",
"type": "ref"
},
"provenance": {
"description": "Optional reference to a provenance document for this release.",
"ref": "#provenance",
"type": "ref"
}
},
"required": [
"declaredAccess"
],
"type": "object"
},
"mediaAccess": {
"description": "Operations under media.",
"properties": {
"bytesRead": {
"description": "Plugin may read bounded bytes and content hashes for ready media.",
"ref": "#mediaBytesReadConstraints",
"type": "ref"
},
"metadataWrite": {
"description": "Plugin may change alt text, captions, and focal points on ready media.",
"ref": "#mediaMetadataWriteConstraints",
"type": "ref"
},
"read": {
"description": "Plugin may read ready media metadata. Storage keys, author identity, content hashes, and file bytes are excluded.",
"ref": "#mediaReadConstraints",
"type": "ref"
},
"write": {
"description": "Plugin may upload, modify, or delete media. Implies `read`.",
"ref": "#mediaWriteConstraints",
"type": "ref"
}
},
"type": "object"
},
"mediaBytesReadConstraints": {
"description": "Constraint object for media.bytesRead. No constraint keys are normatively defined here.",
"type": "object"
},
"mediaMetadataWriteConstraints": {
"description": "Constraint object for media.metadataWrite. No constraint keys are normatively defined here.",
"type": "object"
},
"mediaReadConstraints": {
"description": "Constraint object for media.read. No constraint keys are normatively defined here.",
"type": "object"
},
"mediaWriteConstraints": {
"description": "Constraint object for media.write. No constraint keys are normatively defined here.",
"type": "object"
},
"networkAccess": {
"description": "Operations under network.",
"properties": {
"request": {
"description": "Plugin may make outbound HTTP requests. Constraints scope the access; an empty object grants unrestricted requests.",
"ref": "#networkRequestConstraints",
"type": "ref"
}
},
"type": "object"
},
"networkRequestConstraints": {
"description": "Constraint object for network.request. Open shape — additional constraint keys (rate limits, etc.) may be declared and will be surfaced advisorily until normatively defined by a follow-on RFC.",
"properties": {
"allowedHosts": {
"description": "Allow-list of outbound host patterns. Each entry is a hostname pattern with no scheme, path, or port; a leading '*.' wildcard is permitted for subdomains. Field absent means no host restriction; an empty array MUST NOT appear in records.",
"items": {
"maxLength": 256,
"type": "string"
},
"maxLength": 64,
"minLength": 1,
"type": "array"
}
},
"type": "object"
},
"pageAccess": {
"description": "Operations under page (rendered-output participation).",
"properties": {
"fragments": {
"description": "Plugin injects script and/or style fragments into rendered pages.",
"ref": "#pageFragmentsConstraints",
"type": "ref"
}
},
"type": "object"
},
"pageFragmentsConstraints": {
"description": "Constraint object for page.fragments. No constraint keys are normatively defined here; position/placement scoping is reserved for a follow-on RFC.",
"type": "object"
},
"provenance": {
"description": "Provenance document reference. Unknown predicate types are retained as present-but-unverifiable; consumers understand https://slsa.dev/provenance/v1 in v1. Lexicon validates URI syntax and field lengths; consumers validate multibase-multihash syntax and source and builder canonicalization.",
"properties": {
"builderId": {
"format": "uri",
"maxLength": 1024,
"type": "string"
},
"checksum": {
"description": "Multibase-encoded multihash of the provenance document bytes. Consumers validate the multibase-multihash syntax and supported hash function.",
"maxLength": 256,
"type": "string"
},
"predicateType": {
"maxLength": 1024,
"type": "string"
},
"sourceRepository": {
"format": "uri",
"maxLength": 1024,
"type": "string"
},
"url": {
"format": "uri",
"maxLength": 2048,
"type": "string"
}
},
"required": [
"predicateType",
"url",
"checksum",
"sourceRepository",
"builderId"
],
"type": "object"
},
"redirectsAccess": {
"description": "Operations under redirects.",
"properties": {
"read": {
"description": "Plugin may read redirect rules.",
"ref": "#redirectsReadConstraints",
"type": "ref"
},
"write": {
"description": "Plugin may create, update, or delete redirect rules and change where visitors are sent. Implies `read`.",
"ref": "#redirectsWriteConstraints",
"type": "ref"
}
},
"type": "object"
},
"redirectsReadConstraints": {
"description": "Constraint object for redirects.read. No constraint keys are normatively defined here.",
"type": "object"
},
"redirectsWriteConstraints": {
"description": "Constraint object for redirects.write. No constraint keys are normatively defined here.",
"type": "object"
},
"schemaAccess": {
"description": "Operations under schema.",
"properties": {
"read": {
"description": "Plugin may read public collection and field definitions.",
"ref": "#schemaReadConstraints",
"type": "ref"
}
},
"type": "object"
},
"schemaReadConstraints": {
"description": "Constraint object for schema.read. No constraint keys are normatively defined here.",
"type": "object"
},
"taxonomiesAccess": {
"description": "Operations under taxonomies.",
"properties": {
"read": {
"description": "Plugin may read taxonomy definitions, their terms, and the terms assigned to content entries.",
"ref": "#taxonomiesReadConstraints",
"type": "ref"
},
"write": {
"description": "Plugin may create terms and add or remove term assignments. Implies `read`.",
"ref": "#taxonomiesWriteConstraints",
"type": "ref"
}
},
"type": "object"
},
"taxonomiesReadConstraints": {
"description": "Constraint object for taxonomies.read. No constraint keys are normatively defined here.",
"type": "object"
},
"taxonomiesWriteConstraints": {
"description": "Constraint object for taxonomies.write. No constraint keys are normatively defined here.",
"type": "object"
},
"usersAccess": {
"description": "Operations under users.",
"properties": {
"read": {
"description": "Plugin may read site user records.",
"ref": "#usersReadConstraints",
"type": "ref"
}
},
"type": "object"
},
"usersReadConstraints": {
"description": "Constraint object for users.read. No constraint keys are normatively defined here.",
"type": "object"
}
},
"description": "EmDash-specific extension data embedded inside a release record under its `extensions` field. Carries the trust contract (declaredAccess) the sandbox enforces. EXPERIMENTAL: shape may change before stabilisation.",
"id": "com.emdashcms.experimental.package.releaseExtension",
"lexicon": 1
}