Audit Management Changes¶
Purpose¶
Inspect canonical management changes independently of inference Requests. Audit records actual human or system actors, Organization/Team scope, action, target, revisions and time. Raw metadata and private content are not displayed.
Prerequisites¶
audit.read at the relevant Organization or Team scope. Organization audit readers may inspect all or selected Teams; Team readers see only authorized Team events and no Organization-scope events. Inference permission does not grant management audit access.
Procedure¶
- Open Manage → Audit, choose Audit scope, optionally choose an Action, and select Filter events. Action lists the actions recorded in the newest 20,000 events of the selected scope, grouped by their prefix (
team,key,membershipand so on); All actions removes the filter. After changing Audit scope, select Filter events once to see that scope's actions. The URL usesteamId=all|<teamId>,action=<exactAction>and an opaquecursor; anactionthe list does not offer stays selected as (unavailable) and still filters. - Read events in descending time/ID order, 50 per page. Older events follows a cursor bound to the current scope/action; Latest events returns to the newest matching page. Current authority is rechecked on every page.
- Inspect the actor, scope, action, target and revision evidence for the change you are investigating. Target names the changed item — a Team, key, service account, membership (by the person it belongs to), evaluator, dataset, score definition, experiment, rule, review queue, comparison, interpretation, role, management token, deployment, namespace or the Organization — and keeps
<type> · <id>beneath the name. Every other target kind shows<type> · <id>as its only text. Offline bootstrap uses a system actor; it is not attributed to a fabricated human session. - For a model/tool/deployment outcome, open Observe → Requests instead. Request policy/configuration evidence and financial attempts are separate from management audit.
Expected result¶
Audit reflects canonical role, membership, Team, key, budget, namespace and deployment changes, and each completed Trace export (trace.export, targeting trace · <Trace ID>). Audit events are append-only: the database refuses to change, delete or truncate a recorded event, and only removing an Organization clears its legacy audit rows. Management audit events also form one hash chain per Organization: each event stores the hash of the one before it, so an export shows whether any event was edited, removed or reordered after it was recorded. The record also holds:
session.sign_inandsession.sign_out: once for each Organization where the person holds an active membership, targetinguser · <user ID>, withmethod(magic_link,githuborenterprise) on a sign-in when it is known. Sessions that suspension or revocation end are not sign-outs and are not recorded as such.connector.oauth.connectandconnector.oauth.disconnect: a person's own Connector connection, or an administrator's shared one, targetingconnector · <server ID>.deployment.publish.refused: a publish a required evaluation gate refused, withcodeevaluation_gate_failorevaluation_gate_no_evidence. It targets the deployment, or the Agent when its first publish was refused.audit.export: each exported page.
Tool approval decisions appear as tool_approval.approve and tool_approval.deny with the decider as actor and a tool_approval · <id> target; requests and executions are Request evidence, not audit events. A target whose record no longer exists, or whose kind carries no name, shows <type> · <id> alone; the table makes no claim about why. A name is read inside your Organization under the same audit.read you read the events with, and grants no access to the named item. It never presents an Agent principal as the current caller or copies instructions, credentials or private transcript content into the table. Source configuration history is evidence, not an activation control.
Export and verify the audit record¶
Export the Organization's management audit events and check that the chain is intact. You need audit.read at Organization scope; a management token needs audit.read among its permissions.
- Create a management token with
audit.readunder Access, and setMC_MANAGEMENT_TOKENandMC_CONTROL_URLas in First management request. -
Export every page, from any working directory:
after=0 upto="" : > audit-export.ndjson while :; do query="after=$after&limit=1000${upto:+&until=$upto}" curl --fail-with-body --silent --dump-header headers.txt \ --header "Authorization: Bearer $MC_MANAGEMENT_TOKEN" \ "$MC_CONTROL_URL/management/v1/audit-events?$query" >> audit-export.ndjson upto=$(grep -i '^x-mission-control-until:' headers.txt | tr -d '\r' | cut -d' ' -f2) next=$(grep -i '^x-mission-control-next-after:' headers.txt | tr -d '\r' | cut -d' ' -f2) [ -n "$next" ] || break after=$next done -
Verify the file. From
platform/of the release:
Expected result: Audit chain verified in /path/to/audit-export.ndjson: N events, seq A to B, from the Organization's first event. Each page you exported appears in the record as audit.export, with {after, until, count}. The export covers the events that existed when its first page was served; later events, including the export's own audit.export events, belong to the next export.
With DATABASE_URL set, audit:verify --organization <Organization ID> checks the database itself and requires the chain to start at the Organization's first event.
A break prints Audit chain broken in <source> at seq <n>: <reason> and exits 1:
hash_mismatch: that event was changed after it was recorded;chain_broken: an event before it is missing, or the export was spliced;out_of_order: the lines are not inseqorder;organization_mixed: the file mixes Organizations.
Keep the export and the verification output as evidence, and treat a break as a security incident. An export that starts after the first event (after above 0) verifies from its first line and says so.
Verification¶
Change a synthetic key policy or Team allowance, then find its actual actor/target/revision event. A Team-only reader must not see foreign Team or Organization-scope events. Use a canonical Request to verify the resulting inference behavior; an audit row alone does not prove a provider call occurred.
Failure recovery¶
For an unavailable scope, inspect current audit.read authority. A filter cannot widen it, and the Action list holds only actions recorded inside the scope you may read. An action whose last event is older than the newest 20,000 events of the scope is not listed: narrow Audit scope to one Team, or put its exact name in the URL as action=<exactAction>. Use the correct Organization/Team and distinguish management event identity from Request/Trace identity. Former Audit → Decisions links now lead to Open Requests; the old decisions CSV endpoint returns 410 JSON rather than exporting legacy data. Use current Observe export with its separate permission. Current permission changes need no restart; a suspended session needs a new valid sign-in after recovery.