Skip to content

Archons

An Archon is a Soul Stack operator — a record in the operators registry in PostgreSQL. It has an identifier (AID), a set of roles, and a lifecycle: creation, token issuance, revocation. Records are never deleted — Archons are only revoked, so that audit references to the initiator of operations stay valid.

The AID (Archon ID) is a stable string validated against ^[a-z0-9][a-z0-9._@-]{1,127}$:

  • the first character is a lowercase letter or digit;
  • then lowercase ASCII letters, digits, and the characters . _ @ -;
  • length 2–128 characters.

Valid examples: archon-alice, email-like alice@corp.com, an LDAP uid such as uid-4815, ops-team. The character set is deliberately narrow and safe (no /, \, quotes, control characters, or unicode) — an AID gets embedded in filenames, JWT claims, and logs.

On the cluster’s first initialization the operators registry is empty. Since the base policy is default-deny, without a special mechanism any API call would end in 403, and creating the first operator would be impossible. This chicken-and-egg problem is solved by Keeper’s own administrative subcommand:

Terminal window
keeper init --archon=archon-alice --config=/etc/keeper/keeper.yml \
[--credential-out=/etc/keeper/archon-credential.json]

What the command does:

  1. Under a PostgreSQL advisory lock, it checks that the operators registry is empty. If it already has records, it refuses with a message that the cluster is initialized and which Archon exists.
  2. Creates the first Archon with the given AID and binds it to the built-in cluster-admin role (permission * — full access).
  3. Issues a JWT credential and writes it to a file with 0400 permissions.

A few details that matter in operation:

  • This isn’t Keeper’s “client mode”. keeper init is an administrative subcommand: a locally installed Keeper binary initializes its own state in PostgreSQL. It does not connect to a remote Keeper.
  • The lock removes the HA race. If several instances run keeper init at once, the advisory lock guarantees exactly one creates the first Archon; the rest see a non-empty registry and refuse.
  • The bootstrap token’s TTL is 30 days (longer than usual) so the operator has time to set up further administration. The 0400 file must be stored securely — it’s the first administrator’s credential.

Protection against accidental re-bootstrap

Section titled “Protection against accidental re-bootstrap”

If Keeper starts and sees the operators registry is empty, its behavior depends on an explicit flag:

  • without --initialize (or the KEEPER_INITIALIZE=true variable) Keeper refuses to start and asks you to run keeper init first;
  • with --initialize Keeper starts in a waiting mode: the listeners come up, but any API/MCP call returns 503 until keeper init has run.

This is a safeguard against a catastrophic loss of PostgreSQL: without the operator’s explicit intent, the system won’t automatically issue a new admin token.

Every operator except the first is created through the Operator API (REST/MCP/web UI) by an Archon that holds the operator.create permission:

  • a record is created in the operators registry, and on creation the API returns the new operator’s JWT;
  • if an operator loses its token, another Archon with the operator.issue-token permission can issue it a new one — without recreating the Archon itself.

Binding a new operator to roles is a separate step (Roles and access); a freshly created Archon with no roles has no permissions at all (default-deny).

An Archon is revoked, not deleted:

  • revocation is done through the Operator API with the operator.revoke permission — the record gets revoked_at set;
  • the record stays in the registry so that “who created / who changed” references (the created_by_aid / changed_by_aid fields on other entities) remain valid for auditing;
  • a revoked operator is no longer issued new tokens, and its active JWT stops passing the check — revocation propagates across all cluster instances almost instantly. The token’s short TTL is an additional, natural layer of defense.

Invariant: you can’t remove the last administrator

Section titled “Invariant: you can’t remove the last administrator”

The cluster must always retain at least one active Archon with effective full access (*). An operation that would break this — for example, revoking the sole cluster-admin or stripping its last *-granting role — is rejected with a 409 would-lock-out-cluster error.

The invariant accounts for every path to *: a direct role binding and a binding via a group (Synod). This is self-lockout protection — you can’t accidentally or maliciously “lock” yourself and the whole cluster out of an administrator.