Skip to content

sdk headers init - #160

Open
ewood-ac wants to merge 11 commits into
mainfrom
pmk-1281-headers
Open

sdk headers init#160
ewood-ac wants to merge 11 commits into
mainfrom
pmk-1281-headers

Conversation

@ewood-ac

Copy link
Copy Markdown
Contributor

No description provided.

ewood-ac and others added 11 commits October 24, 2025 13:50
Three changes to the client-identification headers:

The version was a hand-maintained `public static $SDK_VERSION = '7.0.0'`. That
has to be bumped by hand on every release and will silently go stale — at which
point the telemetry these headers exist to provide is actively wrong, which is
worse than absent. It now reads Composer's runtime metadata, falling back to a
constant only when that is unavailable (source checkout, no installed package).
The property was also public and mutable; the replacement is a method plus a
const.

The new User-Agent dropped the OS field that the old format carried. Anything
parsing that string for platform breakdown would have gone blank without
warning, so OS is back: `Postmark-SDK/<v> (PHP/<ver>; OS/<os>)`.

Also drops this branch's composer.json and CI edits. They overlap with the ones
in #164, which sets a wider range (adding 8.5 as well as dropping 8.1) and so
supersedes them — leaving both would just conflict. The PHP-version decision
belongs to that PR; this one is only about the headers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Restoring it to the merge-base copy: the previous commit reverted it to current
main, which pulled in main's own newer edits and made them read as this PR's.
getPrettyVersion() throws OutOfBoundsException when the package is absent from
Composer's installed map -- a vendored copy, a Phar, a php-scoper'd build, or
any future Packagist rename. class_exists() does not guard that: in a
Composer-managed host project the class exists and simply does not know about
us. Since sdkVersion() runs on every request, that fatalled every API call,
and OutOfBoundsException is not a PostmarkException so the documented
catch would not have caught it. Guard with isInstalled(), keep a catch as
belt-and-braces, and memoize so the lookup happens once rather than twice per
request.

Normalize the result to a valid RFC 9110 product-version token. Tags are
v-prefixed so getPrettyVersion() yields "v7.0.0" while the fallback is
"7.0.0" -- the header format differed by install shape -- and a branch install
yields "dev-feature/x", where "/" is a delimiter rather than a token character.

Declare composer-runtime-api, which the lookup actually depends on. Leaving it
out did not fatal, thanks to the class_exists() guard; it silently pinned every
report to the fallback, which defeats the point.

Keep the User-Agent product token as Postmark-PHP rather than Postmark-SDK, so
existing server-side reporting keyed on it does not break silently.

The version assertion compared the header against sdkVersion() -- the
production code agreeing with itself. Mutation-verified: returning
'0.0.0-WRONG' passed before and fails now. It derives the expected value from
Composer directly, and SdkVersionTest covers token validity, memoization,
normalization, and the fallback-vs-CHANGELOG invariant, all without credentials.

Also in the test suite, which this branch had already churned:
- Recipients moved to blackhole.postmarkapp.com. The addresses were real-domain
  and nonexistent, so each CI run hard-bounced against Postmark's own domain.
- Restored the multi-recipient fixtures in the string-or-array tests, which
  built them and then sent to a single address, removing the only coverage of
  the thing that file exists to test.
- Restored the outbound paging assertion from >= 1 back to 10.
- Deleted a sender-signature cleanup loop that compared against a fresh
  uniqid() -- it could never match, and issued one API call per signature in
  the account to guard a live delete behind that comparison.
- str_ireplace for the [TOKEN] placeholder: testing_keys.json.example documents
  it lowercase, so a fresh setup hit the new hard fail().
- Removed a dead getVerifiedSenderSignature() (no callers, undefined $tk in its
  catch) and dead $testDataCreated properties.
- Removed returns after markTestSkipped(), which is @return never.

PHPStan is clean and CHANGELOG records the header change for v7.1.0 -- additive
public API, so a minor.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant