The brief
SignerX is a document-signing SaaS — recipients open a private link, fill the fields, sign, and the package routes itself through a multi-step workflow to the next signer or the finalizer. I led the API as the primary developer from October 2019 to April 2026. The codebase existed before me — what’s mine is what it became across those years: three Laravel major-version migrations, a multi-year build-out of the workflow engine, and an encryption layer protecting sensitive payloads end-to-end.
I’m not the original author. What’s mine is the shape of the codebase as it stands now — how it’s organized, how it scales, how it’s tested, and how it stayed current through a six-year run.
What I shaped
A request-level encryption layer. A DecryptPayloadMiddleware does
hybrid encryption end-to-end: clients encrypt the payload with
AES-256-CBC, encrypt the symmetric key with the server’s RSA public key,
and send both. The middleware decrypts the key with the private RSA
key, decrypts the payload with AES, and merges the plaintext back into
the request — controllers downstream are none the wiser. A companion
RequireEncryptionMiddleware enforces the policy on routes that handle
anything sensitive; legacy clients fall back to direct RSA; snake-case
normalization on the decrypted fields keeps the API surface clean.
A domain-organized data model. Forty-six Eloquent models split across eight domains — Auth, Billing, CMS, ConnectedServices, Documents, OAuth, Support, Workflow — with all six relationship types in active use, custom pivot models where the pivot tables earned them, ordered relationships, and self-referential trees (folders, sub-fields). The kind of discipline that pays off the moment you onboard a new developer or chase a multi-table query.
A queue-driven workflow engine. Twenty-five jobs running on Redis + Supervisor + Horizon. The interesting ones aren’t the cleanups — they’re the video pipeline (Qencode-orchestrated transcoding with an FFmpeg fallback and chunked uploads for large files), the connected-services sync (every completed package routes itself to the customer’s Dropbox or Google Drive automatically), and the recipient-reminder cadence that nudges signers without nagging them.
Event-driven orchestration. Twenty-five-plus domain events drive
the package lifecycle. A PackagePublishedEvent fans out to email
dispatch and activity logging; a RecipientSignedEvent updates state
and attempts package completion; a PackageCompletedEvent triggers
the final-PDF generation and connected-services sync. Listeners do
substantive work, and the event surface ends up being the most honest
documentation of how the platform actually moves.
A test suite that earns the term. Seventy-one feature test files covering the feature surface — packages, recipients, fields, subscriptions, the video pipeline, the encryption layer — each gated in CI on every PR. The test bench is what made three Laravel major-version migrations (7 → 8 → 9.52, one version at a time) survivable without a rewrite.
What’s notable about it
Six and a half years of disciplined ownership. The codebase stayed current with Laravel through every major version, the data model absorbed feature growth without re-architecture, and the workflow engine absorbed every “what if we also did X” the product team asked for without rebuilding the spine. The longevity wasn’t an accident — it’s what disciplined ownership of someone else’s codebase looks like when the goal is to make it last, not to put your own name on it.