Skip to main content

AIControls Data

Reference

MCP request and response fields for the AIControls Data administrator SQL preview.

For connection and query steps, see Connect an MCP server.

Availability and authority​

AIControls Data is exposed as four governed tools on the administrator endpoint /mcp/admin in every MCP-serving deployment, including managed and self-hosted installations, sidecars, and deployments with the UI disabled. The existing application and service-account endpoint /mcp remains supported. Both routes use the same Data provider, grants, and bounded reporting capacity. Data uses one bound deployment source store, backed by SQLite or PostgreSQL; SQL requests execute against a sanitized SQLite snapshot using the documented SQLite dialect. Authz-only mode does not expose Data tools.

Administrator SQL requires a current local session JWT or a personal PAT owned by an active persisted administrator, plus an explicit, current Data Access grant containing admin_sql. A personal PAT must be bound to that administrator's immutable account ID. Legacy email-only PATs, machine-ingest PATs, raw external OIDC tokens, service accounts, viewers, and builders do not qualify for administrator SQL. A personal PAT's tool scope must contain the exact qualified tool name, such as data__query; a valid empty tool list ([]) allows all Data tools, while wildcard or bare names confer no Data authority. Current account, credential, scope, and grant authority are checked before source access and again before results are delivered. Authentication alone creates no grant.

Use Authorization: Bearer YOUR_ADMIN_TOKEN for external clients. The current agentctl_session cookie is also validated on each request. An MCP session never preserves an earlier caller's Data authority after credentials change or disappear. The /mcp/admin endpoint rejects URL token parameters before authentication.

With the UI disabled, /mcp/admin supports existing personal administrator PATs without requiring a usable JWT provider. Local JWT validation and the JWT-only grant API require the deployment's existing session signing key; login routes stay disabled. Obtain a local session on a UI-enabled instance sharing the same source store and signing key, or before disabling the UI. No replacement signing key, users, sample data, or grants are provisioned for this endpoint. With storage disabled or the Data provider unavailable, Admin discovery hides Data tools and calls fail closed.

admin_sql grants deployment-wide access to all rows of the reviewed business tables. It is separate from the dataset, field, and row scopes of prepared and semantic queries. Those scopes remain unchanged; they do not narrow administrator SQL. Local UI administrators administer the deployment, and this preview does not support tenant-constrained SQL administrators or row-level isolation between customers sharing a source database. A tenant_id business column is available for analysis where published; it is not an automatic SQL authorization filter.

The normal MCP server enabled state, access controls, policies, approvals, rate limits, and response controls apply. This preview has fixed safety limits and makes no production capacity, high availability, complete export, or fairness guarantee.

Tools and transport​

Use /mcp/admin with your current administrator JWT or qualified personal PAT and an explicit Data grant. Applications and service accounts continue to use /mcp for their authorized prepared and semantic reporting tools. Successful SQL and schema tool results contain a JSON document in the MCP text content.

ToolRequest formPurpose
data__catalog{}Authorized logical reporting catalog; includes SQL discovery information when the caller has SQL authority.
data__catalogschema: "admin_sql"Paged business table, column, relationship, or exclusion metadata.
data__querysql, optional parameters, limit, and profileNative read-only SQLite query over reviewed business data.
data__queryPrepared or semantic requestExisting scoped reporting contract. SQL arguments cannot be mixed into this form.
data__explain_querySemantic requestSemantic validation and explanation; does not accept SQL.
data__coaching_contextOptional limitPrepared coaching evidence.

Each tool publishes a single flat input schema that lists every argument any of its forms accepts, with no top-level oneOf, anyOf, or allOf. Agents can pass the gateway's tool list to OpenAI or Anthropic function calling unchanged. The server picks the form from the arguments supplied and rejects mixed or incomplete requests with invalid_request.

Prepared report names remain recent_sessions, recent_pull_requests, coaching_context, and team_directory.

SQL request​

FieldTypeRequirement
sqlStringRequired. One read-only SQLite SELECT or WITH statement, up to 64 KiB of UTF-8 text.
parametersObjectOptional map from parameter names to typed values. At most 64 names.
limitIntegerOptional result row limit, 1–100; defaults to 50.
profileStringOptional fixed SQL execution budget: "interactive" (default) or "report". Prepared and semantic requests do not accept this field.

