Skip to main content

One Execution Argument: Why TeaQL Queries Receive Only UserContext

· 2 min read
TeaQL Team
Core Team

A generated TeaQL query has exactly one caller-supplied runtime dependency argument: UserContext.

await request.execute_for_list(ctx)

There is no second data-service, provider or connection argument. Those dependencies—together with tenant identity, authenticated user, permissions and policy—are installed when the trusted context is initialized and resolved from it during execution.

Why a second argument is structurally wrong

An API such as execute_for_list(ctx, service) creates two possible sources of runtime truth. The context may authorize one tenant while the separately supplied service points somewhere else. Even when today's implementation is safe, the shape invites future bypasses and inconsistent tests.

TeaQL therefore applies the context-only rule to list, one, entity-list, entity-one and mutation operations across Java, Rust, Go, Python, .NET and TypeScript. Required resources fail closed when context initialization omitted them.

An audit reason remains an explicit business intent value. It is not dependency injection.

Purpose is a type-state transition

Comment and purpose have different roles:

  • comment describes what operation is being performed and may appear anywhere in the builder chain;
  • purpose explains why the application needs the read;
  • after purpose, the Request transitions into an executable state.

A canonical flow is:

Q.orders()
.comment("Find orders awaiting review")
...filters, sorting, selections...
.purpose("Prepare the authorized review queue")
.executeForList(ctx)

Comment does not have to sit immediately before purpose. The important design constraint is that execution is not exposed before purpose.

Cross-language verification

The acceptance work removed obsolete Python and .NET two-argument forms and added required-resource resolution to generated runtimes. Tests cover successful injection, missing-resource failure and rejection of the old call shape. Freshly generated workspaces compile and execute with their formal runtimes.

This is an API-design control, not merely a runtime if statement: make the unsafe call difficult or impossible to express.