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

# Decision envelope

> Every /decide response carries a reproducibility envelope for audit and replay.

Every response from `POST /api/v1/public/decide` (and `POST /rulesets/{id}/explain-failure`) carries a small set of envelope fields that let callers reference, verify, and replay a specific decision — without the server having to echo potentially-PII inputs back.

If you're building anything regulated, audited, or support-ticketable, read this page.

## The fields

| Field                                               | Type                  | Example                                | Replay-critical |
| --------------------------------------------------- | --------------------- | -------------------------------------- | :-------------: |
| `decision_id`                                       | string                | `dec_k3h9s2MnPq_7xZbA`                 |        ✅        |
| `inputs_hash`                                       | string                | `sha256:5f4dcc3b...`                   |        ✅        |
| `engine_version`                                    | string                | `aethis-core@0.36.0`                   |        ✅        |
| `ruleset_id` + `ruleset_version` *or* `rulebook_id` | string                | `aethis/uk-fsm/child-eligibility`, `1` |        ✅        |
| `decision_time`                                     | string (ISO-8601 UTC) | `2026-04-17T12:34:56.789Z`             | informational\* |

\*`decision_time` is only replay-critical when a rule references wall-clock time.

### `decision_id`

Unique per invocation, format `dec_<16 urlsafe chars>`. **Fresh on every call** — two identical requests get different IDs even when the server serves the response from its decision cache. Use it in bug reports, support tickets, and client-side logs. The server emits a structured log line keyed by `decision_id`, so operators can trace a user-quoted ID back to full context.

### `inputs_hash`

Algorithm-prefixed SHA-256 over the [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) canonical form of `field_values`. Invariant under key reordering, whitespace, and `1` vs `1.0` vs `1e0`. Lets a caller prove "this decision was computed from exactly these inputs" without the server persisting or echoing the values. The `sha256:` prefix is forward-compatibility for when the algorithm rotates — parsers should split on `:` and route by algorithm.

### `engine_version`

Product-prefixed semver, format `aethis-core@<semver>`. Same value for the lifetime of a server process. Different engine versions can produce different outcomes for identical inputs and rule artefacts if DSL semantics or solver behaviour change — reliable replay requires matching the engine version.

### `ruleset_version` / `rulebook_id`

Ruleset calls return `ruleset_id` + `ruleset_version`; rulebook calls return `rulebook_id`. Together with `engine_version`, these pin the exact rule artefact used.

## How to replay a decision

The envelope is designed for two-party replay: the caller keeps the inputs they sent, the server re-runs the engine when asked.

1. Retain the original `field_values` and the full envelope on the caller side.
2. Re-run `POST /decide` with the same `field_values` and `ruleset_id`.
3. Verify:
   * `inputs_hash` matches the retained value → inputs are identical
   * `engine_version` matches → engine build is the same
   * `ruleset_id` + `ruleset_version` match → rule artefact is the same
   * The new `decision` equals the original → decision is reproducible

The new response will have a **different** `decision_id` and `decision_time` — those are per-invocation and deliberately excluded from the replay contract.

## Caching interaction

The server caches responses for identical `(ruleset_id, field_values, flags)` combinations for up to 10 minutes. Per-call envelope fields (`decision_id`, `decision_time`, `inputs_hash`, `engine_version`) are stripped before caching and stamped fresh on every response. **A cache hit is invisible from the envelope's perspective** — the ID is fresh, the hash is computed from the caller's actual inputs, the timestamp is current.

## Example

```json theme={null}
{
  "decision": "eligible",
  "fields_provided": 2,
  "fields_evaluated": 2,
  "decision_id": "dec_k3h9s2MnPq_7xZbA",
  "inputs_hash": "sha256:5f4dcc3b5aa765d61d8327deb882cf99",
  "engine_version": "aethis-core@0.36.0",
  "ruleset_id": "aethis/uk-fsm/child-eligibility",
  "ruleset_version": "1",
  "decision_time": "2026-04-17T12:34:56.789Z"
}
```

## What to log on your side

For audited workloads, retain at minimum:

* `decision_id` — your handle for this decision
* `inputs_hash` — proves the inputs later
* `engine_version` + `ruleset_id`/`ruleset_version` — pins the artefact
* Your own request correlation ID (e.g. application trace ID)

Retain the raw `field_values` separately if your compliance regime requires input-level audit; `inputs_hash` alone is sufficient for reproducibility proof, but not for "what exactly did the user submit" questions.
