# Security & Trust

What the agent keeps on your host, what it sends to the control plane and receives from it, and who else handles that data. The agent reads and loads your records on your infrastructure; metadata, run results, advisor statistics, and stored credentials reach the control plane.

## Platform · Security & Trust — What leaves your network, and who receives it.

The agent reads, moves, and loads your records inside your network. It sends the control plane configuration, contracts, run results, and, for the table-type advisor, column statistics that include the earliest and latest value of each date and time column. In return it receives connection credentials and commands. This page sets out each of these, who receives them, and how to reduce what leaves.

Links: [Join the waitlist](/waitlist/)

## Outbound-only agent

The agent opens no listening port. It connects out to the control plane with tokens it signs with its own key, and its connectors listen on 127.0.0.1 by default.

## Tenant isolation, and its limits

Row-level security limits the application's queries to the request's tenant, and each organization's credentials sit in a vault project of their own. Some platform reads and writes run on a connection that row-level security does not restrict.

## Credentials through the control plane

The agent does not talk to the vault. When it needs a connection, it asks the control plane and receives it, password included, over its outbound connection.

## The boundary, in brief.

**What the agent keeps on your host.** Your records, with the default local connectors. The agent and its connectors read them from your sources and write them to your data platform, and the agent writes its own log on the host.

**What leaves.** Configuration and contracts, including each server's host, port, database, and schema. Run events and results: counts, durations, classified errors, the number a failing critical quality rule returns, and host facts such as OS and CPU count. Connection credentials, when you store them in the vault. And for the advisor, a profile of each table: record count, null share, distinct count, and the minimum and maximum of date and time columns.

**Who receives it.** The Amfelt control plane, built to run on Scaleway in Amsterdam behind Cloudflare, whose edge terminates TLS. The control plane forwards advisor contracts and profiles to an LLM provider, Anthropic by default, when your organization has turned the advisor on.

**Switching the advisor off.** The advisor is off until your organization turns it on, and until then the control plane sends nothing to an LLM provider. The agent's automatic call still sends each unclassified object's contract and profile to the control plane. To stop that, set `advisor.gate: false` in the agent's `config.yaml`, or `AMFELT_ADVISOR_GATE=false`. An advise run that someone starts from the control plane still sends a profile.

Links: [Security model](/docs/concepts/architecture/security-model/)

## The detail — What crosses the boundary.

### What does the agent keep on my host?

- **Records, by default.** The agent runs each connector as a local process on the host, listening on `127.0.0.1` by default, and relays Apache Arrow batches from source to data platform. A connector configured with the `grpc` registry instead runs at the network address you give it: records go to that address, and the agent sends that connector the resolved connection, password included.
- **Error text.** A failure the agent reports carries an Amfelt-written message and the SQLSTATE when the error carries one. The driver's own message, which can hold a record value, goes to the agent's local log. A connection test is the exception, as the next answer says.
- **Sample values for PII detection.** The agent's PII classifier reads sample values on the host. With the advisor gate, it sends a proposed label, a confidence, and the method for each flagged column.
- **A target login, if you choose.** `amfelt add-target --store-login-in-file` keeps the login in the project file on the host instead of the vault.

### What does the control plane receive?

- **Registration**, once: the registration code, the agent's public key, its hostname, version, and capabilities.
- **Connection and heartbeat**: a signed token, the agent version, deploy mode, uptime, and the project, environment, and commit the agent holds.
- **Run events**: start and finish of each run and task, record and byte counts, durations, object and layer names, connector names and versions, and the host's OS, architecture, CPU count, Go version, and on Linux its available memory.
- **Errors**: a classified code, an Amfelt-written message, and the SQLSTATE when the error carries one. A failing critical data-quality rule also reports the rule, the table it ran on, and the number its query returned.
- **Run reports**: per table, its status, history mode, skip reason, and per-layer counts and durations, with warning counts and classified errors.
- **Contracts**: after discovery, and after runs the control plane dispatches, the source and data platform contracts. They hold table and column names, types, keys, and descriptions, and a server block with the host, port, database, schema, and connection settings such as the TLS mode, or for a file source its path. User and password are removed from it.
- **Configuration commits**: `amfelt commit` pushes the project file, contracts, and SQL template overrides, with credentials removed. It refuses to push a project file whose target holds a login.
- **Rendered SQL**, when the control plane asks for it.
- **Connection-test answers**: the driver's own message, with the password replaced. It can name the host and the user.
- **Advisor profiles and stored credentials**, described in the next two answers.

### What does the advisor send, and to whom?

The advisor can recommend a table type for each object. It is off until your organization turns it on.

