- Repository and folder:
FNET-github-dispatch-workflow - Human-readable name:
FNET-GitHub Dispatch Workflow - Composer package:
fnet/fnet-github-dispatch-workflow - PHP namespace:
Fnet\GitHubDispatchWorkflow
The name describes authentication and the single supported GitHub operation without implying official GitHub ownership.
src/
Configuration.php
Environment.php
GitHubAppClient.php
InstallationToken.php
Workflow.php
Exception/
Internal/
tests/
Support/
Unit/
docs/
Configuration, Workflow, InstallationToken, and GitHubAppClient are stable public API. Environment is public only to make environment sourcing deterministic and independently testable. Classes below Internal are not API.
Configuration is immutable and contains app ID, installation ID, private-key source, and User-Agent. Its constructor is fully programmatic. Configuration::fromEnvironment() resolves the existing GITHUB_APP_ID, GITHUB_APP_INSTALLATION_ID, and GITHUB_APP_PRIVATE_KEY keys plus GITHUB_USER_AGENT, with non-null programmatic overrides taking precedence.
Workflow is an immutable owner/repository/workflow/ref definition. Workflow::fromEnvironment() resolves the existing GITHUB_WORKFLOW_* keys with the same override semantics. The package never loads .env files.
GitHubAppClient composes internal key loading, JWT generation, and GitHub REST requests. Consumers inject a PSR-18 client plus PSR-17 request and stream factories. Runtime code never discovers or constructs a concrete transport. The base URL and API version are intentionally fixed internal compatibility constants; no GitHub Enterprise behavior was found.
The constructor accepts an optional PSR clock. An internal system clock is used by default. This preserves a minimal consumer API while allowing exact JWT and expiration tests.
GitHubAppException is a marker implemented by the package's runtime exception base. ConfigurationException, JwtException, TransportException, AuthenticationException, and WorkflowDispatchException distinguish actionable failure categories. Previous exceptions are retained. Messages never contain keys, JWTs, tokens, authorization headers, or arbitrary response bodies.
An optional PSR-3 logger defaults to NullLogger. Only operation names, installation ID, repository coordinates, workflow identifier, status, and GitHub request ID are logged. Authentication artifacts are never context fields.
Only standard interfaces are injected: HTTP client, request factory, stream factory, logger, and clock. There are no package-specific service interfaces, container, cache interface, event system, or inheritance-based hooks.
PHPUnit uses generated ephemeral RSA keys, a fixed clock, an in-memory PSR-18 fake, and Nyholm PSR-7 factories. Tests parse and verify JWTs without network access. PHPStan runs at maximum level for src and tests; PHP-CS-Fixer enforces PSR-12-compatible style.
- PSR HTTP client/message/factory: transport independence and interoperable requests.
- PSR Log: optional framework-independent logging.
- PSR Clock: deterministic time-sensitive behavior.
- OpenSSL and JSON extensions: secure RS256 signing and GitHub JSON payloads.
No JWT library is required because the existing compact RS256 construction is small, uses OpenSSL for all cryptography, and must preserve exact claims and timing. Encoding JWT JSON/base64url envelopes is protocol serialization, not a custom cryptographic primitive.