# Read and write roles, and the write gate

> Investigate only, approved changes only or both on one credential; what counts as a write for every connector type; and the write gate as a control matrix.

_Concept · Updated 2026-10-27 · Describes release 0.1.164_

Every connection is used in one of three ways, and every tool call is classified as a read or a write in one place for all connector types. This page owns both rules. The connect form, secrets, **Test** and the row actions are on [Manage connections](/help/manage-connections.md); the write side step by step is [Write connections and approved fixes](/help/setup-write-connections.md).

## Read role vs write role {#read-role-vs-write-role}

Choose **Use this connection for**. This controls which platform workflows can use the credential; it does not grant cloud IAM permissions.

![Connect datasource: Use this connection for decides whether the credential investigates, executes approved changes, or both; Allow use for approved plans is the separate consent.](/help/media/portal/portal-connect-dialog.png?v=0.1.132)

| Choice | Investigation, chat and discovery | Approved execution |
|---|---|---|
| **Investigate only** (`read`, default) | Read operations | Unavailable |
| **Approved changes only (separate credential)** (`write`) | Credential excluded | Available only after **Allow use for approved plans** is enabled |
| **Investigate and approved changes (same credential)** (`read_write`) | Read operations through the same read-only tool boundary | Available only after **Allow use for approved plans** is enabled |

**Allow use for approved plans** starts off. Changing the connection's use clears this consent; enabling it never approves an individual plan. Turning it off blocks subsequent execution; a shared connection remains available for investigation. Changing credential, scope, use or consent requires a fresh execution review.

Moving an **Approved changes only (separate credential)** connection to another use hands its stored credential to investigations and private agents, so it is a release decision: it needs `approvals.decide` as well as `datasources.manage` (of the builtin roles, only the owner holds both). Pointing such a connection somewhere else is the same decision, because **Test** and operation discovery send its stored credential to the address in its settings: once it holds a stored credential, a change to its settings needs `approvals.decide` too. An operator's change of use or of those settings is refused with 403; the operator can still rename it, describe it, replace its credential and switch it on or off.

A separate execution credential is excluded from investigation tool registries. The planner sees only capability and scope metadata. A shared credential is available to read tools, but an investigation cannot use its cloud write permissions: writes still go through the exact approved Change executor. Separate credentials also enforce this separation in the provider's IAM; shared credentials depend on the platform's read boundary as well as their provider scope.

An enabled AWS/Azure execution credential with consent can be saved with **Save and check access**. That runs a safe identity/read check, never a mutation probe and never proof of all future write permissions. Without consent, **Save remediation credential** saves it without that check. **Audit perms** on the connection's row in **Data sources** inspects grants where supported; the exact action is checked again before dispatch.

**Chat** reads the platform records your role allows. With `chat.estate`, it may also query live read-only connections; write-role credentials stay excluded and mutating calls are denied. Collected telemetry additionally requires the active lakehouse feature and its read permission.

### Split a powerful credential in two

Use this when you want investigation credentials to have no provider write permissions.

1. Connect the read half first. Give it a narrow viewer credential. Choose **Investigate only** and **Connect and verify**. Requires `datasources.manage`.
2. Wait for the read check to succeed. A queued private-agent check is still waiting for a result.
3. Press **Audit perms** and confirm the verdict reads **least-privilege OK**. If it reads **over-privileged**, scope the credential down at the source and re-check before going further.
4. Connect the write half as a second datasource of the same type, with a distinct name (`prod-eks-remediate`, `core-switch-config`). Choose **Approved changes only (separate credential)**.
5. Give the write half only the permission the intended fix needs — push to one repository, restart one workload, write one device config section — and nothing else.
6. Enable **Allow use for approved plans** when ready. Save the connection, inspect any access-check result, then return to the incident or Change to review the exact proposed action and recovery checks.

A connection can support different approved actions inside its validated scope. For the simpler setup, choose **Investigate and approved changes (same credential)**, connect a suitably scoped identity, and explicitly enable approved-plan use. Repository access is connected separately when a configuration change belongs in Git; cloud access does not grant repository permissions.

### Several connections into one cloud account {#several-connections-into-one-cloud-account}

Some organisations give each job its own role: one for operations reads, one with security-audit reads for compliance, one for the audit log. Each role can be its own connection into the same AWS account, and several app registrations can each be a connection into the same Azure subscription. Fixes still run only through your separate write connection, after approval.

