ADR-0011: Retain Vault streaming without falling back to the PHP stream handler
- Status
-
Historical proposal (original status: Proposed)
- Date
-
2026-10-08
- Original decision makers
-
Project architecture/security owners; approval still pending in the original proposal.
- Requirements
-
HG-028, HG-029, HG-030, HG-036, HG-037
- Original supersession
-
None; a new decision for the proposed product.
Note
This is the full English translation of the historical proposal dated 2026-10-08, originally Proposed. Its pending approval is historical and creates no additional alpha approval gate. Current Security model and limits, Development and tests, Verification report and Requirements and security invariants describe the operative scope and evidence.
The later single-package decision is recorded in ADR-0015: One installable extension.
The proposed Vault adapter below is historical context. Its foreign reference overlay is retained outside this extension; this ADR does not establish a current Vault integration or deployment.
Context
Vault's ADR-039 describes streaming through a pinned curl-multi transfer whose
progress is driven while the response body is read. stream=true
would instead select the PHP stream handler and lose the pin. The
credential-bearing API deliberately encapsulates transport, promise and
secrets.
Sources: [S05, S08].
Decision
In v1, global middleware supports ordinary buffered sends and explicitly
rejects Guzzle's stream=true. This does not exclude Vault's
separate streaming API. Its adapter uses the same policy/ConnectionPlan logic,
but receives an internally controlled transfer lease for ongoing progress and
cancellation.
A single owner is responsible for the tick loop, settlement and release. Cancellation before start prevents the transfer; cancellation in flight closes the active socket. Body close, errors and aborted consumption release resources idempotently. Errors after partial responses are not presented as complete EOF success.
Vault retains credential injection, prior secret permissions, audit, buffer limits, idle/total time semantics and the distinction between proxy and origin responses in its existing regressions. The new v1 proxy boundary is treated as an explicit compatibility change rather than hidden. Its public API still exports no raw security options.
Rejected alternatives
- Remove streaming entirely: unnecessary product loss.
- Accept
stream=true: selects the wrong transport. - Copy the streaming mechanism anew: avoidable errors around EOF, buffer limits and cancellation.
- Expose a raw client: expands the credential-bearing surface.
Consequences
The demanding Vault feature is retained. Migration requires real streaming/cancellation tests and is not complete merely by replacing a factory. Long streams remain resource-bearing transfers that must be ended explicitly.
Evidence and acceptance in the original proposal
T058, T059, T060, T061, T069, T070, T071, T072. Details and
expected results are in Original verification specification. These tests
were specified, not executed as part of the original documentation delivery.
Reasons to reconsider
Global incremental streaming is a later feature. It must satisfy the same pin, lifecycle and error obligations, rather than merely enabling a different Guzzle switch.