<!-- ephemeral -->

# TeaQL .NET Runtime Customization

The ASP.NET composition root owns the module, provider, request policy, trusted tenant and App
audit sink. These objects must never be model-bound from HTTP or federation JSON.

```csharp
using System.Text.Json;
using TeaQL.DataService;
using TeaQL.Runtime;

public static class RuntimeCustomization
{
    private static readonly HashSet<string> GovernanceKeys = new(StringComparer.OrdinalIgnoreCase)
    {
        "tenant", "trustedTenant", "provider", "dataService", "requestPolicy",
        "auditSink", "appAuditSink", "hardLimit", "continuousPage"
    };

    public static UserContext RequestContext(
        RuntimeModule module,
        IDataService provider,
        IRequestPolicy requestPolicy,
        string trustedTenant,
        IAppAuditEventSink appAuditSink)
    {
        var context = module.IntoContext()
            .WithDataService(provider)
            .WithRequestPolicy(requestPolicy)
            .WithAppAuditEventSink(appAuditSink)
            .WithTrustedTenant(trustedTenant);
        return context;
    }

    public static Task ReadinessAsync(UserContext context) => context.EnsureSchemaAsync();

    public static void RejectGovernanceOverride(JsonElement value)
    {
        if (value.ValueKind == JsonValueKind.Array)
        {
            foreach (var nested in value.EnumerateArray()) RejectGovernanceOverride(nested);
            return;
        }
        if (value.ValueKind != JsonValueKind.Object) return;
        foreach (var property in value.EnumerateObject())
        {
            if (GovernanceKeys.Contains(property.Name))
                throw new ArgumentException($"Untrusted governance override: {property.Name}");
            RejectGovernanceOverride(property.Value);
        }
    }
}
```

Generated queries and audited mutations receive only this context. Readiness reaches every
registered entity through the context-owned schema boundary when the configured provider is
schema-aware. Raw provider audit remains separate from
the safe event passed to `IAppAuditEventSink`; public DTOs contain business fields only.

## Runtime telemetry

Observability is optional and application-owned. Construct
`OpenTelemetryRuntimeTelemetry` with the application logger and explicit flush
and shutdown delegates, then call `context.WithRuntimeTelemetry(telemetry)`.
Keep `NoopRuntimeTelemetry.Instance` when absent. The application owns bounded
OpenTelemetry processors and OTLP exporters; exporter failure must never change
business results. Telemetry setup does not call `EnsureSchemaAsync`.
TeaQL derives `teaql.error.category` from the native error type. Sampling never
controls or replaces App Audit Sink delivery. Do not generate a Collector,
additional exporters, auto-discovery, or a telemetry configuration DSL.

---

## TeaQL seven-language assist contract

Apply the verified Rust semantic ceiling while using only the exact DOTNET 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: `runtime-custom`.

- Keep trusted dependencies and global runtime policy in UserContext initialization.
  Custom providers, policy hooks, and audit sinks must not add execute/save arguments.
- Preserve immutable row audit events and a separate customizable App Audit Sink.
  Include health, integration, and negative governance tests for every customization.