- **The gate, on by default in the agent.** During a run the control plane dispatches, the agent asks the advisor about each object that has no classification yet and no job override. It sends the object's contract, server block included, and its profile: table name, record count, and for each column its name, type, null share, distinct count, heuristic signals drawn from those figures and the column name, and the actual minimum and maximum value of date and time columns. With your organization's advisor on, the object loads staging but no history until a person approves the proposal, unless the answer is confident enough to apply on its own, in which case history loads in the same run. If the advisor gives no answer, the object loads no history and the next run asks again. With the advisor off, the object loads in its resolved history mode and does not wait.
- **Advise runs.** An advise run started from the control plane (`cmd.advise`), or `amfelt advise` in API mode, profiles a PostgreSQL source with a SQL query. It sends the minimum and maximum of every column whose type name contains `date` or `time`, which can include a type that is not a date or time ([agent#810](https://github.com/amfeltlabs/agent/issues/810)). No agent setting refuses an advise run.
- **Where it goes.** The control plane removes credentials from the contract and sends the contract and profile to your organization's LLM provider: Anthropic (`claude-sonnet-4-6`) by default, or a gateway endpoint an owner or admin configures.
- **Direct mode.** `advisor.mode: direct` sends the same data from the host straight to the LLM provider with your own key. It is a development setting and needs `AMFELT_ALLOW_DIRECT_LLM=true`.

### Where do credentials live?

- **In your organization's vault project.** Each organization gets its own project in an Infisical vault that Amfelt runs on the platform's private network, and the control plane reaches it through a machine identity scoped to that project. One encryption key, for the whole vault, protects every project. Connection details you enter in the web app are stored there, and so is a login given to `amfelt add-target --user` or `--password`, unless you pass `--store-login-in-file`.
- **Delivered to the agent per use.** For each job, discovery, advise run, or connection test, the agent asks the control plane for a connection, and the answer includes the password. The agent does not talk to the vault, and it refuses to start when a vault address is set on its host.
- **Encrypted at rest.** The control plane stores each vault project's machine-identity secret encrypted with AES-256-GCM.

### What can the control plane make the agent do?

The agent acts on these commands over its outbound connection: lint, run a job, stop a job, discover, advise, render SQL, test a connection, deploy configuration, and upgrade itself.

- **Deploy.** The control plane writes the project configuration and its contracts on the host. That configuration decides which source and data platform the agent connects to, what it reads, and the SQL template overrides it runs. A contract can also carry SQL quality rules: single `SELECT` or `WITH` queries that the agent runs against the data platform, in a read-only transaction, after each table lands. A failing critical rule reports the number its query returned. The agent applies a deploy when it arrives, with no approval step on the host. The control plane sends one when an agent is assigned to the project, and after other changes, among them each save or delete of a source, data platform, or job, and each discovery.
- **Raw commands.** An owner, admin, or operator can send any `cmd.*` command through `POST /v1/agents/{agent_id}/icpc-cmd`. Only `cmd.test_connection` is refused there.
- **Ad hoc jobs.** A `cmd.execute_job` names a project folder and a job, and can carry a source connection URL that replaces the configured source. These runs carry no control-plane project, so the advisor gate does not run for them.
- **Upgrade.** The agent downloads the version the command names, older versions included, from the control plane. It checks the download's SHA-256 against a checksum the same server sends, runs a smoke test, then replaces its binary and restarts. The binary carries no signature the agent checks. An agent installed as a container, in Kubernetes, or by a package manager refuses the upgrade.
- **Connector downloads** are checked against a checksum only when the server sends one ([core#287](https://github.com/amfeltlabs/core/issues/287)).

### Which third parties handle this data?

- **Anthropic**, by default, receives advisor contracts and profiles, with logins removed, when your organization has turned the advisor on.
- **Cloudflare** proxies every public host. TLS from the agent ends at Cloudflare's edge, at whichever edge site the agent reaches; no regional restriction is configured.
- **Scaleway** hosts the control plane in Amsterdam (`nl-ams-1`), including the vault and the Git server that holds each project's configuration, and keeps the platform's logs in Scaleway Cockpit.
- **Hanko** runs sign-in for people. It does not handle agent traffic.
- **Your own Git host**, if you connect your own repository, receives the configuration commits instead.

### What does the control plane keep, and for how long?

- **Request log.** The API logs each request body of up to 32 KiB, except credential resolution. Credential fields are redacted and contracts have their logins removed, but the advisor profile (`toon_profile`) is logged as received. Production keeps these logs in Cockpit for 30 days.
- **Agent events.** Every event frame the agent sends is stored, with no retention limit today, except heartbeats: a heartbeat updates the agent's last-seen time and version instead.
- **Advisor answers** are cached in memory for 24 hours.
- **Contracts, configuration, and run reports** are stored for your project, with logins removed from contracts and configuration.

### What is the network path?

- The agent opens no listening port. It connects out: to your sources and data platform, and to the control plane over a WebSocket and HTTPS requests. A registered agent signs every token it sends with its own Ed25519 key. A token expires after five minutes by default, `amfelt channel --token-ttl` sets the WebSocket's, and the control plane requires an expiry but sets no maximum.
- Agent to Cloudflare: TLS 1.2 or later. Cloudflare to Scaleway's load balancer: TLS, with the origin certificate validated. Load balancer to the API, and API to the vault: plain HTTP on the private network.
- Agent to your sources and data platform: set a TLS mode on each database connection. With none set, a run reads a PostgreSQL source without TLS (`sslmode=disable`).
- Production is not live yet: it serves no customers, and Cloudflare refuses requests to its public hosts except from an allowlist of addresses and the platform's own gateway.

### How do I reduce what leaves my host?

- **Turn off the advisor gate** with `advisor.gate: false` or `AMFELT_ADVISOR_GATE=false`, and limit who can start advise runs: owners, admins, and operators can.
- **Exclude columns** with `columns.extract.exclude`. An excluded column is not selected, staged, or sent to the advisor gate. Primary-key, cursor, and event-time columns cannot be excluded, so the earliest and latest value of an event-time column still reach the advisor gate. An advise run profiles the whole contract it discovers.
- **Keep a login on the host** with `amfelt add-target --store-login-in-file`. `amfelt commit` then refuses to push that project file.
- **Leave telemetry off.** The separate HTTP telemetry endpoint is empty, and so off, by default.
- **What Amfelt does not offer yet:** column masking, column encryption, and tokenization. Exclusion applies only to the columns you name: a PII label the classifier proposes does not exclude a column or keep it out of the advisor's profile.

## Access control, deny by default.

People sign in through Hanko, a managed authentication provider, and the API verifies the token Hanko signs on every request a signed-in person makes. Routes that need a permission are checked by a policy engine that denies by default: an unknown user, an unknown role, or a role without the permission is refused. Many reads need only membership of the organization.

Four roles (owner, admin, operator, viewer) govern who manages, who operates, and who observes. Row-level security scopes each tenant table to the request's tenant, so a query on the application's connection sees that tenant's data. Two exceptions are deliberate: a person can see their own memberships and organizations, and an invite can be looked up by its token. Row-level security does not enforce roles; the policy engine does. Some platform reads and writes use a connection that row-level security does not restrict, among them storing the run events agents send, agent registration, the scheduler, and the command queue; there the code, not row-level security, keeps tenants apart.

The permission checks that guard routes log each decision, allowed or denied, with the actor, organization, route, outcome, and reason. Reads and changes of projects, environments, data platforms, sources, jobs, and contracts, schedule pauses and resumes, and reruns are also written to an append-only audit table. A few checks inside handlers, such as the guard on changing an owner's membership, write no audit event of their own.

Links: [Roles and access](/docs/guides/organization/roles-and-access/)

## Hosting and deployment — Where it runs, and where it can run.

### Hosting region

The control plane is built to run on Scaleway in Amsterdam, behind Cloudflare, and production is not live yet. Not every leg stays in the EU: TLS from the agent ends at whichever Cloudflare edge site it reaches, and the advisor's default provider, Anthropic, is outside EU jurisdiction.

### On-premise deployment

The agent runs on your own infrastructure today, and that is where it processes your records. Need a private-cloud or on-premise control plane? [Contact us](/contact/) to discuss it.

## FAQ — Common questions.

### Do you support SSO and SCIM (System for Cross-domain Identity Management)?

Not yet. People sign in through Hanko, a managed authentication provider. Single sign-on with your identity provider, SCIM provisioning, and MFA policies are on the enterprise roadmap.

### Where is my data stored?

Your records are written by the agent to your own data platform, cloud or on-premises. The control plane stores what the answers above list: configuration, contracts, run events and reports, advisor proposals, audit events, and its request log, with credentials in your organization's vault project.

### Does Amfelt work with airgapped or private cloud solutions?

The agent runs in your private cloud or data center, is included in every plan, and connects out to the managed control plane. It can also run without a control plane. Using the platform where nothing may connect out needs a private-cloud or on-premise control plane; [contact us](/contact/) if you need one.

## Trust, but verify.

Join the waitlist to hear when Amfelt opens to more teams. For a demo or security questions, [contact us](/contact/).

Links: [Join the waitlist](/waitlist/)


