Skip to content

Decisions

One file per decision, numbered. The number is the identifier: it is what code cites, so it never changes and is never reused.

Each records the context that forced a choice, the alternatives weighed, and an outcome section when what shipped differed from what was decided. That last part is the point: a decision record whose outcome is never written back is how a document drifts away from the code it describes.

#Decision
0001Read certificates through ext-openssl, keep the CLI as a fallback
0002Parse the CMS in-package, by declared length
0003Temporary files live outside the package, with guaranteed cleanup
0004The seal is rendered in memory
0005PHP 8.4 and Laravel 13 as the floor
0006Sign by appending a revision, written in-package
0007PEM as a second entry point onto one pipeline
0008Exceptions name the fault that actually occurred
0009Cross-reference streams
0010Validation consumes the material signing writes
0011The report carries signing time and certificate validity
0012Certification signatures and DocMDP
0013Signing into a field the document already carries
0014Encrypted documents are refused, not signed badly
0015Objects packed into object streams are read, and written back uncompressed
0016Trust is the application's policy, and its verification is ours
0017The seal goes where it was asked for
0018Prefer the platform's own constructs: Laravel's helpers, and enums over class constants
0019Validation reads what it writes, one level down
0020Decode the filters documents actually use
0021Locking fields, and honouring the locks already there
0022The archive timestamp is a chain, not a state
0023A seal that can be transparent, and say what the caller wants
0024Revocation is evaluated, not counted
0025What signing does to PDF/A, measured
0026The verification tools are instruments, and nothing skips
0027The transport is a seam, so the profiles can be gated
0028The seal carries its own colour space, built rather than vendored
0029The identity a Brazilian signer is known by
0030Signing a document that is encrypted
0031Certification is verified by a reader that enforces it
0032What signing does to PDF/UA, measured
0033The seal honours the page's rotation
0034Signing takes ownership of the document
0035The audit trail is opt-in, and its context is an allowlist
0036The signed artefacts are reproducible, and their coherence is a gate
0037What we write, against the specification's own grammar

Nothing is currently proposed and unbuilt. The four that were, 0009, 0010, 0012 and 0013, all shipped in 2.2, and each carries the measurement that decided its shape rather than only the shape.

0012 carried a caveat for two releases, and it is closed. Its verification was deliberately incomplete, because pdfsig does not surface /DocMDP and no reader the project had would say whether a certification is enforced. 0031 found one that does, pyHanko, and made it a gate: a certified document modified beyond its level is now reported as violating its policy on every run.

Rules that break the product when violated are not decisions and do not live here. They are in the invariants.

Numbering after the split

0001 to 0037 were inherited from lsnepomuceno/laravel-a1-pdf-sign, with their original numbers. They are the reasoning behind code that was extracted rather than written here, and renumbering them would break every citation in that repository and every link anyone has followed.

This package's own decisions start at 0100. The gap is deliberate: the Laravel package keeps numbering upwards from 0038, and a shared range would guarantee two records with the same number within a release or two.

#Decision
0100The core is framework-agnostic, and five rules say what that means
0101Symfony is the only framework vendor the core depends on
0102A document arrives as a source and leaves through a destination
0103Encryption is the platform's, and the envelope is versioned
0104The regional layer is its own namespace
0105The seal's page is named, not sentinelled
0106Validation reports findings, and only one of them is a verdict
0107The /ByteRange is checked before it is believed
0108A signature can name itself, and say how long it lasts
0109Offline completeness is reported, and its limits are stated
0110A revision says what it changed
0111A field can be created, not only filled
0112The site documents one release line, and says which
0113The seal joins the structure tree
0114Verification has two implementations, and the binary stays the default
0115laravel-a1-pdf-sign is rebuilt on this package
0116Signing has two phases, and the key does not have to be here
0117A contract addition is a major release

Released under the MIT Licence.