first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
# Audit log
## Purpose
`AuditLog` is the request-recorder that backs the `lastRequest()` and
`allRequests()` accessors on the mock IdP handle. Every HTTP request the
server processes is captured as a frozen `AuditRecord` and appended to
the log in serve-order. Tests can then assert on the recorded headers,
query string, body, and ordering without re-running the flow.
The records are deep-frozen at insertion time so audit consumers cannot
accidentally mutate captured state through their assertions.
## Features
- Frozen `AuditRecord` snapshots with method, path, headers, query,
body, and `at` (millisecond epoch) timestamp.
- `last()` returns the most recently appended record or `undefined`.
- `all()` returns a frozen shallow-copy snapshot of the records array,
preserving insert-order iteration.
- `clear()` resets the log between scenarios.
## Usage: Basic
```ts
import { AuditLog } from "@suaveplan/testing-integration-oauth-mock/control";
const log = new AuditLog();
log.push({ method: "GET", path: "/authorize", headers: {}, query: {}, body: "", at: Date.now() });
log.last();
```
## Usage: Advanced
When asserting flows that involve multiple requests, snapshot the whole
array up front and walk it deterministically rather than calling
`last()` repeatedly:
```ts
const events = log.all();
expect(events.map((e) => `${e.method} ${e.path}`)).toEqual([
"GET /authorize",
"POST /token",
"GET /userinfo",
]);
```
## API Reference
- `interface AuditRecord` — `{ method, path, headers, query, body, at }`,
all read-only and frozen.
- `class AuditLog`
- `push(record: AuditRecord): void`
- `last(): AuditRecord | undefined`
- `all(): readonly AuditRecord[]`
- `clear(): void`
## Implementation Notes
`push` performs an `Object.freeze` not only on the record itself but on
the nested `headers` and `query` objects, because callers can legally
hold the input object and mutate it post-push otherwise. `all()` returns
a frozen *copy* via `slice()` so the public snapshot can never reach
back into the internal array — preventing test mutations from corrupting
later assertions.