**Add the extra role.** Name it `aiops-…`, with no path, and give it the same trust policy as your read role: `sts:AssumeRole` with this workspace's External ID, and `sts:TagSession`, for the platform role and the workspace reader role. In **any-account** mode that is all it needs: the platform assumes any `aiops-*` role whose trust names the workspace External ID. With roles **prepared by platform staff** (also the case with a private-network agent, whose own role is the workspace reader), the reader is granted only the roles staff prepared, so ask platform staff to also grant it `sts:AssumeRole` and `sts:TagSession` on the new role, and the platform role too where its grants name exact roles. **Test** runs as the platform role and cannot check the reader's grant: until staff add it, Estate x-ray scans and investigation reads through the new connection are refused. Connect it as **Investigate only** under its own name. An access-key connection needs one passing **Test** before the platform knows its account; until then it is grouped with no other connection.

**Choose what each connection runs.** Under **Advanced · agent access and automation credentials**, **Jobs this connection runs** lists the account-wide reads an AWS or Azure read connection makes beside its agent tool: four on both clouds, and **Service map (Application Signals / X-Ray)** and **Built-in detection** on AWS. All of them start ticked. When the role you type reaches an account another read connection already reaches, the form names that connection and what it runs; it warns, and never refuses the second connection.

![Edit connection → Advanced · agent access and automation credentials → Jobs this connection runs: the account-wide jobs this credential performs, and the pillar allowlist beneath.](/help/media/portal/portal-connection-jobs.png?v=0.1.142)

