Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,22 @@

## Code and tooling

- All code must remain compatible with PHP 7.4, and PHPStan and PHP-CS-Fixer
must be run against PHP 7.4.
- All code must remain compatible with PHP 7.4. Run PHPStan and PHP-CS-Fixer
only under a PHP 7.4.x runtime; never run either tool under any other PHP
major.minor version.
- Use fully qualified `#[\SensitiveParameter]` on concrete executable
parameters when their established role normally carries a secret,
credential-bearing aggregate, or confidential Guzzle-owned container, and
the active frame can throw or invoke throwing code.
- Repeat the attribute on every qualifying owned caller, callee, concrete trait
method, and closure parameter. Do not add it to interfaces, abstract-only
declarations, pure/no-realistic-throw helpers, assignment-only sites,
arbitrary generic payloads, or completed non-recoverable derivatives.
- For PHP 7.4 compatibility, put `#[\SensitiveParameter]` on its own line and
the parameter on the following line, expand the complete parameter list, and
never add a comma after the final parameter. Native trace redaction starts on
PHP 8.2 and does not redact logs, messages, properties, wire traffic, captured
variables, return values, or the separate backtrace `$this`/`object`.
- Always pass an explicit character list to `trim()`, `ltrim()`, and `rtrim()`;
never rely on the default characters.
- Handle `preg_*` engine failures: when the result is used as data, test for
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- Added a `guzzle-server/stall-brief` endpoint that stalls mid-body for 1.5s, then completes
- Added `Server::enqueueRawBytes()` to queue verbatim-byte responses that bypass Node's HTTP handling
- Inline Digest auth so secure endpoints avoid optional `http-auth` and no-qop is deterministic
- Hide queued and received raw HTTP records in stack traces on PHP 8.2+

## 0.7.0 - 2026-07-16

Expand Down
11 changes: 11 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,14 @@ if (!is_int($validatedPort)) {
Server::$port = $validatedPort;
Server::$url = sprintf('http://127.0.0.1:%d/', Server::$port);
```

#### Sensitive Stack Trace Arguments

Queued and received raw HTTP records are marked with
`#[\SensitiveParameter]`. PHP 8.2 and later replace those arguments in stack
traces with `SensitiveParameterValue`. PHP 7.4 through 8.1 do not redact trace
arguments.

This does not redact the Node server log, other logs, exception messages,
object properties, wire traffic, captured variables, return values, user
callbacks, or the separate executing object in an explicit backtrace.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"php": "^7.4 || ^8.0",
"guzzlehttp/guzzle": "^8.0@dev",
"guzzlehttp/psr7": "^3.0@dev",
"symfony/polyfill-php80": "^1.25"
"symfony/polyfill-php80": "^1.25",
"symfony/polyfill-php82": "^1.27"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
Expand Down
27 changes: 20 additions & 7 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,10 @@ public static function flush(): ResponseInterface
*
* @throws InvalidArgumentException
*/
public static function enqueue($responses): void
{
public static function enqueue(
#[\SensitiveParameter]
$responses
): void {
if ($responses instanceof ResponseInterface) {
$responses = [$responses];
}
Expand Down Expand Up @@ -114,8 +116,14 @@ public static function enqueue($responses): void
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public static function enqueueRaw($statusCode, string $reasonPhrase, array $headers, ?string $body): void
{
public static function enqueueRaw(
$statusCode,
string $reasonPhrase,
#[\SensitiveParameter]
array $headers,
#[\SensitiveParameter]
?string $body
): void {
$data = [
[
'status' => (string) $statusCode,
Expand All @@ -139,8 +147,10 @@ public static function enqueueRaw($statusCode, string $reasonPhrase, array $head
*
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public static function enqueueRawBytes(string $bytes): void
{
public static function enqueueRawBytes(
#[\SensitiveParameter]
string $bytes
): void {
self::getClient()->request('PUT', 'guzzle-server/responses', [
'json' => [
[
Expand Down Expand Up @@ -176,7 +186,10 @@ public static function received(): array
}

return \array_map(
static function ($message): RequestInterface {
static function (
#[\SensitiveParameter]
$message
): RequestInterface {
if (!\is_array($message)) {
throw new \RuntimeException('Expected each received request from node.js server to be an array');
}
Expand Down