Skip to main content

Security & Privacy

This page explains Anyy's trust model: how the runtime bounds the risk of a capable, root-able assistant, what it redacts, and what stays on your machine versus what leaves it. It is the map; the detail lives in the linked pages.

Anyy is local-first. Your sessions, memory, audit trail, and secrets live in a local SQLite database and files under your home directory. Model providers are configurable backends that Anyy calls out to — they are not its identity, and only the data needed to answer a turn is sent to them.

The Trust Model

Anyy is designed to be capable on purpose. When you enable a capability pack, it can run shell commands and edit files across the host. The trust model does not work by hiding that power behind permanent walls; it works by making the consequences of an action explicit and recoverable before the action runs.

Three ideas hold the model together:

  1. Authority is not risk. Being root-capable does not make every operation dangerous. Risk is judged from what an operation actually does — whether it could break connectivity, change credentials, destroy data, or merely read state — not from whether the tool could do something dangerous.
  2. Classification is deterministic and runtime-owned. The model chooses tools and fills in arguments, but it does not decide how risky a call is. A deterministic classifier in the runtime inspects the resolved arguments, paths, and command shape, assigns an effect class, and looks up the handling path from a fixed table. No extra model call is made to grade risk.
  3. Owner authority stays explicit. Confirmation, ChangePlan, rollback, verification, audit, and redaction exist to communicate risk and provide recovery — they are not hidden capability denials. A determined owner can always proceed through the appropriate gate.

The layers are kept separate by design: product identity (Anyy), Role identity (the persona in SOUL.md), workspace context, and permission boundaries are distinct. A persona file cannot grant tools, bypass approval, or redefine product identity, and the workspace is storage — not a security boundary.

tip

The fastest way to understand the model: ask "if this operation fails, can I recover on my own?" If yes, Anyy runs it directly. If it could lose access or be irreversible, the runtime stops and asks first.

Approvals & ChangePlan as a Safety Boundary

Every state-changing or root-capable operation is classified into one effect class, and each effect class maps to a fixed handling path. This mapping is the safety boundary. (For the user-facing approval flow — the prompts, the ChangePlan card, scheduled approvals — see Approvals & ChangePlans.)

Effect classWhat it coversHandling path
read_onlyReads host, process, network, package, service, log, or file stateDirect
workspace_writeOrdinary workspace artifacts — notes, reports, generated filesDirect
anyy_managed_writeDurable assistant state (memory, skills, skill docs)Audit (runs, recorded)
system_config_writePersistent OS / init / network / runtime configurationChangePlan
service_runtime_changeStart/stop/restart/enable/disable a serviceConfirm
package_changeInstall / remove / upgrade / reconfigure packagesChangePlan
credential_or_security_changeCredentials, keys, auth policy, user accounts, SSH accessForce ChangePlan
destructive_or_lockoutWipe data, format a device, recursive delete, host shutdown, lockoutForce ChangePlan

Compound shell commands are split and classified part by part; the strongest effect in the chain wins, so a read piped into a destructive write is treated as destructive.

What a ChangePlan is, mechanically. When the handling path is change_plan or force_change_plan, the runtime creates a ChangePlan record capturing the proposed changes, expected impact, affected services, validation steps, rollback steps, a content hash, and an expiry (10 minutes by default). The operation cannot run until that plan is approved.

The boundary is enforced by a runtime preflight that the model cannot talk its way past:

  • A tool that requires a ChangePlan is blocked unless an approved plan ID and a matching plan hash are present — both supplied by the runtime, never by the model.
  • A force_change_plan operation requires a plan that was force-approved; an ordinary approval is not enough.
  • Before execution, the runtime re-derives the plan hash and rejects the run if it no longer matches the approved plan — so an approved-then-edited plan will not execute.
  • Ordinary approvals expire; an expired plan is rejected. (Force-approved plans intentionally skip the expiry check, but never the hash check.)
warning

Approval authorizes a specific, hashed plan — not a blanket permission. If the proposed commands change after you approve, the hash check fails and execution is refused. Approving a force_change_plan (for credential or destructive operations) is the strongest action you can take; treat it as a deliberate, irreversible decision.

Approvals can be answered from whichever surface is active — TUI, CLI, a chat channel, or the dashboard — and every approval, denial, force-approval, execution, verification, and rollback is written to the audit trail. See Audit.

Secret Redaction

Anyy treats credential material as something that should never appear in a place where you'd later read it back. The coding rule is explicit: secrets are redacted in logs, errors, debug bundles, snapshots, and test fixtures.