| Job | What it reads | Config key |
|---|---|---|
| **Estate inventory** | Every resource the account lists (on AWS: tagging `GetResources`, Resource Explorer `ListResources` in a region where its index is on, and AWS Config's recorded inventory through `SelectResourceConfig`; on Azure: Resource Graph) and the typed network, compute and data structure behind the estate map, into the `[estate] <connection>` knowledge item. `config_inventory: false` leaves AWS Config out | `harvest_inventory` |
| **Platform checks (EST-01..06)** | The platform's own cloud checks: backups, public storage, open security groups, encryption at rest, audit logging and IAM hygiene | `platform_checks` |
| **Security findings sync** | Security Hub findings on AWS, Defender for Cloud assessments on Azure | `sync_findings` |
| **Change capture** | CloudTrail write events on AWS; the Activity Log and Change Analysis on Azure | `harvest_changes` |
| **Service map (Application Signals / X-Ray)** (AWS) | Application Signals `ListServices` and `ListServiceDependencies`, with X-Ray `GetServiceGraph` where Application Signals lists nothing in a region; hourly, into traced service dependencies, never trace content. A connection whose **Pillar allowlist** leaves out Incident is not read, although its **Runs** line still lists the job | `service_map` |
| **Built-in detection** (AWS) | CloudWatch `ListMetrics` and `GetMetricData` for the built-in rules, in the regions this connection evaluates; runs only while the workspace has [Built-in detection](/help/builtin-detection.md) on | `builtin_detection` |

An unticked job saves `false` under its key in the connection's configuration, and ticking it again removes the key. A connection without the key runs the job, so connections made before this setting keep running all of them. Saving re-tests the connection, as every edit does: on a connection that also runs approved changes, a pending approval bound to it needs a fresh review.

**Divide the jobs the way your roles are divided.**

- Leave **Platform checks** on the one role with security-audit-level reads (the AWS managed `SecurityAudit` policy, or equivalent reads) and untick it on the others. One check reads several services; through a narrow role some of those reads are denied, and the check reads **unknown** instead of passing. **Test** an access-key connection before you untick it: an unticked connection counts as checked only through a connection the platform knows reads its account (see below).
- **Change capture** can run on its own audit-log role. A change it captures updates the inventory item of the connection into the same account that runs **Estate inventory** (the first by name), once the platform knows the capturing connection's account: its role ARN or a passing **Test** on AWS, one whole subscription on Azure. Until then keep **Change capture** on the connection that runs **Estate inventory**: a connection with no inventory item has nothing to update.
- After you untick **Estate inventory** on a connection that ran it, its `[estate] <name>` item is switched off at the next harvest by any connection in the workspace, or when that connection is deleted: [Knowledge](/portal/knowledge) (in the product: `/portal/knowledge`) shows it inactive, and the audit log records a `knowledge.deactivate` by the system. **Activate** brings it back for good. Deactivate it by hand only when no other connection harvests.
- A role that reads regions its sibling does not is a reason to keep a job ticked on both.

**What the platform does with one account behind several connections.** A connection's account is the account of its role ARN, else the account its last **Test** proved for its current settings. An Azure connection's is the one subscription its jobs read (its Scope JSON `subscriptions`, else its subscription ID), and only when it reads that whole subscription: several subscriptions, or a resource group, leave it grouped with no other connection. The `accounts` in an AWS Scope JSON are intent and never group connections. For connections sharing an account:

- **Data sources** shows `AWS account … · same account as …` and a **Runs:** line on each, sorts them side by side, and adds one notice per account naming which connection runs each job, with **nobody …** for a job no connection runs. Saving a connection names the others in its check result.
- Each connection keeps its own agent tool, and each tool's description names its same-account sibling tools. An estate x-ray says which scanned connections reach one account, and one connection's tool no longer counts as coverage for the others.
- Platform checks list a resource seen through several connections once per account. Its row names the connection it is listed from and, after *also seen through*, the others. A suppression covers only the copy it was approved on, and holds only while that copy's connection reads the resource: if that connection stops running the checks, is disabled or deleted, stops reading the resource's region (on Azure, its subscription), or a read there fails, the resource reopens through another connection's copy until that connection reads it again or that copy is suppressed too. Where you can, leave **Platform checks** on one connection per account before approving suppressions. Two resources a check cannot tell apart, such as two VMs with one name in different resource groups, stay two: a connection's first copy pairs only with another connection's first, its second with the second. Offender counts do not grow with the number of connections: where several already read one account, the counts and the posture trend step down once, on the first check that groups them. The number of resources checked still adds up every connection's reads.
- A read one connection could not make, a denied call for example, does not hold back a check when another connection into the same account ran that check with no failed read over at least the same regions (on Azure, at least the same subscriptions). The evidence still names the excused reads. A check is excused as a whole, never pieced together from two connections' partial reads, and a listing cut short is never excused.
- A connection with **Platform checks** unticked counts as checked only while a connection that runs them is known to read the same account in every region the unticked one reads (on Azure, every subscription it lists). Otherwise the checks read **unknown**, with *probe pending for <name> (platform checks off; no other connection checks its account)*: never a pass for an account nobody checked.
- When the connections' inventory items hold the same resources, the agents read them as one merged estate inventory, each resource once with the newest harvest's values, so the cost of a prompt does not grow with the number of roles. An item with prose of its own (a hand-written ontology, a recorded x-ray inventory) keeps its own block.

## The read/write gate in detail {#the-read-write-gate-in-detail}

Investigation datasource tools reject writes, even with a shared read/write credential. Supported mutations must be prepared and released through the Change executor. Approval gates for sensitive reads can still pause a run; approving one does not turn an investigation tool into a write executor. [Guardrails and cost limits](/help/guardrails-and-cost-limits.md#which-posture-your-deployment-runs) is the authority on which posture your deployment runs, and [Configure the agents](/help/configure-the-agents.md#procedure-add-an-extra-approval-gate) on how to add gates of your own; this section is the authority on *what counts as a write*.

Every connector type has a declared read surface, and the tool description tells the agent exactly what it is.

- **Plain HTTP connectors**: `GET` and `HEAD` only. Argo CD, Alertmanager, Dynatrace, Opsgenie, Jaeger, Tempo, RabbitMQ, ServiceNow, GitHub, GitLab, Kubecost, the generic API and Postgres all fall here. (Dynatrace's Grail DQL endpoint is a POST that needs a platform token, so it is not a read path for the Dynatrace connector.)
- **Query-over-POST families**: the specific query endpoints only — Prometheus `api/v1/query`, `api/v1/query_range`, `api/v1/series`, `api/v1/labels`, `api/v1/query_exemplars`; Elasticsearch `_search`, `_msearch`, `_count`, `_field_caps`, `_sql`, `_async_search`; Grafana `api/ds/query` and `api/tsdb/query`; Loki `loki/api/v1/series`; plus per-type sets for Datadog, Splunk, PagerDuty, Jira, Azure, Azure DevOps and Sentinel. Matching is on whole path segments against the full path or its trailing run — never a bare prefix — so a write endpoint that lives one segment deeper, such as `services/search/jobs/{id}/control`, cannot ride in on a read classification.
- **Endpoints where the verb lies** are force-gated even on `GET`. The canonical example is the VictoriaMetrics `api/v1/admin/tsdb/delete_series`, which accepts a `GET`. An Azure App Configuration key-value read through ARM (`…/configurationStores/<store>/keyValues/…`) is gated the same way, because it returns the value; a read of the store itself stays free.
- **AWS**: `Describe*`, `List*`, `Get*`, `Head*`, `BatchGet*`, `Lookup*`, `Search*`, plus `Query`, `Scan`, `FilterLogEvents` and the policy-simulation calls run freely. Creates, deletes, arbitrary-SQL verbs such as `ExecuteStatement`, and secret-returning reads (Secrets Manager, SSM parameters and their history, KMS `Decrypt` and `GenerateDataKey`, `AssumeRole`, `GetAuthorizationToken`) are gated, and so are reads that return configuration content (AppConfig `GetConfiguration`, `GetHostedConfigurationVersion`, `GetLatestConfiguration`). A read-only exfiltration is still a breach. On the REST-style AWS APIs the HTTP method is the signal instead of the action name. One query runs freely: a bounded CloudWatch Logs Insights `StartQuery` — the default query language, 1 to 5 named log groups without `*`, no `SOURCE` command, at most 24 hours. It runs in estate scans too, and AWS bills it to your account per GB scanned (about $0.005 per GB at the us-east-1 list price), outside the platform's cost cap.
- **GCP**: `GET` plus read custom methods (`:list`, `:get`, `:query`, `:search`, `:testIamPermissions` and similar). BigQuery SQL through `jobs` or `queries` is gated.
- **GraphQL**: queries run, mutations and subscriptions are gated, and a request whose GraphQL document is missing, empty or not a plain string — a batched body, for instance — is gated by default.
- **Vendor firewalls** (drafted from the vendors' public docs; the reads were validated against FortiOS 8.0.2 and PAN-OS 11.2.15 lab firewalls in October 2026, and the refusals happen in the platform before anything is sent): FortiGate reads with `GET` only, `HEAD` included in the refused methods, and its configuration backup and credential tables (admins, API users, local users, IPsec phase-1 keys, local certificates) are refused although they are `GET`s. On Palo Alto Networks the REST API reads with `GET`, but the XML API writes over `GET` too, so the request decides: `type=version`, one `show` command (not a whole-configuration dump) or the policy and route lookups, a config `get`/`show` of a rulebase, object or network subtree that names no credential node, and log retrieval run; everything else, an ambiguous request and any request with a body is refused. On both, a key in the URL (`access_token` on FortiGate, `key` or `password` on Palo Alto Networks) is refused: the key rides a header. [FortiGate](/help/integration-fortigate.md#read-surface) and [Palo Alto Networks](/help/integration-paloalto.md#read-surface) list them in full.
- **Zabbix JSON-RPC**: `*.get` methods run, plus `*.checkAuthentication`, `apiinfo.version` and `configuration.export`. Everything else is gated, including `script.execute`.
- **Two universal path triggers** override the connector type entirely: any request whose path ends in `/graphql` or `/api_jsonrpc.php` is classified from its body, so a GitHub or GitLab connector reaching GraphQL gets the same treatment as a dedicated GraphQL connector.
- **MCP**: `readOnlyHint=true` runs, everything else is gated, and a mutating-looking tool name overrides the hint.
- **CLI and network devices**: a network device's read commands, listed under [Network device](/help/manage-connections.md#network-device), run. Of the CLI connectors only `kubectl` has the platform's verified read adapter ([CLI](/help/manage-connections.md#cli)); every SSH and Generic CLI call is refused in an investigation, a chat turn and an estate x-ray, read verbs included.
- **Web access**: `web_fetch` runs freely only for domains on your allowlist; `web_search` is never gated but its query is scrubbed for personal data before it leaves the platform; `http_get` is always gated, because it is a general-purpose exfiltration channel.

### Two overrides with no portal control

Both are set on the datasource config through the REST or MCP API. Neither has a control on the Data sources page.

**Tightening** (`gate_paths`) forces specific paths to be gated even when they would otherwise classify as reads. Use it to put a sensitive endpoint behind a human decision.

**Widening** (`read_post_paths`) adds POST endpoints to the approval gate's read set for one datasource. It does not widen what an agent may call: the read floor every investigation, chat turn and estate x-ray applies classifies a call with the connector's own read set only, so in this release a POST outside that set is still refused, adopted or not. It applies to POST only, never to PUT, PATCH or DELETE, and any path containing a dangerous token (`write`, `delete`, `exec`, `admin`, `control`, `import`, `bulk`, `restart`, `create`, `update`, `run` and others) is rejected outright.

### Widen a read set the reviewed way {#widen-a-read-set-the-reviewed-way}

Widening is deliberately a two-step, reviewed operation: the platform derives candidates from the API's own specification, and a human adopts them.

1. Set an OpenAPI path on the datasource, if it does not have one. Requires `datasources.manage`.
2. Call the discovery endpoint. It fetches the specification, derives the API's read and write surface in code, and records query-shaped POST endpoints as *pending candidates* — up to 50, trusted by nobody yet. It fails with a `400` if the datasource has no OpenAPI path, or if the spec cannot be fetched or parsed.

```bash
curl -X POST \
  -H "Authorization: Bearer $AIOPS_TOKEN" \
  "$AIOPS_URL/api/aiops/$TENANT_ID/datasources/$DS_ID/discover-operations"
```

3. Review the returned candidates. Adopt only the ones you have confirmed are genuinely read-only.

```bash
curl -X POST \
  -H "Authorization: Bearer $AIOPS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"paths": ["reports/query", "search/execute"]}' \
  "$AIOPS_URL/api/aiops/$TENANT_ID/datasources/$DS_ID/adopt-read-paths"
```

4. Confirm the behavior on a real call before relying on it.

You know it worked when the adopt response lists your paths under `adopted` with nothing under `rejected`. The next agent call to that endpoint is still refused in this release (see **Widening** above). Only pending candidates can be adopted — anything else is refused with a `400` — every adopted path is re-validated against the denylist, both endpoints require `datasources.manage`, and both are audited. Existing adopted paths are preserved when editing other connection fields.

### Estate x-ray ignores widening

Estate x-ray does not use any of this. It runs on a credential-independent read-only registry where a gated call is denied outright rather than queued, it re-classifies with no operator configuration at all, it applies its own CLI read-verb floor instead of the connector's configured read verbs, and every denial is counted onto the scan as proof it wrote nothing. A scan therefore sees slightly less than an investigation does, on purpose.

## The write gate as a control matrix {#the-write-gate-as-a-control-matrix}

**Investigation datasource tools reject writes, regardless of whether the connected credential has provider write permissions.** Supported mutations are prepared and released through the Change executor. Approval gates may still pause sensitive read operations; approving a read gate does not allow an investigation tool to execute a mutation.

What counts as a write is decided by an intrinsic floor in code. Your per-agent approval list can only **add** gates on top of it; it can never remove one.

| Tool family | Runs without approval | Gated |
|---|---|---|
| Command-line connectors | `kubectl` reads the platform's own adapter verifies; no other binary, whatever verbs the operator declared read-only | Everything else |
| Generic API connectors | `GET` | Every `POST` (a path adopted as a read included), and every `PUT` / `PATCH` / `DELETE` |
| AWS native | Read action verbs (`Describe*`, `List*`, `Get*`, `Query`, `Scan`, `Lookup*`) — gating by HTTP method would pause every read, since AWS reads are form posts | Credential and secret reads, statement execution, every mutating action |
| Azure native | `GET`, plus a small read allowlist for `POST` | All other `POST`, and `PUT` / `PATCH` / `DELETE` always |
| Google Cloud native | `GET` | Every other method |
| MCP server tools | Only tools the server annotates `readOnlyHint=true` | Everything else — deny by default, because nothing here can know a third-party tool's semantics |
| Network devices | `show` / `display` reads | Configuration lines |
| `web_fetch` | Allowlisted domains | Every other URL |
| `http_get` | Never | Always |
| `web_search` | Always (PII-scrubbed query) | Never |
| `lake_query` | Always | Never — see below |

These guarantees apply independently of the chosen credential mode:

- **Write-role datasources are invisible to the agent.** A datasource marked with the write role is never rendered into any agent registry — not investigations, not chat, not x-ray. Its tools do not exist to the model, so they cannot be attempted, hallucinated or prompt-injected into being called. That credential is exercised only by the remediation path, behind a human click. Gated means "paused for a human"; write-role means "does not exist to the loop".
- **Shared credentials do not remove the read boundary.** `read_write` connections can supply reads to investigation, chat and discovery. Only the Change executor can use their write permissions, and only with explicit `allow_approved_execution` consent plus a valid reviewed plan. Separate credentials additionally restrict investigation in the provider IAM policy.
- **Chat with live connectors is read-only regardless of credential.** A member holding `chat.estate` can ask the analyst about the running estate, and the analyst answers from the tenant's real connectors — wrapped in the same read-only registry an x-ray uses. A mutating call is **denied before it executes**, never paused. A conversation is a read-only assistance flow, not an approval or execution channel. Write-role credentials remain invisible, a datasource allowlisted to other pillars is not rendered into chat, and `http_get` / `web_search` / `web_fetch` are removed outright, so there is no arbitrary-URL egress channel in a chat turn.
- **Estate x-ray is read-only regardless of credential.** A gated call inside a scan is **denied**, never paused — there is no approval that can let it through, and no operator setting that relaxes it. Two independent guards apply: the intrinsic floor, plus a command-line guard that ignores the operator's own declared read-only verbs. Every block is counted onto the scan's **denied writes** figure as customer-visible proof. A write-role datasource is refused at launch. Everything a scan proposes is applied as a **disabled draft** a human must enable.

`lake_query` is deliberately ungated because it is read-only by construction, three ways: the DuckDB connection is opened read-only; external file access is disabled at connect time on every connection, so filesystem table functions cannot reach host files or another tenant's lake; and the SQL guard accepts a single `SELECT`/`WITH` statement only, rejecting DDL, writes, extensions and filesystem functions after stripping strings and comments.

Editing an agent's approval list or its toolsets requires `pillars.manage`, which by default only the **owner** role holds. Someone who merely operates or approves cannot widen the gate. Full detail: [Configure the agents → Procedure: add an extra approval gate](/help/configure-the-agents.md#procedure-add-an-extra-approval-gate).

**One thing we will not overstate.** Untrusted-input fencing — every alert-derived string and every tool result enters the model inside `<<<UNTRUSTED ... >>>` delimiters, with a standing rule that fenced content is data and never instructions — is a *mitigation*, not a boundary. A determined prompt injection can still steer which reads the agent performs. The write gate and the always-gated `http_get` are the blast-radius limiter, and they are enforced in our code, outside the model's reach.

## Review a change on the incident {#review-a-change-on-the-incident}

An incident's **Prepared change** section names the change, target, connection, impact and recovery checks. For a prepared incident or standalone Change plan, the platform selects an enabled execution connection with **Allow use for approved plans** enabled whose capability and scope support the evidenced target, or asks you to choose between compatible connections. These steps do not need a saved remediation route. Expand **Exact changes and execution method** to inspect the API request, CLI arguments or repository edit. Authorized users can approve the reviewed action; other operators can request approval. Missing or ambiguous access is resolved on that incident before execution becomes available.

Review displays the actual API method/path/body, CLI arguments or repository edit that execution will use. Rollback and verification guidance is labelled separately: prose is not an executable command, and a validated restore action is shown only when available.

Unknown targets, unsupported operations and unconfirmed repository ownership require more evidence. A successful connection test is not approval, and a created PR is not a deployed fix. See [Review and apply a fix](/help/approve-and-run-a-fix.md#review-and-apply-a-fix).

## Use cases

### Proving least privilege at audit time

A compliance officer opens the page with `datasources.view` and, for each connector, reads the Role column: only the two remediation credentials carry a write use, and both read *remediation only* — kept out of every agent. He asks the platform owner to run **Audit perms** on the cloud connector; the dialog names the principal, lists the evaluated permissions, flags nothing as over-privileged, and states the gate classification — which read actions run freely, and that every write is gated regardless. He exports the evidence trail from [Audit log](/help/audit-log.md#export-evidence-for-an-auditor), where each connect, edit, test, permission audit, operation discovery, read-path adoption and route change is recorded with actor and timestamp.

## Next steps {#next-steps}

- [Write connections and approved fixes](/help/setup-write-connections.md) — connect and rehearse the write side.
- [Approval policy and change tiers](/help/approval-policy.md) — who releases what a gated call proposes.
- [Security and data handling](/help/security-and-data.md) — where every credential lives and what leaves your network.
- [Manage connections](/help/manage-connections.md) — the form, the catalog and the **Test** verdicts.