Unknown fields and mixed SQL/prepared/semantic requests are rejected. Parameter names contain ASCII letters, digits, and underscores, start with a letter or underscore, and are at most 64 bytes. Use :name in SQL and name as the map key. Every referenced parameter must be supplied, and every supplied parameter must be referenced. Positional ? and $name or @name parameters are unsupported.

{
"sql": "SELECT :answer AS answer, :note AS note",
"parameters": {
"answer": {"type": "integer", "value": "9007199254740993"},
"note": {"type": "null", "value": null}
},
"limit": 10
}

Supported SQL includes joins, CTEs, recursive queries, subqueries, aggregation, window functions, unions, and supported SQLite scalar expressions. Only reviewed business tables and columns are available. Writes, DDL, multiple statements, ATTACH, PRAGMA, system catalogs, extension loading, virtual tables, filesystem/network functions, and implicit rowid, _rowid_, or oid access are rejected. Use published primary-key columns instead.

SQL runs in an isolated snapshot of the referenced business tables. Source values retain their native encodings. Read each catalog column's unit and description before converting timestamps; seconds, milliseconds, nanoseconds, mixed historical encodings, and calendar date strings all occur.

The loader copies only columns required by the query. On SQLite-backed deployments, it also applies supported comparisons on source fields before copying rows. Existing SQL and parameters work unchanged. For example, a timestamp range inside a source CTE can keep older rows out of the snapshot. Required populations from repeated references are combined, so a comparison period or another branch of a UNION is preserved.

Filtering is conservative: complex expressions, filters through derived tables, and nullable sides of outer joins can require a wider snapshot. PostgreSQL-backed source reads retain the full bounded row population. The original query always runs against the resulting snapshot; result limits never become source sampling. A query still fails if its required snapshot exceeds a source bound, even when its final result would be a single aggregate row.

For a report whose required population exceeds the interactive source-row budget, explicitly select "profile":"report". This allows up to 1,000,000 source rows and 60 seconds for the complete SQL execution, including authorization, admission, snapshot loading, computation, and result release. A shorter caller deadline still applies. The source-byte, cell, and result bounds remain unchanged. The report profile uses the same administrator grant, read-only snapshot, shared reporting slot, and release checks. It is a provisional bounded reporting option, not a production capacity or fairness guarantee; neither profile guarantees every query will complete.

Both catalog discovery forms advertise execution_profiles, with each profile's name, maximum_source_rows, maximum_runtime_seconds, and source/result byte, cell, and row bounds. Report clients should require the "report" profile in discovery and request it explicitly. If the server does not advertise this profile, upgrade the server before running these reports.

Typed values and SQL results​

Each parameter and result cell is an object with type and value.

typeJSON encoding of valueMeaning
integerDecimal stringExact signed 64-bit integer. Use canonical decimal notation, such as "0" or "-42"; no leading zeros, plus sign, or "-0".
realJSON numberFinite floating-point value.
textStringUTF-8 text.
blobStringStandard base64-encoded bytes.
nullJSON nullSQL NULL.

Integer values are strings so JSON clients preserve values above JavaScript's safe integer range. Do not convert them to floating-point numbers. SQL expression types can differ between rows.

Result fieldTypeMeaning
query_idStringRandom 128-bit query identifier encoded as 32 hexadecimal characters. Correlates the durable admission and release receipts; contains no query content.
profileStringResolved SQL execution profile: "interactive" or "report".
columnsArray of objectsOrdered column metadata: name and type. SQL result column type is "dynamic"; inspect each cell for its actual type.
rowsArray of arraysTyped cells in the same order as columns.
truncatedBooleanMore rows exist than the requested result limit.
completeBooleanThe query result was not truncated. This describes the retained snapshot, not all historical activity.
source_tablesArray of stringsReferenced business tables copied into the snapshot.
source_rowsIntegerTotal rows copied after any supported source filtering, before the original SQL executes. This may exceed the rows contributing to the result.
source_bytesIntegerAccounted source bytes copied, with a minimum of eight bytes per copied source cell. Rows copied only to preserve row counts, with no required columns, account for eight bytes each.

The example above returns this shape, with a fresh query_id for each admitted query:

