docs: document two-key privilege model
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,11 +9,14 @@ it isn't permitted to see or send mail to people it isn't permitted to contact.
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
export EMCLI_KEY="$(head -c 32 /dev/urandom | base64)" # one-time: generate & save a key
|
||||
emcli init # create the DB, add your first account
|
||||
emcli doctor # confirm it connects and authenticates
|
||||
export EMCLI_ADMIN_KEY="$(head -c 32 /dev/urandom | base64)" # you (human) keep this
|
||||
export EMCLI_KEY="$(head -c 32 /dev/urandom | base64)" # the agent launcher gets ONLY this
|
||||
emcli init # writes both wrap slots
|
||||
emcli doctor # confirm connect/auth (agent key is enough)
|
||||
```
|
||||
|
||||
`emcli init` needs both keys. Give the agent's orchestrator only `EMCLI_KEY`; admin commands (`account`, `whitelist`, `config`, `audit`) require `EMCLI_ADMIN_KEY` and will refuse to run without it.
|
||||
|
||||
## Documentation
|
||||
|
||||
See the **[User Manual](USER-MANUAL.md)** for full setup, account configuration (including Gmail
|
||||
|
||||
+81
-31
@@ -13,7 +13,8 @@ This manual is for **using and administering** `emcli`. It assumes you have the
|
||||
## Contents
|
||||
|
||||
1. [Key concepts](#1-key-concepts)
|
||||
2. [Setup: the encryption key and database](#2-setup-the-encryption-key-and-database)
|
||||
2. [Setup: encryption keys and database](#2-setup-encryption-keys-and-database)
|
||||
- [Privilege model](#2a-privilege-model)
|
||||
3. [Quick start](#3-quick-start)
|
||||
4. [Adding accounts](#4-adding-accounts)
|
||||
- [Gmail (app password)](#gmail-app-password)
|
||||
@@ -32,10 +33,12 @@ This manual is for **using and administering** `emcli`. It assumes you have the
|
||||
## 1. Key concepts
|
||||
|
||||
**Two kinds of commands.**
|
||||
- **Admin commands** (`init`, `account`, `whitelist`, `config`, `audit`, `doctor`) are for *you*,
|
||||
the human. They print human-readable text or open an interactive form.
|
||||
- **Agent commands** (`list`, `get`, `search`, `ack`, `send`) are for the *agent*. They print one
|
||||
line of JSON and nothing else, so a program can consume them reliably.
|
||||
- **Admin commands** (`init`, `account`, `whitelist`, `config`, `audit`) require `EMCLI_ADMIN_KEY`
|
||||
and are for *you*, the human. They print human-readable text or open an interactive form.
|
||||
- **Agent commands** (`list`, `get`, `search`, `ack`, `send`, `doctor`) require `EMCLI_KEY` (or
|
||||
`EMCLI_ADMIN_KEY` as a superset) and are for the *agent*. They print one line of JSON and
|
||||
nothing else, so a program can consume them reliably. (`doctor` prints human-readable text but
|
||||
is authorised by the agent key — the agent or a human with either key can run it.)
|
||||
|
||||
**Accounts** are named (e.g. `gmail`, `work`). The agent refers to an account by name and never
|
||||
sees its password.
|
||||
@@ -61,50 +64,91 @@ acking is a deliberate, separate step.
|
||||
|
||||
---
|
||||
|
||||
## 2. Setup: the encryption key and database
|
||||
## 2. Setup: encryption keys and database
|
||||
|
||||
`emcli` reads two environment variables:
|
||||
`emcli` reads three environment variables:
|
||||
|
||||
| Variable | Purpose | Default |
|
||||
|---|---|---|
|
||||
| `EMCLI_KEY` | **Required.** Base64-encoded 32-byte key (AES-256) used to encrypt passwords at rest. | none — commands fail without it |
|
||||
| `EMCLI_ADMIN_KEY` | **Required for admin.** Base64-encoded 32-byte key (AES-256). Authorises ALL commands. | none — admin commands fail without it |
|
||||
| `EMCLI_KEY` | **Required for agents.** Base64-encoded 32-byte key (AES-256). Authorises agent commands only. | none — agent commands fail without it |
|
||||
| `EMCLI_DB` | Path to the database file. | `~/.config/emcli/emcli.db` (Linux/macOS), `%AppData%\emcli\emcli.db` (Windows) |
|
||||
|
||||
**Generate a key once** and keep it safe (store it the way the program/orchestrator that launches
|
||||
`emcli` expects — e.g. a secrets manager or your shell profile):
|
||||
**Generate both keys once** and keep them safe:
|
||||
|
||||
```bash
|
||||
head -c 32 /dev/urandom | base64
|
||||
export EMCLI_ADMIN_KEY="$(head -c 32 /dev/urandom | base64)" # you (human) keep this
|
||||
export EMCLI_KEY="$(head -c 32 /dev/urandom | base64)" # the agent launcher gets ONLY this
|
||||
```
|
||||
|
||||
Set it in your environment before running any command:
|
||||
|
||||
```bash
|
||||
export EMCLI_KEY='paste-the-base64-key-here'
|
||||
```
|
||||
|
||||
> **Important:** the key encrypts your account passwords. If you lose it, the stored passwords
|
||||
> can't be decrypted and you'll have to re-add accounts. If you change it, the same applies.
|
||||
> `emcli` never falls back to plaintext — a missing or wrong key makes every command fail safely.
|
||||
> **Important:** the keys protect your account passwords via envelope encryption (see "Privilege
|
||||
> model" below). If you lose `EMCLI_ADMIN_KEY`, account secrets can't be decrypted and you'll have
|
||||
> to re-add accounts. `emcli` never falls back to plaintext — a missing or wrong key makes every
|
||||
> command fail safely.
|
||||
|
||||
Account passwords are stored **encrypted**; they never appear in command output, error messages,
|
||||
or the audit log.
|
||||
|
||||
---
|
||||
|
||||
## 2a. Privilege model
|
||||
|
||||
`emcli` enforces a two-role privilege split so a process holding only the agent key cannot
|
||||
reconfigure accounts, whitelists, or audit settings.
|
||||
|
||||
### The two keys
|
||||
|
||||
| Key | Holder | Authorises |
|
||||
|---|---|---|
|
||||
| `EMCLI_ADMIN_KEY` | Human / secrets manager | ALL commands (`account`, `whitelist`, `config`, `audit`, `init`, plus all agent commands) |
|
||||
| `EMCLI_KEY` | Agent orchestrator | Agent commands only (`list`, `get`, `search`, `ack`, `send`, `doctor`) |
|
||||
|
||||
`EMCLI_ADMIN_KEY` is a strict superset: a process with only the admin key can run agent commands
|
||||
too. A process with only `EMCLI_KEY` is refused with `emcli: this command requires EMCLI_ADMIN_KEY
|
||||
(admin privilege)` if it attempts an admin command.
|
||||
|
||||
### Envelope encryption (DEK)
|
||||
|
||||
`emcli init` generates a random data-encryption key (DEK) that seals all account secrets. The DEK
|
||||
is stored in the `settings` table in two sealed copies:
|
||||
|
||||
- `dek_wrap_admin` — the DEK encrypted under `EMCLI_ADMIN_KEY`.
|
||||
- `dek_wrap_agent` — the DEK encrypted under `EMCLI_KEY`.
|
||||
|
||||
The DEK is never written in cleartext. Admin commands unwrap the DEK from the admin slot only; they
|
||||
have no fallback to the agent slot. This means a process holding only `EMCLI_KEY` cannot unlock the
|
||||
DEK for an admin command, even if it somehow knows the agent key.
|
||||
|
||||
### Command → role table
|
||||
|
||||
| Command | Role required |
|
||||
|---|---|
|
||||
| `list`, `get`, `search`, `ack`, `send`, `doctor` | Agent (`EMCLI_KEY` or `EMCLI_ADMIN_KEY`) |
|
||||
| `account`, `whitelist`, `config`, `audit` | Admin (`EMCLI_ADMIN_KEY` required) |
|
||||
| `init` | Both keys required (writes both wrap slots) |
|
||||
|
||||
### Agent launcher guidance
|
||||
|
||||
Configure your agent's orchestrator with **only `EMCLI_KEY`**. Never give the orchestrator
|
||||
`EMCLI_ADMIN_KEY`. If the agent tries to run an admin command — even by mistake — `emcli` will
|
||||
refuse it at the key level, not just by convention.
|
||||
|
||||
---
|
||||
|
||||
## 3. Quick start
|
||||
|
||||
```bash
|
||||
# 1. Set your key (see section 2)
|
||||
export EMCLI_KEY='…'
|
||||
# 1. Generate and export both keys (see section 2)
|
||||
export EMCLI_ADMIN_KEY="$(head -c 32 /dev/urandom | base64)" # keep this yourself
|
||||
export EMCLI_KEY="$(head -c 32 /dev/urandom | base64)" # give only this to the agent
|
||||
|
||||
# 2. Create the database and add your first account (interactive form)
|
||||
emcli init
|
||||
|
||||
# 3. Check it connects and authenticates
|
||||
# 3. Check it connects and authenticates (agent key is enough for doctor)
|
||||
emcli doctor
|
||||
|
||||
# 4. The agent can now read
|
||||
# 4. The agent can now read (needs only EMCLI_KEY)
|
||||
emcli list --account gmail --folder INBOX --limit 10
|
||||
```
|
||||
|
||||
@@ -491,10 +535,16 @@ emcli config get audit_retention_days
|
||||
## 11. Troubleshooting
|
||||
|
||||
**"EMCLI_KEY is not set" / "must be base64 of exactly 32 bytes".** Set `EMCLI_KEY` to a valid
|
||||
base64-encoded 32-byte key (section 2). Every command that touches the database needs it.
|
||||
base64-encoded 32-byte key (section 2). Agent commands (`list`, `get`, `search`, `ack`, `send`,
|
||||
`doctor`) need this key.
|
||||
|
||||
**A command fails to decrypt / "wrong EMCLI_KEY?".** The key doesn't match the one used when the
|
||||
account was added. Restore the original key, or re-add the account with the current key.
|
||||
**"this command requires EMCLI_ADMIN_KEY (admin privilege)".** Set `EMCLI_ADMIN_KEY` (section 2).
|
||||
Admin commands (`account`, `whitelist`, `config`, `audit`, `init`) need this key; `EMCLI_KEY`
|
||||
alone is not enough for them.
|
||||
|
||||
**A command fails to decrypt / wrong key.** The key doesn't match the one used when the database
|
||||
was initialised. Restore the original key, or re-run `emcli init` (idempotent — it won't regenerate
|
||||
the DEK if one already exists) with both correct keys, then re-add any accounts if needed.
|
||||
|
||||
**`doctor` shows `IMAP FAIL` / `SMTP FAIL`.**
|
||||
- *Invalid credentials / authentication failed* — wrong username or password. For Gmail, make sure
|
||||
@@ -528,7 +578,7 @@ running non-interactively.
|
||||
emcli # or: emcli help / emcli --help — list all commands
|
||||
emcli <command> --help # usage and flags for one command
|
||||
|
||||
# Admin
|
||||
# Admin (requires EMCLI_ADMIN_KEY)
|
||||
emcli init # create DB + add first account (form)
|
||||
emcli account add [flags | none for form] # add an account
|
||||
emcli account list # list accounts (no secrets)
|
||||
@@ -537,10 +587,10 @@ emcli account remove --name N --yes # delete an account
|
||||
emcli whitelist in|out add|remove|list --account N [--address A]
|
||||
emcli config set|get <key> [value] # e.g. audit_retention_days
|
||||
emcli audit list [--account N] [--limit K]
|
||||
emcli doctor [--account N] # connectivity/auth check
|
||||
emcli version
|
||||
|
||||
# Agent (one line of JSON each)
|
||||
# Agent (requires EMCLI_KEY or EMCLI_ADMIN_KEY; one line of JSON each)
|
||||
emcli doctor [--account N] # connectivity/auth check
|
||||
emcli list --account N [--folder F] [--new] [--limit K] [--before U] [--since U]
|
||||
emcli get --account N [--folder F] --uid U
|
||||
emcli search --account N [--folder F] [--from A] [--subject-contains S] [--text S] [--since-date D] [--before-date D] [--limit K]
|
||||
@@ -548,4 +598,4 @@ emcli ack --account N [--folder F] --uid-list U1,U2,U3
|
||||
emcli send --account N --to A [--cc A] [--bcc A] --subject S --body B [--attach P]… [--reply-to U [--folder F]]
|
||||
```
|
||||
|
||||
Environment: `EMCLI_KEY` (required, base64 32-byte key), `EMCLI_DB` (optional DB path).
|
||||
Environment: `EMCLI_ADMIN_KEY` (required for admin commands, base64 32-byte key), `EMCLI_KEY` (required for agent commands, base64 32-byte key), `EMCLI_DB` (optional DB path).
|
||||
|
||||
@@ -65,32 +65,36 @@ git clone https://gitea.dcglab.co.uk/steve/emcli && cd emcli
|
||||
CGO_ENABLED=0 go build -o emcli ./cmd/emcli # then move ./emcli onto your PATH
|
||||
```
|
||||
|
||||
## 3. Confirm the encryption key is present
|
||||
## 3. Confirm the agent key is present
|
||||
|
||||
emcli needs `EMCLI_KEY` (a base64-encoded 32-byte AES key) to touch its database. For agent use,
|
||||
**the orchestrator that launched you provides it** in the environment.
|
||||
emcli uses two keys; **you (the agent) are given only `EMCLI_KEY`** (the agent key). It authorises
|
||||
`list`, `get`, `search`, `ack`, `send`, and `doctor`. Admin commands require `EMCLI_ADMIN_KEY`,
|
||||
which the human holds — attempting admin commands with only `EMCLI_KEY` is refused by `emcli`.
|
||||
|
||||
For agent use, **the orchestrator that launched you provides `EMCLI_KEY`** in the environment.
|
||||
|
||||
- Confirm it's set, without printing it: `test -n "$EMCLI_KEY" && echo present`.
|
||||
- **Never** read, print, log, pass as an argument, or generate this value.
|
||||
- If it's empty, stop and tell the user: "emcli needs the `EMCLI_KEY` environment variable set by
|
||||
your orchestrator; I can't read or create it for you."
|
||||
|
||||
(For a human setting emcli up the first time: generate one with `head -c 32 /dev/urandom | base64`
|
||||
and store it securely. Account creation and other admin is the human's job — see the project's
|
||||
(For a human setting emcli up the first time: generate both keys with
|
||||
`head -c 32 /dev/urandom | base64` (once per key) and store them securely; then run `emcli init`
|
||||
with both keys exported. Account creation and other admin is the human's job — see the project's
|
||||
`USER-MANUAL.md`.)
|
||||
|
||||
## 4. Find the account(s)
|
||||
|
||||
You refer to an account by name (e.g. `gmail`, `work`). Ask the user which account to use. If the
|
||||
user permits running admin commands, `emcli doctor` lists the configured accounts and checks that
|
||||
each one connects and authenticates:
|
||||
You refer to an account by name (e.g. `gmail`, `work`). Ask the user which account to use.
|
||||
`emcli doctor` is an agent command (authorised by `EMCLI_KEY`), so you can run it to check that
|
||||
configured accounts connect and authenticate:
|
||||
|
||||
```bash
|
||||
emcli doctor # all accounts
|
||||
emcli doctor --account gmail
|
||||
```
|
||||
|
||||
Otherwise, just take the account name from the user and start with the workflow in `SKILL.md`.
|
||||
Just take the account name from the user and start with the workflow in `SKILL.md`.
|
||||
|
||||
## You're set up
|
||||
|
||||
|
||||
+11
-6
@@ -17,10 +17,13 @@ sets its exit code to match.
|
||||
|
||||
## Security model — read this first
|
||||
|
||||
- **You only run agent commands:** `list`, `get`, `search`, `ack`, `send`. Account setup,
|
||||
passwords, whitelists, and config are the **user's** job (admin commands) — do not run or suggest
|
||||
running `account`, `whitelist`, `config`, `init`, or `doctor` unless the user explicitly asks you
|
||||
to help administer.
|
||||
- **You only run agent commands:** `list`, `get`, `search`, `ack`, `send`, `doctor`. You are
|
||||
provided only `EMCLI_KEY` (the agent key), which authorises these commands and nothing else.
|
||||
Account setup, passwords, whitelists, and config are the **user's** job (admin commands that
|
||||
require `EMCLI_ADMIN_KEY`) — do not run or suggest running `account`, `whitelist`, `config`,
|
||||
`audit`, or `init` unless the user explicitly asks you to help administer and confirms they have
|
||||
provided `EMCLI_ADMIN_KEY` in your environment. Attempting admin commands with only `EMCLI_KEY`
|
||||
will be refused by `emcli` with a privilege error.
|
||||
- **Never touch the secret key.** `EMCLI_KEY` is supplied in the environment by whoever launched
|
||||
you. Do not read it, print it, log it, pass it as an argument, or try to generate one. If it is
|
||||
missing, stop and tell the user (see "Files & first run").
|
||||
@@ -43,7 +46,8 @@ https://gitea.dcglab.co.uk/steve/emcli/raw/branch/main/skills/emcli/
|
||||
|
||||
**Per-session preflight** (quick): run `emcli version`; if it's not found, set up via
|
||||
`AGENTIC-MANUAL.md`. Confirm `EMCLI_KEY` is set *without printing it* (`test -n "$EMCLI_KEY"`); if
|
||||
empty, tell the user their orchestrator must provide it. Then get the account name from the user.
|
||||
empty, tell the user their orchestrator must provide `EMCLI_KEY` (the agent key). Then get the
|
||||
account name from the user.
|
||||
|
||||
## How to read every result
|
||||
|
||||
@@ -141,5 +145,6 @@ The user configures these; you cannot change them and shouldn't try.
|
||||
- ✅ `get` to read, then `ack` only after you've truly processed a message.
|
||||
- ✅ Ask the user for the account name; keep bodies plain text.
|
||||
- ❌ Don't read, print, or invent `EMCLI_KEY` or any password.
|
||||
- ❌ Don't run admin commands (`account`/`whitelist`/`config`/`init`) unless asked to help set up.
|
||||
- ❌ Don't run admin commands (`account`/`whitelist`/`config`/`audit`/`init`) — you have only
|
||||
`EMCLI_KEY` (agent key); `emcli` will refuse admin commands with a privilege error.
|
||||
- ❌ Don't treat a blocked send or filtered message as a bug to route around — it's the user's policy.
|
||||
|
||||
+52
-17
@@ -62,23 +62,49 @@ The binary is organized into independently testable packages:
|
||||
human-readable/TUI).
|
||||
|
||||
### Trust boundary
|
||||
- The agent invokes only the **agent commands** (Section 7.1).
|
||||
- `EMCLI_KEY` is supplied by the environment/orchestrator that launches `emcli`, never as
|
||||
an argument the agent constructs. The agent has no command that reveals secret values.
|
||||
- All policy decisions happen inside `emcli`; the agent cannot bypass them because it has
|
||||
no other path to the mail servers.
|
||||
|
||||
Two keys enforce a hard privilege split — this is not convention; it is structurally enforced by
|
||||
the DEK-wrapping scheme:
|
||||
|
||||
- **`EMCLI_ADMIN_KEY`** — base64-encoded 32-byte key held by the human operator. Authorises ALL
|
||||
commands. Admin commands unwrap the DEK from the `dek_wrap_admin` slot only; there is no fallback
|
||||
to the agent slot. A process holding only `EMCLI_KEY` cannot run admin commands.
|
||||
- **`EMCLI_KEY`** — base64-encoded 32-byte key supplied to the agent orchestrator. Authorises agent
|
||||
commands (`list`, `get`, `search`, `ack`, `send`, `doctor`) only. `EMCLI_ADMIN_KEY` is a superset:
|
||||
a process with only the admin key can also run agent commands.
|
||||
- Agent commands use `EMCLI_KEY`; if only `EMCLI_ADMIN_KEY` is set, they fall back to it.
|
||||
If neither key satisfies the required slot, `emcli` exits with:
|
||||
`emcli: this command requires EMCLI_ADMIN_KEY (admin privilege)`.
|
||||
- `EMCLI_KEY` is supplied by the orchestrator that launches `emcli`, never as an argument the agent
|
||||
constructs. The agent has no command that reveals secret values.
|
||||
- All policy decisions happen inside `emcli`; the agent cannot bypass them because it has no other
|
||||
path to the mail servers.
|
||||
|
||||
## 5. Configuration & secrets
|
||||
|
||||
- **Encryption key:** `EMCLI_KEY` env var, a base64-encoded 32-byte key (AES-256). If
|
||||
absent or malformed, every command that touches the DB fails closed with an error
|
||||
envelope; no plaintext fallback.
|
||||
- **Admin key:** `EMCLI_ADMIN_KEY` env var, a base64-encoded 32-byte key (AES-256). Required for
|
||||
admin commands and for `init`. If absent or malformed when an admin command is attempted, the
|
||||
command fails with `emcli: this command requires EMCLI_ADMIN_KEY (admin privilege)`.
|
||||
- **Agent key:** `EMCLI_KEY` env var, a base64-encoded 32-byte key (AES-256). Required for agent
|
||||
commands. If absent or malformed, every agent command fails closed with a `config` error envelope;
|
||||
no plaintext fallback. `EMCLI_ADMIN_KEY` is accepted as a fallback for agent commands when
|
||||
`EMCLI_KEY` is not set.
|
||||
- **Database path:** `EMCLI_DB` env var; default `~/.config/emcli/emcli.db`
|
||||
(`%AppData%\emcli\emcli.db` on Windows).
|
||||
- **Field-level encryption:** secret columns are stored as AES-256-GCM ciphertext with a
|
||||
random 96-bit nonce per value, prefixed to the ciphertext. Non-secret config remains
|
||||
plaintext for debuggability. Decryption with the wrong key fails (GCM auth tag) and is
|
||||
surfaced as an error, never silently ignored.
|
||||
- **Envelope encryption (DEK):** `emcli init` generates a random data-encryption key (DEK) that
|
||||
protects all account secrets. The DEK is stored in the `settings` table sealed under both keys:
|
||||
- `dek_wrap_admin` — the DEK encrypted under `EMCLI_ADMIN_KEY` (AES-256-GCM).
|
||||
- `dek_wrap_agent` — the DEK encrypted under `EMCLI_KEY` (AES-256-GCM).
|
||||
The DEK is never written in cleartext. Admin commands unwrap from `dek_wrap_admin` only; agent
|
||||
commands unwrap from `dek_wrap_agent` (or `dek_wrap_admin` if only the admin key is present).
|
||||
There is no cross-slot fallback for admin commands — a holder of only `EMCLI_KEY` cannot unwrap
|
||||
the admin DEK slot.
|
||||
- **`init` idempotency:** re-running `emcli init` does not regenerate the DEK; the existing wrapped
|
||||
DEK rows are preserved.
|
||||
- **Field-level encryption:** secret columns are encrypted with the DEK using AES-256-GCM with a
|
||||
random 96-bit nonce per value, prefixed to the ciphertext. Non-secret config remains plaintext for
|
||||
debuggability. Decryption with the wrong key fails (GCM auth tag) and is surfaced as an error,
|
||||
never silently ignored.
|
||||
|
||||
Secret columns: account password, OAuth client secret, OAuth refresh token.
|
||||
|
||||
@@ -142,7 +168,9 @@ audit_log
|
||||
settings
|
||||
key TEXT PK
|
||||
value TEXT
|
||||
-- includes: audit_retention_days, schema_version
|
||||
-- includes: audit_retention_days, schema_version,
|
||||
-- dek_wrap_admin (DEK sealed under EMCLI_ADMIN_KEY),
|
||||
-- dek_wrap_agent (DEK sealed under EMCLI_KEY)
|
||||
```
|
||||
|
||||
Notes:
|
||||
@@ -216,8 +244,11 @@ command that advances read state is `ack`.
|
||||
|
||||
### 7.2 Admin commands (human-readable / TUI)
|
||||
|
||||
- **`emcli init`** — TUI flow: creates the DB (generating schema), adds the first account,
|
||||
and runs OAuth consent if the account is OAuth2.
|
||||
Require `EMCLI_ADMIN_KEY`.
|
||||
|
||||
- **`emcli init`** — TUI flow: creates the DB (generating schema + DEK), adds the first account,
|
||||
and runs OAuth consent if the account is OAuth2. Requires both `EMCLI_ADMIN_KEY` and `EMCLI_KEY`
|
||||
(writes both DEK wrap slots). Idempotent — re-running does not regenerate the DEK.
|
||||
- **`emcli account add | edit | remove | list`** — interactive add/edit; `list` prints a
|
||||
table (never secrets). `account add` accepts `--process-backlog` (default off) which sets
|
||||
the account's baseline policy: off ⇒ newly-seen folders floor at their current max UID
|
||||
@@ -225,8 +256,12 @@ command that advances read state is `ack`.
|
||||
- **`emcli whitelist in|out add|remove|list --account <name>`** — manage whitelist entries.
|
||||
- **`emcli config set|get`** — global settings (e.g. `audit_retention_days`).
|
||||
- **`emcli audit list [--account <name>] [--limit N]`** — view recent audit entries.
|
||||
- **`emcli doctor`** — verifies `EMCLI_KEY` is present and valid, the DB opens, and each
|
||||
account's IMAP/SMTP connectivity and auth succeed. Human-readable diagnostics.
|
||||
|
||||
### 7.2a `doctor` — agent-role diagnostics
|
||||
|
||||
`doctor` is authorised by `EMCLI_KEY` (or `EMCLI_ADMIN_KEY`). It verifies the key is present and
|
||||
valid, the DB opens, and each account's IMAP/SMTP connectivity and auth succeed. Prints
|
||||
human-readable diagnostics. Can be run by the agent or by a human; does not require admin privilege.
|
||||
|
||||
### 7.3 Defaults & limits
|
||||
- `list --limit` default: 50; maximum: 500.
|
||||
|
||||
Reference in New Issue
Block a user