<!-- ephemeral -->

# Rust Assist — Debug and SQL evidence

TeaQL captures structured SQL evidence on `UserContext`. Keep `sql` and
`parameter_count` in application diagnostics; `debug_sql` and raw `params` may
contain customer data and must remain inside a trusted, access-controlled test
or operator boundary.

```rust
use teaql_runtime::{SqlLogEntry, SqlLogOptions, SqlLogOperation, UserContext};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SafeSqlEvidence {
    pub operation: &'static str,
    pub parameterized_sql: String,
    pub parameter_count: usize,
    pub elapsed_micros: u128,
    pub result_count: Option<usize>,
    pub affected_rows: Option<u64>,
    pub result_summary: String,
}

pub fn enable_all_sql_evidence(context: &mut UserContext) {
    context.set_sql_log_options(SqlLogOptions::all());
    context.clear_sql_logs();
}

pub fn enable_select_sql_evidence(context: &mut UserContext) {
    context.set_sql_log_options(SqlLogOptions::select_only());
    context.clear_sql_logs();
}

pub fn enable_mutation_sql_evidence(context: &mut UserContext) {
    context.set_sql_log_options(SqlLogOptions::mutation_only());
    context.clear_sql_logs();
}

pub fn disable_select_sql_evidence(context: &mut UserContext) {
    context.disable_select_sql_log();
    context.clear_sql_logs();
}

pub fn disable_mutation_sql_evidence(context: &mut UserContext) {
    context.disable_mutation_sql_log();
    context.clear_sql_logs();
}

pub fn disable_sql_evidence(context: &mut UserContext) {
    context.disable_sql_log();
}

pub fn sql_evidence(context: &UserContext) -> Vec<SafeSqlEvidence> {
    context.sql_logs().iter().map(safe_sql_evidence).collect()
}

fn safe_sql_evidence(entry: &SqlLogEntry) -> SafeSqlEvidence {
    SafeSqlEvidence {
        operation: match entry.operation {
            SqlLogOperation::Select => "select",
            SqlLogOperation::Insert => "insert",
            SqlLogOperation::Update => "update",
            SqlLogOperation::Delete => "delete",
            SqlLogOperation::Recover => "recover",
        },
        parameterized_sql: entry.sql.clone(),
        parameter_count: entry.params.len(),
        elapsed_micros: entry.elapsed.as_micros(),
        result_count: entry.result_count,
        affected_rows: entry.affected_rows,
        result_summary: entry.result_summary.clone(),
    }
}
```

Every generated query must still carry non-empty `.comment(...)` and
`.purpose(...)`; every mutation must carry `.audit_as(...)`. Classify
not-found, validation/checker, optimistic-conflict, and provider errors rather
than converting them into an empty successful result.

Runtime log formatting accepts these environment values:

- `TEAQL_SQL_LOG`: `_silent`, `_summary`, `_full`, `_full_with_payload`;
- `TEAQL_SQL_LOG_TABLES`: comma-separated table focus;
- `TEAQL_AUDIT_LOG`: the same four levels;
- `TEAQL_AUDIT_LOG_ENTITIES`: comma-separated entity focus.

Query and mutation SQL logging are both enabled on a new `UserContext`.
`context.disable_select_sql_log()` and
`context.disable_mutation_sql_log()` are independent switches; use
`disable_sql_log()` only when both families must be silent. Each entry retains
`comment`, `purpose`, `audit_reason`, the typed multi-level `trace_path`,
parameterized SQL, copy-paste `debug_sql`, elapsed time, result count, and
affected rows. Rendered values remain trusted operator output and
`RuntimeTelemetry` must not export them.

---

## TeaQL seven-language assist contract

Apply the verified Rust semantic ceiling while using only the exact RUST generated and
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
model-aware Assist. Do not inspect generated domain-library source.

- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
- Human and non-human entities use different generated predicate vocabularies. Preserve
  forms such as “who are active” and “whose email is”; never infer them from English.
- Configure filters, projection, paging, and other query options before `purpose(...)`.
  Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
  requires both values, but comment does not have to immediately precede purpose.
- Every execute/list/stream and every save accepts exactly one context argument:
  `UserContext`. Name that argument `context`, never `runtime`; data services and global
  policy are injected when the context is built. Reserve `runtime` for process-level
  runtime ownership, provider/pool setup, and module assembly.
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
  and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
- If the required operation is absent after current entity/action and required field
  Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
  generated library as a fallback.
- Create each application-owned source file once. After its first compile attempt,
  repair only the smallest block identified by the exact compiler or test diagnostic.
  Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
- Before a repair that would replace more than 25% of an existing application file,
  stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
  estimated scope. Initial creation and model-driven regeneration are not repairs.

Capability: `debug`.

- Capture purpose, comment, trace/correlation id, parameterized SQL summary,
  duration, row count, provider, and the runtime's native response when available.
- Preserve the immutable row audit event and the customizable App Audit Sink as
  separate paths. Redact credentials, tokens, connection strings, and customer data.
- Document only switches and hooks present in the selected runtime source.
