Pro edition
Output Pipeline — Deep Reference
At a glance
Section titled “At a glance”This page is the deep reference for the public surface of NextPDF\Pro\OutputPipeline. It covers manifest construction and validation, topological execution order, retry and timeout semantics, resume behavior, and the fail-closed pack-capability gate. It states parameters, defaults, and failure modes for every public symbol. Read the Output Pipeline capability page first for workflow guidance.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Pro (nextpdf/pro) and activates with a Pro-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.
The executor and seven of the ten step types carry no per-feature flag. Three step types additionally require a Pack capability:
| Step type | Manifest value | Required capability | Pack |
|---|---|---|---|
| Redact | redact | pack.privacy.redact | Privacy Pack |
| Extract | extract | pack.intelligence.extract | Intelligence Pack |
| OCR overlay | ocr_overlay | pack.intelligence.searchable_pdf | Intelligence Pack |
The gate is enforced at execution time, fail-closed, before the step reaches its resolver. An unlicensed gated step yields a Failed step result carrying the SPEC-LIC-001 code and the required capability; the resolver is never invoked. A pipeline with no injected capability resolver rejects every gated step.
Public API surface
Section titled “Public API surface”composer require nextpdf/pro:^3The nextpdf/premium metapackage installs the nextpdf/pro code; this module lives under the NextPDF\Pro\OutputPipeline namespace.
| Symbol | Parameters | Default behavior | Returns | Throws or fails with | Notes |
|---|---|---|---|---|---|
PipelineExecutor::__construct | StepResolverRegistry $registry, ?CapabilityResolverInterface $capabilityResolver = null | Binds the built-in resolver registry and the optional entitlement source | PipelineExecutor | Nothing declared | A null capability resolver rejects every pack-gated step |
PipelineExecutor::execute | PipelineManifest $manifest, array $variables = [] | Runs steps in topological order and aggregates results | PipelineResult | Nothing declared; resolver failures are captured as Failed step results | Designed to run inside an asynchronous job worker |
PipelineManifest::__construct | string $id, array $steps, PipelineOptions $options = new PipelineOptions(), ?string $resumeFromStepId = null | Validates the step graph at construction | PipelineManifest | InvalidArgumentException on an empty step list, duplicate step IDs, unknown dependencies, cycles, output-type mismatch, or a missing resume step; OverflowException above 10 000 steps | All validation completes before any execution |
PipelineManifest::topologicalOrder | none | Orders steps with dependencies before dependents | list<PipelineStep> | Nothing declared | Deterministic for a given manifest |
PipelineManifest::getStep | string $stepId | Linear lookup by step ID | ?PipelineStep | Nothing declared | null for an unknown ID |
PipelineManifest::rootSteps | none | Returns the steps with no dependencies | list<PipelineStep> | Nothing declared | Root steps run first |
PipelineManifestBuilder::create | string $manifestId | Starts a new builder | self | Nothing declared | The constructor is private; this is the only entry |
PipelineManifestBuilder::addStep | string $id, PipelineStepType $type, array $parameters = [], array $dependsOn = [], ?StepOutputType $outputType = null | Appends a step; a null output type is inferred from the step type | self | Nothing declared | Validation is deferred to build() |
PipelineManifestBuilder::stopOnError | bool $stop = true | Sets halt-on-first-failure | self | Nothing declared | Defaults to true |
PipelineManifestBuilder::maxRetries | int $retries | Sets the per-step retry ceiling | self | Nothing declared | Defaults to 0 (no retries) |
PipelineManifestBuilder::timeout | int $timeoutMs | Sets the global pipeline timeout | self | Nothing declared | 0 disables the timeout |
PipelineManifestBuilder::resumeFrom | string $stepId | Sets the resume point | self | Nothing declared | The step must exist at build() time |
PipelineManifestBuilder::build | none | Constructs the validated manifest | PipelineManifest | As PipelineManifest::__construct | — |
PipelineOptions::__construct | bool $stopOnError = true, int $maxRetries = 0, int $timeoutMs = 0 | Immutable execution options | PipelineOptions | Nothing declared | Readonly value object |
PipelineStep::__construct | string $id, PipelineStepType $type, array $parameters = [], array $dependsOn = [], StepOutputType $outputType = StepOutputType::Pdf | Immutable step definition | PipelineStep | Nothing declared | Direct construction defaults the output type to PDF for every type |
PipelineStep::isRoot | none | True when the step has no dependencies | bool | Nothing declared | — |
PipelineStepType (enum) | — | Ten string-backed cases: generate, merge, split, inspect, compress, sign, convert, plus the gated redact, extract, ocr_overlay | — | — | One case per built-in operation |
PipelineStepType::requiresPack | none | True for Redact, Extract, and OcrOverlay | bool | Nothing declared | All other cases return false |
PipelineStepType::requiredCapability | none | Maps gated cases to their capability codes | ?string | Nothing declared | null for non-gated cases |
PipelineStatus (enum) | — | Five cases: pending, running, completed, failed, cancelled | — | — | Shared by pipeline and step results |
PipelineStatus::isTerminal | none | True for Completed, Failed, and Cancelled | bool | Nothing declared | Pending and Running are non-terminal |
StepOutputType (enum) | — | Three cases: pdf, json, metadata | — | — | Drives build-time edge validation |
StepOutputType::forStepType | PipelineStepType $stepType | Default output type for a step type | self | Nothing declared | Inspect and Extract map to JSON; all other types map to PDF |
StepOutputType::isCompatibleWith | self $expectedInput | True for a same-type match or a PDF output | bool | Nothing declared | Helper; PDF is the universal input |
PipelineContext::__construct | string $manifestId, array $variables = [], ?string $resumeFromStepId = null | Per-run in-memory context | PipelineContext | Nothing declared | No TTL, expiry, persistence, or backing store |
PipelineContext::setStepResult / ::getStepResult | string $stepId (+ StepResult on set) | Records or reads a step result | void / ?StepResult | Nothing declared | null for a step not yet executed |
PipelineContext::setStepOutput / ::getStepOutput | string $stepId (+ mixed on set) | Stores or reads an intermediate output | void / mixed | Nothing declared | null for a missing output |
PipelineContext::hasStepResult | string $stepId | Whether a step already executed | bool | Nothing declared | Supports resume checks |
PipelineContext::allStepResults | none | All results recorded so far | array<string, StepResult> | Nothing declared | Keyed by step ID |
PipelineContext::isResume | none | Whether the run resumes from a step | bool | Nothing declared | — |
PipelineResult::isSuccess | none | True only for overall Completed status | bool | Nothing declared | Result is produced by the executor |
PipelineResult::getStepResult | string $stepId | Finds one step result by ID | ?StepResult | Nothing declared | null for skipped or unknown steps |
PipelineResult::failedSteps | none | Filters the failed step results | list<StepResult> | Nothing declared | Empty list on full success |
StepResult::isSuccess | none | True only for step status Completed | bool | Nothing declared | Carries stepId, type, status, durationMs, error, output |
CapabilityResolverInterface::hasCapability | string $capability | Affirmative entitlement test for one capability code | bool | Must not throw | Deny-by-omission: false for unknown, expired, or unmapped codes |
Entry-point signatures
Section titled “Entry-point signatures”final class PipelineExecutor{ public function __construct( private readonly StepResolverRegistry $registry, private readonly ?CapabilityResolverInterface $capabilityResolver = null, )
public function execute(PipelineManifest $manifest, array $variables = []): PipelineResult}final class PipelineManifestBuilder{ public static function create(string $manifestId): self
public function addStep( string $id, PipelineStepType $type, array $parameters = [], array $dependsOn = [], ?StepOutputType $outputType = null, ): self
public function stopOnError(bool $stop = true): self
public function maxRetries(int $retries): self
public function timeout(int $timeoutMs): self
public function resumeFrom(string $stepId): self
public function build(): PipelineManifest}interface CapabilityResolverInterface{ public function hasCapability(string $capability): bool;}Behavior contract
Section titled “Behavior contract”Manifest validation
Section titled “Manifest validation”Validation runs in the PipelineManifest constructor, before any execution. In order: the step list must be non-empty; the step count is capped at 10 000, converting adversarially deep dependency chains into a catchable OverflowException instead of native stack exhaustion; step IDs must be unique; every dependsOn reference must resolve; the dependency graph must be acyclic; output types must be compatible; a declared resume step must exist. Each violation raises InvalidArgumentException with a specific message.
The output-type check applies to steps whose type maps to PDF output: every dependency of such a step must itself produce PDF output. Dependency edges into JSON-producing step types (inspect, extract) are not type-checked in this release.
Execution order, resume, and timeout
Section titled “Execution order, resume, and timeout”execute($manifest, $variables) builds a fresh PipelineContext, computes the topological order, and runs steps sequentially in that order. With a resume point set, earlier steps are skipped until the named step is reached. Skipped predecessors are not re-executed and their outputs are not restored: the context is per-run and in-memory, so a resumed step reading a skipped predecessor’s output observes null.
The global timeout, when positive, is evaluated between steps, before each step starts. On expiry the pipeline status becomes Failed and remaining steps do not start. A step already running is never interrupted mid-execution, so one long step can overrun the budget.
Retries and failure capture
Section titled “Retries and failure capture”Each step receives at most maxRetries + 1 attempts. A successful attempt returns immediately. Any failed attempt — a Failed result from the resolver, or a thrown Throwable — is retried while attempts remain; the final attempt’s result is returned. A Throwable raised inside a resolver is downgraded to a Failed step result carrying the exception message, or Unknown error when the message is empty. execute() therefore always returns a PipelineResult; it never propagates a resolver failure.
A step type with no registered resolver yields a Failed step result with an explicit message; the run is not aborted. With stopOnError true (the default), execution halts on the first failed step and the pipeline status is Failed. With it false, execution continues and the final status is Failed if any step failed, otherwise Completed.
Pack-capability gate
Section titled “Pack-capability gate”Before any resolver dispatch, every pack-gated step (Redact, Extract, OcrOverlay) is checked against the injected CapabilityResolverInterface. The gate is fail-closed: a missing resolver, a false answer, or an unmapped capability code all reject the step. Rejection produces a Failed step result whose error carries the SPEC-LIC-001 code, the step type, and the required capability. A gated rejection consumes no retry attempts and reports a duration of 0.0. Implementations of the resolver must return true only for an affirmatively held entitlement and must not throw.
Result aggregation
Section titled “Result aggregation”PipelineResult reports the manifest ID, overall status, per-step results in execution order, total duration in milliseconds, and the total, completed, and failed step counts. stepsTotal counts every step in the manifest, including steps skipped by resume or unreached after a halt; stepsCompleted and stepsFailed count executed steps only.
Edge cases & failure modes
Section titled “Edge cases & failure modes”- The executor is designed for asynchronous execution inside a job worker. Inline use blocks the caller for the full pipeline duration.
- The global timeout is a between-steps check. A single long step can overrun the budget; no step is interrupted mid-flight.
- Resume skips steps within the same execution only. It does not restore outputs from any store; cross-run resume with cached outputs is not implemented.
- Constructing
PipelineStepdirectly defaults the output type to PDF for every step type. Use the builder, or pass the output type explicitly, soinspectandextractsteps declare JSON output and edge validation stays meaningful. - A resolver exception with an empty message is normalized to
Unknown errorin the step result. - Failed step results produced by the gate or by a missing resolver report a duration of
0.0. PipelineResult::getStepResult()returnsnullboth for unknown IDs and for steps skipped by resume or a halt; distinguish viastepsTotalversus the result list length.- This module performs no cryptographic operations and defines no FIPS-specific behavior. FIPS posture for the
signstep is governed by the signing module, not by the pipeline.
Conformance
Section titled “Conformance”The pipeline performs no format conformance work of its own. Conformance of each produced artifact is owned by the module behind the executing step — signing, optimization, conversion, and so on — and is documented on those modules’ reference pages.
Development notes
Section titled “Development notes”- The module source carries
@since 2.2.0; this reference documents the surface as shipped innextpdf/pro3.1.0. - All classes are
final; the manifest, options, step, and result types are readonly value objects. Construct new instances instead of mutating. StepResolverInterfaceandStepResolverRegistryare@internal. Step resolvers are built-in only; user-defined custom step handlers are not supported in this release.CapabilityResolverInterfaceis the public entitlement seam. Implementations must be deny-by-omission and must not default-allow.- This PHP executor is the manifest-validation and sequential execution path; production deployments may dispatch through the sidecar for parallel orchestration. The capability gate on the PHP path is independently fail-closed either way.
- Internal mechanism detail stays in the source repository’s internal documentation and is out of scope for this manual.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.
See also
Section titled “See also”- Output Pipeline — the capability page for workflow guidance.
- Output Pipeline — NextPDF Enterprise Deep Reference — batch orchestration across manifests.
- Document — Deep Reference
- Accelerator — Deep Reference