{
"query_id": "73e1cc8c00f6477eac76779675bc21f3",
"profile": "interactive",
"columns": [{"name":"answer","type":"dynamic"},{"name":"note","type":"dynamic"}],
"rows": [[{"type":"integer","value":"9007199254740993"},{"type":"null","value":null}]],
"truncated": false,
"complete": true,
"source_tables": [],
"source_rows": 0,
"source_bytes": 0
}

Source overflow fails the entire request, including aggregates. Row-limit overflow returns truncated:true and complete:false; this SQL response has no resumable cursor. Cell, row, or response byte overflow fails instead of silently shortening values. On SQLite-backed deployments, supported WHERE predicates can reduce the rows copied before source limits are checked. Unsupported predicates retain a wider source population. Neither an SQL LIMIT clause nor the request's limit reduces the source population copied.

Business schema discovery​

Call data__catalog with schema: "admin_sql". The schema revision is business-sql-v1, and the dialect is sqlite.

ArgumentTypeDefault and constraints
schemaStringRequired for this form; "admin_sql".
sectionString"tables" by default; also accepts "relationships" or "exclusions".
tablesArray of stringsOptional exact published table names, at most 50 names. Applies to tables and relationships. Omit for exclusions.
offsetIntegerDefaults to 0; must be nonnegative.
limitIntegerDefaults to 25; 1–50 entries per page.
include_columnsBooleanDefaults to true; false omits column detail from table entries.

Responses include revision, dialect, section, total, and limit, plus the selected section's array. total counts entries after any table filter. Follow next_offset until it is absent. An empty result section can be omitted from the response.

Section arrayEntry fields
tablesname, description, domain, owner, disposition, and columns. Each column has name, type, nullable, primary_key, description, classification, and disposition; optional unit describes its encoding. With column detail disabled, columns is null.
relationshipstable, column, referenced_table, referenced_column, and description. These document useful joins, not enforced foreign keys or evidence completeness.
exclusionstable, optional column, and reason. An absent column excludes the whole table.

Catalog column type is the snapshot storage class: INTEGER, REAL, TEXT, or BLOB. Nullability and primary-key metadata describe the source schema. New source fields are not automatically exposed. Credentials, dedicated raw-content stores, and unreviewed secret-bearing payloads are excluded; published business descriptions or policy text can still contain sensitive information entered by users.

Administrator SQL grant API​

The following routes are on the admin endpoint and operate only on the authenticated administrator's own grant. Use the current local UI session JWT; personal PATs cannot read or change these grant routes. There is no target user, tenant, or grant identifier in the request.

Method and pathRequestSuccess
GET /api/v1/data-access/admin-sql/grantNo body200 with the current grant, including expired or revoked state; 404 grant_not_found if no grant exists, after current identity validation.
PUT /api/v1/data-access/admin-sql/grantRequired expected_revision decimal string and enabled boolean200 with the created or updated grant.
{"expected_revision":"1","enabled":true}

To create your first grant, explicitly send {"expected_revision":"0","enabled":true}. This grants only discover and admin_sql, with no logical dataset or content permissions, and an initial lifetime of 365 days. It is an audited, revision-checked operation; startup and GET never create grants. enabled:false on a missing grant returns 404 without creating it.

For an existing grant, use its returned revision. Set enabled:false to remove SQL authority. Updates preserve logical dataset permissions, content permission, expiry, and revocation. They do not renew expired grants or restore revoked grants. A fresh demo seeds its administrator's missing grant; activation leaves every existing grant unchanged.

The returned grant includes:

FieldMeaning
principalBound tenant_id, subject_id, kind, and application_id. This route requires kind: "admin".
revisionCurrent grant revision as a decimal string; use it for the next update.
policy_epochCurrent authorization policy revision as a decimal string.
scope.capabilitiesCapability strings; includes "admin_sql" when SQL authority is enabled.
scope.datasetsExisting dataset entries with dataset, fields, and row_policy.
scope.contentExisting content permission.
expires_atUTC RFC3339 timestamp.
revokedWhether the grant is revoked.

Unknown PUT fields, missing fields, or malformed bodies return 400. A stale or nonpositive expected_revision returns 409 (revision_conflict). Authentication middleware rejects unauthenticated callers; authorization failures return 403. An unavailable Data provider returns 503. Grant-operation timeouts and storage failures return 500 with deadline_exceeded or unavailable. An enabled capability alone does not make an expired or revoked grant usable.

