PHP collector API

seamward/php-collector is the framework-neutral implementation shared by PHP adapters. It targets PHP 8.3 or later, has no framework dependency, and is available from Packagist as an alpha package.

Connection and policy

Connection::fromCredentials($connectionKey, $ingestToken, $endpoint) validates both Integration-owned values, derives the bound Integration id, and requires HTTPS except for localhost development.

RedactionPolicy accepts:

ArgumentDefaultPurpose
versionshape-only-v1Audit label stored with every payload shape
hashKeycollector-derivedLocal key used before identifiers enter an envelope
hashNamespacedeterministic local derivationNon-secret generation label for keyed hashes
dropFields[]Fields removed by the optional local payload redaction helper
hashFields[]Fields hashed by the optional local payload redaction helper

The default hash key is derived locally from the ingest token and the token itself is never serialized into an envelope.

Observations

Create an Observation with an Operation, status code, duration, and JSON-compatible payload. Convenience factories cover inbound webhooks and outbound HTTP APIs:

Code example

Operation::inboundWebhook('/webhooks/candidates');Operation::outboundHttp('POST', '/v1/candidates');Operation::queuePublish('candidate-events');Operation::queueConsume('candidate-events');Operation::scheduledFeed('nightly-candidate-import', 'inbound');

HTTP route templates must be bounded absolute paths without a query string. Surrounding whitespace is trimmed, and :id or {id} segments are normalized to {}. Queue and scheduled-feed targets use bounded stable labels. Use placeholders rather than concrete identifiers. JsonValue::decode() preserves the difference between JSON objects and arrays, including empty {}, [], and numeric-string object keys.

Optional observation metadata includes attempt, eventType, declaredContractVersion, deployment, correlation, and outcome. Raw correlation identifiers and business object ids are replaced by keyed hashes.

The completed envelope is validated strictly before enqueue. Unknown fields, invalid nested values, malformed deployment labels, noncanonical keyed hashes, missing operation identity, invalid status combinations, and malformed shapes are rejected locally. record() suppresses that telemetry failure and increments buildErrors.

Collector lifecycle

Collector::connect() accepts a validated connection, a transport, and optional buffer, policy, envelope builder, and batch size.

  • record(Observation $observation): void builds and buffers an envelope. It never throws.
  • observeQueuePublish(...) wraps an outbound queue publisher and projects success, rejection, or error to 202, 422, or 500.
  • observeQueueConsumer(...) wraps an inbound queue consumer with the same status projection.
  • observeScheduledFeed(...) wraps an inbound import or outbound export and projects completion, rejection, or error to 200, 422, or 500.
  • flush(): void ships the current queue. It never throws.
  • stats(): array returns seven delivery and build counters.

The default in-memory buffer holds 1,000 envelopes and drops the oldest entry on overflow. The default batch size is 50.

Collector::connect() also accepts deployment. Explicit valid values win over supported environment variables. A valid deployment attached directly to one Observation wins over the collector default. The core remains manual-flush by design and performs no destructor or timer-based network I/O.

Local redaction helpers

Redactor::payload($value, $policy) and Redactor::headers($headers, $policy) mirror the Node.js helpers for separate local logging or storage pipelines. Credential headers are always dropped. These helpers do not provide the envelope privacy boundary; payload values and headers cannot enter an envelope regardless.

Transport contract

Implement Seamward\Collector\Transport\Transport:

Code example

interface Transport{    public function send(ShippingRequest $request): ShippingResponse;}

The request contains endpoint, headers, and the exact JSON body covered by X-Seamward-Signature. Return the HTTP status and body as a ShippingResponse. Transport exceptions are caught by the collector.

Failure behavior

ResultQueue behaviorCounter
2xx except 207Remove the batchshipped
Valid 207Remove the batch and account per resultshipped and rejected
Non-retryable 4xxRemove the batchrejected
409, 429, 5xx, transport error, malformed 207Retain the batchfailedBatches
Buffer overflowDrop oldestdropped
Invalid observationDo not enqueuebuildErrors

Next steps