How it works:

  • One centralized redactor, shared everywhere. The same redaction pass is applied to logs, the audit trail, debug bundles, tool outputs, provider errors, and channel messages. There is no second, weaker path that skips it.
  • Value-based replacement. The redactor is built from the secret values the runtime currently knows. Any occurrence of those values in a string is replaced with [REDACTED], longest values first so the most specific match wins. Values shorter than four bytes are ignored to avoid corrupting ordinary text.
  • Audit payloads are redacted structurally. When an audit event is written, its summary, object ID, and payload map are run through the redactor recursively (nested maps, slices, and string lists included) before the event is persisted.
  • Provider diagnostics are bounded. Provider status and debug output expose only short, redacted attempt summaries — never full request bodies, full context, provider payloads, or secrets.

Secrets are referenced, not inlined. Tool and provider configuration point at a secret by reference (env:, file:, secret:), and the runtime resolves the value only at the moment it is needed. The secret-listing API returns reference names and metadata only — never the underlying value.

warning

Redaction is a strong, centralized best-effort, not a cryptographic guarantee. It can only mask values the runtime actually holds as secrets. A credential that was never registered as a secret (for example, one pasted inline into a prompt or echoed by an external command that the runtime cannot see as sensitive) will not be recognized. Store credentials as secret references rather than inlining them.

For where credentials are physically kept, see Credentials & Authentication.

What Stays Local, What Leaves

Stays on your machine:

  • The authoritative state store — sessions, messages, tool calls and results, approvals, ChangePlans, memories, skill usage, and capability caches — in local SQLite.
  • The audit trail (SQLite, optionally mirrored to local JSONL).
  • Secrets, stored as files under your home directory.
  • Logs, artifacts, and backups.
  • Conversation persistence: Anyy keeps transcripts locally and does not rely on provider-side conversation state.

Leaves your machine, by necessity:

  • Model provider calls. To answer a turn, Anyy sends the assembled prompt — system/product identity, relevant context, recent messages, and tool results — to the configured model provider over the network. This is the main data that leaves, and it goes only to the provider you configured.
  • Channel and connector traffic. If you enable a chat channel or an external connector (email, calendar, MCP servers, and similar), messages and the data those features act on travel to those services.

There is no separate analytics or telemetry pipeline in the trust model: outbound data is the provider call plus whatever channels and connectors you explicitly turn on. For the per-store retention and deletion detail, and a fuller "what leaves the machine" breakdown, see Data, Retention & Deletion.

Gateway & Dashboard Exposure

Anyy runs as a resident gateway that local clients connect to. Its local transport is a Unix-domain socket. The same gateway configuration also has a TCP/WebSocket listener. In the current build, if gateway.tcp is omitted, the loader defaults that listener to enabled, listening on 0.0.0.0:8765, in open mode. Treat the effective gateway config as network-exposed until you have checked it.

The moment you move beyond the local socket, access control matters:

  • Network listeners support open, token, pairing, and allowlist modes to control which clients may connect.
  • Pairing tokens and channel tokens are themselves sensitive state and are treated as secrets.
  • Context tokens (operational session state) are redacted, root-only, and cleared on revoke, logout, or reset.
warning

An enabled TCP/WebSocket listener in open mode accepts any client that can reach it. Disable TCP when you only need local clients, or bind it to loopback and require token, pairing, or allowlist before exposing it to a LAN. Treat pairing/channel tokens like passwords.

The configuration and operational detail for gateway listeners and the dashboard — how to set tokens, pairing, and access modes — lives in Credentials & Authentication.

Where Your Data Lives

In short: a local SQLite database is the authoritative store, with secrets, logs, artifacts, and backups kept as files under your home directory (~/.anyy/ — for example ~/.anyy/state.db, ~/.anyy/secrets/, ~/.anyy/logs/). JSONL mirrors exist for inspection, recovery, and export.

This is a summary only. For the full per-store breakdown, retention windows, and how to export or delete each kind of data, see Data, Retention & Deletion.

Hardening Checklist

Actionable steps to tighten an Anyy deployment:

  • Check the effective gateway listener. If you do not need network access, set gateway.tcp.enabled: false. If you do, bind it deliberately and never expose it unauthenticated.
  • Require a token or pairing on any network listener, and pair it with an allowlist so only known clients can connect.
  • Store every credential as a secret reference (env:, file:, secret:) rather than inlining keys into prompts, tool config, or commands — inlined values fall outside redaction.
  • Protect the home directory. ~/.anyy/ holds the state database, secrets, and audit trail; restrict its filesystem permissions to the owner.
  • Leave ChangePlan in its default (balanced) mode for everyday use; choose the stricter mode if you want more operations to route through review.
  • Treat force-approval as a deliberate act. Force paths exist for credential and destructive operations — confirm the plan's commands before you approve, and rely on the recorded hash to catch tampering.
  • Review the audit trail periodically (and after any force-approved action) to confirm what ran; see Audit.
  • Scope channels and connectors narrowly. Each enabled channel or connector widens what leaves the machine — turn on only what you use, and remember that pairing/channel tokens are sensitive.
  • Keep backups local and protected, since a backup contains a copy of your state; manage and prune them as covered in Data, Retention & Deletion.