Limits and errors​

LimitValue
Total SQL runtimeInteractive: 5 seconds; opt-in report: 60 seconds
Concurrent reporting executions per provider1
SQL text64 KiB
Parameters / parameter name length64 / 64 bytes
Result columns / column-name length256 / 512 bytes
Expression depth / compound SELECT terms100 / 64
Referenced source rowsInteractive: 100,000; opt-in report: 1,000,000
Accounted source bytes256 MiB for either profile
Source cell, encoded result cell, or encoded result row64 KiB each
Result rows100; default 50
Encoded result document8 MiB
Schema discovery page50 entries; default 25

These bounds do not establish a hard native-memory limit or a production throughput guarantee. The source and result limits apply independently. SQLite query intermediates stay in memory rather than spilling to uncapped temporary sort files; intermediate memory itself has no hard cap in this preview.

Source limits apply to the required columns and conservatively scoped rows across all referenced tables. COUNT(*) preserves row counts without copying unused fields. On SQLite-backed deployments, semantic queries also apply supported numeric and timestamp source filters through their authorized dataset mappings, including seconds-to-nanoseconds normalization. Semantic text, boolean, and estimated-cost conversion filters retain a wider source population; PostgreSQL-backed source reads also retain the full bounded population. For example, a semantic query that filters only by developer email can copy 150 source rows and return one matching row. Its response reports 150 in evidence.rows_examined. A filter in the query does not guarantee fewer source reads.

Data request errors use the safe categories below; backend details are suppressed. MCP authentication or gateway policy errors can occur before the Data request is dispatched.

CategoryMeaning
invalid_requestInvalid fields, unsupported SQL, inaccessible schema objects, or invalid parameters.
access_deniedCurrent administrator, credential, binding, or grant checks failed.
limit_exceededSource, result, or SQL execution resource limit exceeded.
deadline_exceededThe operation timed out or its context was cancelled.
unavailableReporting capacity, a required source/service, or durable audit persistence is unavailable.

When known, a limit error includes a closed diagnostic suffix, such as limit_exceeded: source_read/source_rows, source_read/source_bytes, or source_read/source_cell_bytes. A deadline may identify its phase, such as deadline_exceeded: source_read. These labels contain no SQL, parameters, or backend details. An error does not contain a successful result receipt or completeness flags; clients must not treat it as an empty or complete report.

Governance and audit​

Policy evaluation and response controls receive the actual request and result. Ordinary diagnostic logs and SQL audit projections suppress SQL literals and parameter values. Audit records retain request-size/count metadata and event correlation without retaining a content-derived request fingerprint. Response denials use a fixed message so a policy cannot reflect blocked rows through its error message. Built-in Data responses bypass compression, noise filtering, and repeated-result omission so those optimizations do not rewrite typed values or retain a separate retrievable copy. Response policies and content controls still apply.

SQL approval records and notifications contain request-size/count metadata rather than SQL text or parameter values. Stored approval justifications also omit reflected SQL values. While a request is waiting on the local instance, currently active administrators can inspect its original details in the local portal; viewer accounts and the administrative MCP approval list receive only metadata. Another instance or a restarted instance has only the persisted metadata. Each SQL request requires its own approval; it cannot attach to another pending SQL approval. Approving a live request resumes its original execution, which still must pass the current SQL grant checks.

SQL execution commits an admin_sql_admission receipt before requesting the process-local reporting slot or reading source data. This receipt proves authorization to attempt execution, not acquisition of capacity. Before returning a successful result, the service rechecks current authority and commits an admin_sql_release receipt in the same transaction. Receipts use query_id as their execution identifier. If required receipt persistence fails, the result is not released.

Gateway audit events for completed and response-blocked SQL calls include the same query_id. It comes from the local provider before response controls run, so a policy that modifies or withholds the public result cannot erase that correlation. Caller-supplied fields cannot set it.

Release metadata records the result row count, the JSON byte length of the typed rows array, and a complete or truncated outcome. It excludes SQL text, parameters, cell values, and content-derived hashes. The byte count is separate from source_bytes and excludes result column metadata and the rest of the response envelope. A release receipt records an authorized release attempt, not confirmed client delivery; later response controls or a disconnected client can prevent delivery.

