Skip to content

Enrollment tokens & scopes

The enrollment token is the identity pillar of Postern — the “scoped key that creates up to N mailboxes without the master key.” It is a capability token: it carries only the access it was granted, and that access is enforced server-side, not on trust.

A minted enrollment key looks like pk_enroll_<id>_<secret>. The raw value is shown once; Postern stores only its SHA-256 hash and compares in constant time. A key carries:

PropertyMeaning
labelHuman-readable name for the console (e.g. “support-bot bootstrap”).
scopesThe capabilities it can mint into agent keys: mailbox:create, mailbox:read, mailbox:send.
allowed_domainsThe domains mailboxes may be created on. Empty = any org domain.
max_mailboxesThe hard cap N on how many mailboxes this key may ever mint.
used_countHow many it has minted so far. At max_mailboxes, the key is exhausted.
reusableWhether one key can mint many agents/mailboxes, or is single-use.
expires_atWhen the key stops working, regardless of remaining quota.
revokedA kill switch — instant, isolated.

Postern’s capability model is inspired by Panocrypt’s: the token carries a high-entropy secret, but the server is the source of truth for the counter and revocation.

  1. Mint. A human or org-admin call issues a key with scopes, allowed domains, max_mailboxes, and an expiry. POST /v1/enrollment-tokens (console)

  2. Redeem. An agent redeems the key for a scoped agent key (pk_agent_…), idempotent on a client-provided agent_handle. POST /v1/enroll

  3. Spend. Each mailbox:create increments used_count. At max_mailboxes the key is exhausted — a cloned key cannot exceed N, because the counter lives server-side.

  4. Revoke. Per-token and per-agent-key, instant, isolated. Killing one key never rotates others.

Scopes are additive capabilities. A key grants a subset; the minted agent key can never exceed it.

ScopeGrantsTypical use
mailbox:createCreate new mailboxes (against the quota)Provisioning agents
mailbox:readList/read messages and threadsRead-only monitors, OTP readers
mailbox:sendSend and replyOutbound/transactional agents
example: a read-only OTP runner
scopes = mailbox:create, mailbox:read // can make inboxes + read, but never send
allowed_domains = (empty → any org domain)
max_mailboxes = 20
expires_at = +24h

The motivating failure is a supply-chain compromise of an MCP host that was handed an org-wide key. Postern’s answer is structural: no org-wide key ever reaches an MCP host. The host gets only a single-agent, single-purpose, expiring enrollment key. If it leaks:

  • it can’t exceed max_mailboxes (server counter);
  • it can’t reach domains outside allowed_domains;
  • it can’t do anything outside its scopes;
  • it can be revoked instantly, in isolation, without touching any other agent;
  • every action it took is attributable in the audit log.