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

# 0409 — Access log: fails closed for configured classes and privileged surfaces, and an outbox sink

> Proposed · 2026-10-26

> [!NOTE]
>
> Proposed (STA-821). It amends
> [0212](https://docs.stackra.figentra.com/adr/0212-audit-evidence-access-logs-hash-chain-and-retention.md) open question 1 (a failed
> read audit never blocks the read). Linear STA-821.

## Context

`AccessLogService` always failed open: a read was served when its access record could not be written. That is right
for most personal data, but a financial or health read served unlogged breaks the evidence a regulator asks for. The
read audits also stayed in each service's own table, so the audit service never saw them.

## Decision

1. **Fail closed by class, as configuration.** `AccessLogConfig.failClosed` lists the data classes whose read is
   refused (`access_log_write_failed`, retryable) when its record cannot be written; the default is `financial` and
   `health` (the regulated special category). A market pack or deployment changes the list in runway.
2. **A privileged surface fails closed whatever its class**: `@AccessLogged({ failClosed: true })` on break-glass,
   impersonation or staff export reads.
3. **The record decides before the value leaves**: an async method resolves only after its record is written. A
   synchronous method cannot be held back; a fail-closed read is written async.
4. **An `outbox` sink.** `OutboxAccessLogSinkDriver` sends each record as `AccessRecorded`
   (`access_record.recorded`) through the outbox; the audit service chains and stores it.
5. **One canonical hash.** The chain hash is `@stackra/support`'s `canonicalHash` (ADR 0416), byte for byte the
   earlier form, so stored chains still verify.

## Consequences

* A sink outage now refuses financial and health reads; operators alert on `access_log_write_failed`.
* Services that report to the audit service set `sink: outbox`.

## Enforcement

`packages/security/access-log/src/core/services/__tests__/access-log.service.test.ts`,
`packages/security/access-log/src/core/drivers/__tests__/outbox-access-log-sink.driver.test.ts`,
`packages/security/access-log/src/core/functions/__tests__/hash-access-link.function.test.ts` (pinned hash).

## Supersedes and sources

Supersedes: none. Sources: STA-821 (services/audit SPEC gap 2); OS-289; STA-827.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.