After admission, a failed SQL call records an admin_sql_failure receipt with one closed outcome: invalid_request, resource_limit, capacity_unavailable, source_unavailable, authority_unavailable, execution_unavailable, result_encoding_unavailable, release_unavailable, deadline_exceeded, or cancelled. Failure recording remains possible after authority revocation or caller cancellation because it releases no data. It has a separate two-second persistence deadline, including the local write-lock wait; this can extend error-response time beyond the execution deadline. Failure receipts contain no error messages, SQL text, parameters, or result values. Their row and byte fields are unmeasured and must not be interpreted as zero work.

Failure and release receipts are mutually exclusive for one query. If a release commits but its acknowledgement is lost, the service withholds the result and preserves the release attempt without inventing a failure receipt or claiming delivery. A process interruption or unavailable receipt store can still leave only admission; that means unresolved, not running or successful. A receipt-write failure returns unavailable and no rows. The private receipt ledger remains excluded. The typed query evidence tables below expose reviewed metadata without publishing the private payload.

Query operations evidence​

Administrators can query Data operations through the same governed SQL capability. Each received Data operation has a server-generated attempt_id, including malformed calls and policy denials. An authorized query also has a separate query_id. Catalog and explain operations retain their own mode. Nested semantic/prepared work belongs to one attempt.

TableEvidence
data_query_executionsIdentity when verified, safe request-size/count metadata, admitted and capacity-admitted times, outcome, closed failure details, gateway/audit correlation, and response/delivery state.
data_query_receiptsTyped admission, failed-execution and attempted-release receipts, with authority revisions and measured result counts where available.
data_query_phasesExclusive elapsed time for instrumented phases; uninstrumented_ns in the execution row accounts for the remainder.
data_query_source_usageApproved source names, preflight/read rows and bytes, accounting basis and measurement quality.
data_query_resourcesResult-row counts, runtime byte budgets, exact typed-row JSON bytes, sampled temporary-file peaks, and supported private SQLite compute-connection counters and sampled memory components.
data_query_rollupsHourly and daily outcome counts, duration sums and cumulative latency buckets through 60 seconds, plus overflow.
data_query_phase_rollups, data_query_resource_rollups, data_query_source_rollupsMergeable phase, resource and source summaries with missing-measurement counts or quality.
data_query_diagnostic_rollupsIndependent hourly/daily distributions for reason, failure stage/reason, response/delivery state and approved template.
data_query_persistence_healthLast observed per-Store evidence-write call/failure counts, elapsed write time and supported SQLite writer-lock acquisition time.
data_query_occupancyLast observed actual occupied slots and monotonic cumulative occupied-slot/saturation time for one Store instance.
data_query_configurationCurrent observed SQL profiles, actual process/Store admission cap, schema/build identity, cache and availability-measurement support, and retention policy.
data_query_grant_countsAggregate configured grant states and capability counts; grant changes remain in config_audit_events.
data_query_coverageObservation start, most recent traffic, retention boundaries and maintenance time.

These tables contain no SQL text, literal or parameter values, result contents, credential material or grant fingerprints. Their source reads are additionally fenced to the configured deployment tenant. They do not expand prepared or semantic dataset grants. Join detail evidence on both tenant_id and attempt_id; legacy direct receipt calls may have no attempt identifier. Audit and query detail have independent retention.

For an hourly outcomes chart, use a half-open UTC period with integer nanosecond parameters:

SELECT bucket_start, mode, outcome, SUM(attempts) AS attempts
FROM data_query_rollups
WHERE granularity = 'hour'
AND bucket_start >= :from_ns
AND bucket_start < :to_ns
GROUP BY bucket_start, mode, outcome
ORDER BY bucket_start, mode, outcome

Use granularity = 'day' for long periods. Sum duration totals and measured counts to calculate a weighted mean. Sum matching cumulative latency buckets across processes before calculating a percentile; the latency_over_60s column preserves the tail. Do not combine hourly and daily rows in one total. Buckets use the attempt's received time; timestamps are UTC Unix nanoseconds, while phase durations are elapsed nanoseconds. Convert timestamps to the report's selected timezone for display.

