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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Release Notes

v3.2.3 (2026-10-12)
-------------------

User-Agent identifies the PHP agent (v3.2.3)
--------------------------------------------

### Changed

- When `guardCoreVersion` is not set, the agent fills it from Composer's runtime API if `rennf93/guard-core-php` is installed (leading `v` stripped); otherwise it stays null. A value set by the caller wins.
- The ingestion `User-Agent` header is now `guard-agent-php/<version>` (was `guard-agent/<version>`, identical to the Python agent), so the Guard SaaS can tell the PHP agent apart from the Python one. Lockstep release with the agent family at 3.2.3.

___

v3.2.2 (2026-10-09)
-------------------

Expand Down
9 changes: 9 additions & 0 deletions bin/test_agent.php
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,14 @@ function assertStaticOnlyClass(T $t, string $class): void
// =====================================================================
// 2. Wire models
// =====================================================================
$t->section('guard core version');
$t->same('4.3.3', AgentConfigResolver::bareVersion('v4.3.3'), 'guard core version: leading v stripped');
$rootPackage = \Composer\InstalledVersions::getRootPackage()['name'];
$t->same(ltrim(\Composer\InstalledVersions::getPrettyVersion($rootPackage) ?? '', 'vV'), AgentConfigResolver::installedGuardCoreVersion($rootPackage), 'guard core version: an installed package resolves from Composer');
$t->same(null, AgentConfigResolver::bareVersion(null), 'guard core version: null stays null');
$t->same(null, AgentConfigResolver::resolve(['apiKey' => 'test-api-key-123'])->guardCoreVersion, 'guard core version: null when guard-core-php is not installed');
$t->same('9.9.9', AgentConfigResolver::resolve(['apiKey' => 'test-api-key-123', 'guardCoreVersion' => '9.9.9'])->guardCoreVersion, 'guard core version: a user-set value wins');

$t->section('models');

$event = makeEvent([
Expand Down Expand Up @@ -1698,6 +1706,7 @@ function assertStaticOnlyClass(T $t, string $class): void
$t->same('proj-smoke', $record['x_project_id'] ?? null, 'smoke: X-Project-Id header sent');
$t->same('install-smoke-1', $record['x_agent_install_id'] ?? null, 'smoke: X-Agent-Install-Id header sent');
$t->same(Version::USER_AGENT, $record['user_agent'] ?? null, 'smoke: User-Agent header sent');
$t->same('guard-agent-php/' . Version::VERSION, $record['user_agent'] ?? null, 'smoke: User-Agent names the PHP port');

// The mock runs with requireSigned=true, so a signature computed over the gzip
// bytes would have been rejected with 401; 200 proves the HMAC covers the
Expand Down
22 changes: 21 additions & 1 deletion src/Config/AgentConfigResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ private function __construct()
{
}

public static function installedGuardCoreVersion(string $package = 'rennf93/guard-core-php'): ?string
{
if (!class_exists(\Composer\InstalledVersions::class)
|| !\Composer\InstalledVersions::isInstalled($package)) {
return null;
}

return self::bareVersion(\Composer\InstalledVersions::getPrettyVersion($package));
}

public static function bareVersion(?string $prettyVersion): ?string
{
if ($prettyVersion === null || $prettyVersion === '') {
return null;
}

return ltrim($prettyVersion, 'vV');
}

/**
* @param array<string, mixed> $input
*
Expand Down Expand Up @@ -83,7 +102,8 @@ public static function resolve(array $input): AgentConfig
?? AgentConfig::DEFAULT_SENSITIVE_HEADERS,
maxPayloadSize: self::intInput($input, 'maxPayloadSize', 'max_payload_size', 1024),
guardVersion: self::optionalStringInput($input, 'guardVersion', 'guard_version'),
guardCoreVersion: self::optionalStringInput($input, 'guardCoreVersion', 'guard_core_version'),
guardCoreVersion: self::optionalStringInput($input, 'guardCoreVersion', 'guard_core_version')
?? self::installedGuardCoreVersion(),
compressionEnabled: self::boolInput($input, 'compressionEnabled', 'compression_enabled', true),
compressionThreshold: self::intInput($input, 'compressionThreshold', 'compression_threshold', 1024),
installId: self::optionalStringInput($input, 'installId', 'install_id'),
Expand Down
6 changes: 3 additions & 3 deletions src/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
*/
final class Version
{
public const VERSION = '3.2.2';
public const VERSION = '3.2.3';

/** User-Agent value sent with every request (mirrors guard-agent). */
public const USER_AGENT = 'guard-agent/' . self::VERSION;
/** User-Agent value sent with every request (identifies the PHP port). */
public const USER_AGENT = 'guard-agent-php/' . self::VERSION;
}
Loading