rustclamp 1.1.0

A minimal synchronous entrypoint for Clamp applications.
# ADR 0021: Reference — a UUIDv7 on every request, command and action

Status: Proposed, 2026-09-30.

## Context

When something goes wrong, the first question is "which request was it?",
and today there is no single answer:

- The facade web server (`rustclamp::web`) gives a request no identity at
  all. Log lines carry the method and path, and a 500 page says nothing a
  user could report back.
- `rustclamp-http` mints `request-{N}` from a process-wide counter. It
  restarts at 0 on every deploy, repeats across processes, and says nothing
  about when the request happened. It also takes a client's
  `x-correlation-id` as the id, so any caller can choose or collide it.
- CLI commands, scheduled tasks and worker jobs have no id, and a job
  cannot be traced back to the request that queued it.

A UUIDv7 fixes all three. It is unique without coordination, and it starts
with its creation time in Unix milliseconds, so references sort by time.
Given only a time window, the lowest and highest possible reference in that
window can be computed. "Everything between 10:00 and 10:05" then becomes a
plain range comparison: `BETWEEN` in SQL, or string comparison over log
lines. The facade already generates v7 IDs (`rustclamp::uuid`); only the
core crates cannot reach them.

## Decision

1. **`rustclamp_core::Reference`**, std-only, no dependencies. It wraps a UUIDv7:
   - `Reference::new()`: a v7 ID, strictly increasing within the process
     (RFC 9562 §6.2, method 1: a 12-bit counter right after the time; a
     full counter moves into the next millisecond);
   - `Display` and `FromStr` in the hyphenated lowercase form;
   - `created_at() -> SystemTime`: the time the reference was minted;
   - `Reference::range(from, to) -> (Reference, Reference)`: the lowest and
     highest reference inside `[from, to]`, for range filters.

   The generator moves from the facade to core. `rustclamp::uuid::Uuid`
   keeps its API and uses core's v7 bytes, so there is one implementation.
   The facade depends on core only under its `uuid` feature, so Pico
   (ADR 0003) keeps zero dependencies.
2. **We always mint our own.** An incoming `X-Request-Id` or
   `x-correlation-id` is never used as the reference. It is logged next to
   the reference as `client_ref=…`, so a trace from another service can
   still be joined. The value is capped in length and never parsed, so an
   outside caller cannot choose, collide or inject a reference.
3. **Every entry point gets a reference, and every log line under it carries
   the reference:**
   - **Facade web:** `Router::handle` mints one per request, and
     `Request::reference()` returns it. The response carries it in
     `X-Request-Id`. Log lines written while handling the request add
     `ref=<reference>`, and the built-in 5xx error page shows it.
   - **`rustclamp-http`:** the request-context middleware mints a
     `Reference`, which replaces `request-{N}`. It is exposed the same way:
     request extension, `X-Request-Id` header, log field.
   - **CLI (`clamp`) and app commands:** one reference per invocation. On a
     failure, it is printed with the error.
   - **Worker and scheduler:** each job and each tick gets its own
     reference. A job queued while handling a request also stores that
     request's reference as `parent`, so one ID traces the whole chain.
4. **Finding things by time:**
   - `clamp ref <reference>` prints when the reference was created.
   - `clamp logs --from <time> --to <time>` (or `--ref <reference>`)
     filters log lines by reference range, without parsing timestamps.

## Order of work

1. Core type, and the facade `uuid` module switched onto it.
2. Facade web: minting, header, log field, error page. This is where the
   facade gains the per-request log context that the log line needs.
3. `rustclamp-http` middleware.
4. CLI, worker and scheduler.
5. `clamp ref` and `clamp logs` filters.

Each step ships on its own.

## Consequences

- Every log line under a request, command or job can be found from one ID,
  and a time window narrows to a reference range.
- The creation time can be read from a reference. That is fine for
  request, command and job references, which are operational IDs, not
  secrets. Anything that must hide its time (tokens) keeps using v4.
- Breaking for `rustclamp-http` users: a client's `x-correlation-id` is no
  longer the request's ID. It moves to `client_ref`.
- Minting costs one clock read, one lock, and 16 bytes from
  `/dev/urandom` per request. To keep that off the hot path, the random
  source is read in batches.
- The facade gains `rustclamp-core` as an optional dependency. The boundary
  table needs `rustclamp → rustclamp-core` in `OPTIONAL`.