capacity_admitted_at and capacity_outcome describe the same process-local channel that limits execution. Overflow rejects immediately. There is no execution waiting queue. Evidence persistence has a separate SQLite writer-lock acquisition measurement; it is not a query queue-wait metric. The capacity is shared by repository handles attached to one Store; it is not a fleet-wide quota or fairness guarantee.

A completed execution outcome means the computation returned successfully; it does not establish delivery. response_blocked records a later governance decision. returned_to_transport means the handler returned the response to its transport, with client receipt still unknown. A receipt with outcome = 'bounded' reports measured result counts for a prepared/semantic response but leaves completeness and truncation unavailable. SQL receipts retain their explicit complete/truncated meaning.

audit_event_id is a server-generated correlation key, distinct from the numeric durable audit_events.id. The reviewed scalar columns audit_events.data_tenant_id, data_attempt_id, data_query_id, data_gateway_request_id, data_audit_event_id and data_audit_role allow exact joins without publishing audit arguments. Values come from the gateway-owned Data attempt; caller arguments and headers cannot set them. Historical/non-Data values stay NULL, and data_query_id remains NULL before query admission.

An attempt can have multiple durable audit rows, including additional policy evaluations and repeated audit delivery. data_audit_role = 'request' selects final request/response governance; 'policy' selects additional audit-mode evaluations. Use EXISTS or group the audit side before joining it to attempt totals. For example, this returns one row per attempt with a count of matching durable request audit rows:

WITH request_audit AS (
SELECT data_tenant_id, data_attempt_id, data_audit_event_id,
COUNT(*) AS matching_audit_rows
FROM audit_events
WHERE data_audit_role = 'request'
GROUP BY data_tenant_id, data_attempt_id, data_audit_event_id
)
SELECT e.attempt_id, e.query_id, e.outcome, a.matching_audit_rows
FROM data_query_executions AS e
LEFT JOIN request_audit AS a
ON a.data_tenant_id = e.tenant_id
AND a.data_attempt_id = e.attempt_id
AND a.data_audit_event_id = e.audit_event_id
WHERE e.received_at >= :from_ns AND e.received_at < :to_ns

The count describes audit rows, not unique evaluations or attempts. Audit delivery remains asynchronous with independent retention; a missing match does not prove that governance did not run.

Missing terminal acknowledgements become unresolved after the recorded deadline plus a grace period, or after one day when no deadline was available. This is evidence uncertainty, not a diagnosis that work is still running or failed. Recovery never repeats the query or releases an execution slot. Unresolved attempts contribute to phase and resource missing-measurement counts. A late checkpoint moves those counts with its updated dimensions; a late known completion replaces them atomically.

Measured work can survive a failed request. quality = 'lower_bound' denotes partial observations or sampled file peaks; NULL denotes unavailable measurements. A selected source that has not produced any rows before failure stays unavailable; a completed empty source read records measured zero. Source preflight bytes, source-read bytes, runtime result-budget bytes and exact typed-row JSON bytes use different accounting rules. Keep bytes_basis and measurement separate when aggregating. Prepared source joins expose bounded preflight populations and unavailable physical read counters. The private read-only SQLite compute connection additionally exposes sqlite_compute_cache_hits, sqlite_compute_cache_misses, sqlite_compute_cache_writes, sqlite_compute_cache_spills and sqlite_compute_temp_spill_bytes. These are observed connection-counter differences around computation with quality = 'lower_bound': the driver exposes masked 31-bit outputs, so full wraps between samples cannot always be detected. An observed zero is a zero lower bound, not proof of zero actual work. NULL denotes an unsupported, failed or detectably invalid observation. Cache counts are not source rows, physical source I/O or server result-cache activity.

sqlite_compute_cache_observed_peak_bytes, sqlite_compute_schema_observed_peak_bytes and sqlite_compute_statement_observed_peak_bytes are separately sampled SQLite memory components with quality = 'lower_bound'. Keep their bytes_basis = 'sqlite_dbstatus' separate from filesystem samples and result budgets. They are not total native heap, sort memory, per-query CPU, peak RSS or OS/cgroup pressure. Neither these samples nor temporary-file samples establish a native memory cap.

