> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hyperterse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Input safety

> Statement substitution model, security implications, and defensive patterns.

Hyperterse uses textual substitution for `{{ inputs.field }}` placeholders. Before a statement reaches the connector driver, the executor performs two passes:

1. Environment substitution — `{{ env.VAR }}` placeholders are replaced with process environment values.
2. Input substitution — `{{ inputs.field }}` placeholders are replaced with string representations of validated input values.

The resulting statement is a complete string passed to the connector's `Execute` method. No parameterized query binding occurs at the substitution layer.

## Implications

* Values are inserted directly into the statement text.
* The connector receives the statement as a single string.
* Statement safety depends on query design and input validation.
* This is functionally equivalent to string interpolation — it does not provide prepared-statement injection protection.

## Built-in protections

Hyperterse validates and sanitizes inputs before they reach connectors or scripts.

### Input type validation

| Check               | Behavior                                                                             |
| ------------------- | ------------------------------------------------------------------------------------ |
| Required inputs     | Missing required inputs produce an error before execution.                           |
| Type conversion     | Values are converted to the declared type. Invalid conversions produce a type error. |
| Default application | Omitted optional inputs with defaults receive the default value.                     |

Type validation constrains the value space: an `int` input only accepts numbers, a `boolean` only accepts `true`/`false`. This eliminates injection risk for non-string types.

### Credential isolation

* Connection strings are server-side only.
* Auth policy values are resolved from environment variables and never returned in responses.
* Trace attributes redact sensitive values.

### Auth enforcement

* Tool-level auth runs before any input processing.
* Auth failures stop the request immediately.

## What the framework does not protect against

* SQL injection via string inputs — a `string`-typed input has no content restriction. Malicious SQL can be injected through string placeholders.
* Statement manipulation via crafted values — any input that contributes to statement structure (not just data values) is an injection vector.
* Business logic abuse — negative IDs, excessive limits, and semantically invalid values are not caught by type validation.

## Defensive patterns

Apply the following practices to minimize the surface area exposed to untrusted input.

### Use strict types

Prefer `int`, `float`, and `boolean` over `string`. Numeric and boolean types have constrained value spaces.

```yaml theme={null}
inputs:
  user_id:
    type: int
  active:
    type: boolean
```

### Validate strings in transforms

For `string`-typed inputs, validate format in an input transform:

```typescript theme={null}
export default function inputTransform(payload: {
  inputs: Record<string, any>
  tool: string
}) {
  const { email } = payload.inputs

  if (
    typeof email !== 'string' ||
    !email.match(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)
  ) {
    throw new Error('Invalid email format')
  }

  return payload.inputs
}
```

### Keep statements narrow

Use inputs only in value positions:

```yaml theme={null}
# Safe: input as a WHERE value
statement: "SELECT * FROM users WHERE id = {{ inputs.user_id }}"

# Dangerous: input as a table or column name
statement: "SELECT * FROM {{ inputs.table_name }}"
```

### Use handlers for dynamic queries

When a query needs dynamic structure, implement it as a handler with explicit sanitization:

```typescript theme={null}
export default async function handler(payload: {
  inputs: Record<string, any>
  tool: string
}) {
  const { user_id, fields } = payload.inputs

  const allowedFields = ['id', 'name', 'email', 'created_at']
  const selectedFields = fields.filter((f: string) => allowedFields.includes(f))
  // Construct query with validated field list
}
```

### Deploy behind a gateway

Place Hyperterse behind an API gateway or reverse proxy with rate limiting, request size limits, IP access control, and TLS termination.

## Environment variable safety

`{{ env.VAR }}` values are substituted without sanitization. If a variable contains SQL-significant characters and is used in a statement, the same injection risk applies.

Missing variables fail execution rather than defaulting to empty strings.

## Responsibility matrix

| Layer                     | Protection                                | Responsibility                  |
| ------------------------- | ----------------------------------------- | ------------------------------- |
| Input type validation     | Type conversion and required checks       | Framework (automatic)           |
| Credential isolation      | Connection strings hidden from callers    | Framework (automatic)           |
| Auth enforcement          | Pre-execution access control              | Framework (configured per-tool) |
| String input sanitization | Content validation and format enforcement | Developer (input transforms)    |
| Statement safety          | Avoiding structural injection             | Developer (query design)        |
| Network security          | TLS, rate limiting, access control        | Operator (infrastructure)       |