Detail is retained for 30 days, hourly aggregates for 400 days, and daily aggregates for 1,825 days. Bounded maintenance runs on Data traffic and evidence reads; an idle installation does not run a separate sweep. Earlier rows may remain until pruning catches up. Coverage starts when this instrumentation first records traffic; absence outside retained/observed coverage is not zero activity. Distinct lost attempts cannot be counted reliably, so dropped_attempts stays NULL. Evidence-write call failures are separately observable through the independent channel described below. Configuration and grant counts are as-of snapshots refreshed when selected; configured-active grants do not prove current account or credential authority. No authenticated Data health probe is present, so these records must not be used to claim service availability.

Diagnostic distributions and coverage​

data_query_diagnostic_rollups records six independent dimension values: reason, failure_stage, failure_reason, response_state, delivery_state and template. Each newly observed attempt contributes once to each distribution. Select one dimension and one granularity before summing attempts; adding distributions would count every attempt six times. An empty dimension_value means no applicable/observed detail, not a newly inferred failure. Only approved templates and closed reason/state vocabularies are retained. Caller identifiers are not added to long-term aggregates; caller drilldowns remain subject to detail retention.

These distributions use the original received-time bucket and retain mergeable cumulative latency buckets, sums and measured/missing counts. An unresolved attempt has unknown duration and reason = 'process_outcome_unknown'; a later known outcome replaces its prior diagnostic contribution atomically. There is no historical backfill. General query coverage from before this capability appeared does not establish diagnostic-distribution coverage.

Persistence health and occupancy​

data_query_persistence_health has three operation rows (begin, checkpoint, finalize) per Store instance. write_calls counts completed calls, including retries and validation failures. write_failures counts error returns; a lost acknowledgement can follow a committed write. Neither field counts unique missing attempts. duration_ns_sum includes the whole call. Supported writer_wait_count and writer_wait_ns_sum describe completed SQLite in-process writer-lock acquisition waits, including cancelled waits and calls still in progress; use their own denominator. These times overlap write duration. They do not measure pool waits, database locks, other-process contention or WAL pressure. PostgreSQL has no corresponding Store mutex, so writer_wait_supported = 0 and its wait fields are NULL.

The fixed-label Prometheus series aicontrols_data_evidence_writes_total, aicontrols_data_evidence_write_duration_seconds and aicontrols_data_evidence_writer_wait_seconds remain independent of database writes. They aggregate all Stores in the process, use only the closed operation/outcome vocabulary, and reset on process restart. Unobserved series may be absent. SQL health publication itself needs a functioning database: a failing store cannot provide a fresh SQL health snapshot, and unsampled in-memory counters are lost on process/Store teardown. No audit-drop counter is substituted for Data evidence loss.

data_query_occupancy follows the actual process/Store execution channel. Its active value is measured at observed_at. occupied_slot_ns integrates occupied slots over monotonic time; saturated_ns integrates time when all slots were occupied. For two externally retained snapshots with the same process_id and store_instance_id, divide the occupied-slot difference by the elapsed_ns difference for average occupied slots; divide again by capacity for utilization. A saturation-time difference divided by the elapsed difference gives the fully occupied fraction. A reporting query includes its own occupied slot. Acquisitions and once-only releases count actual execution-slot transitions, including slots released after evidence failure.

Both tables contain the last successfully persisted observation, refreshed only when selected by a SQL read. They are not periodic history or heartbeat tables. observed_from is Store instrumentation initialization; random store_instance_id changes when a Store reopens, and elapsed_ns is the monotonic denominator. Never subtract across reset identities or infer live free slots from an old row, unresolved attempt or missing observation. Counters saturate rather than wrap; exclude rows with counters_overflowed = 1 from cumulative arithmetic. Current active and capacity remain point observations. Bounded maintenance removes snapshots whose last observation is older than the 30-day detail window; absence remains unknown. These observations establish neither fleet fairness nor production capacity qualification.

Remaining capabilities have explicit owners: authenticated probes and trusted monitoring attribution (#3544), attributable execution resources, physical engine work and deeper database contention (#3545), and versioned observed configuration/grant history (#3546). Shared transport, protocol/session lifecycle and delivery evidence remain #3291. Reports must discover the live catalog and retain unavailable values until the corresponding producer is deployed; a handler return never proves client acknowledgement.