mitwork/kalkan
A Laravel/PHP package for integrating Kazakhstan’s Kalkan cryptographic provider, offering tools for electronic digital signatures, certificate handling, signing, and verification in web applications.
Architecture fit. mitwork/kalkan is a thin Laravel client over an NCANode REST service — it does not perform cryptography in PHP, it orchestrates signing, verification, extraction and CMS operations against a Kalkan-backed Java service, plus QR generation. This makes it a good fit for Laravel applications in the Kazakhstan/eGov domain that need document signing without embedding a native crypto stack. v2.0.0 improves architectural alignment with the host framework: moving NcanodeHttpClient from Guzzle to Laravel's HTTP client means outbound calls now inherit the application's HTTP middleware, Http::fake() testability, retry/backoff, and centralized logging/tracing — a meaningful operability gain over a bespoke Guzzle client.
Integration feasibility. The package remains easy to adopt (composer require, config publishing, kalkan:install). The real integration effort is environmental, not code-level: a reachable NCANode instance, keystore/certificate provisioning, and a chosen TSA policy. v2.0.0 does not add integration surface — it constrains it.
Technical risk. v2.0.0 bundles a hard runtime bump with behavioral and API changes in a single major, which concentrates upgrade risk:
1.2.* (a security-supported- framework risk) or complete a framework upgrade first.signCms() now defaults to TSA_GOST2015_POLICY instead of TSA_GOST_POLICY, with older policies deprecated. This is the highest-risk item for a TPM, because it can change signature metadata and timestamp semantics. Any counterparty, validator or regulator expecting the older policy may reject or behave differently on newly produced signatures. Silent reliance on the default is the trap.$client is now PendingRequest rather than GuzzleHttp\Client. Any code that injected, mocked, or configured the Guzzle client directly (timeouts, proxies, TLS verification, handler stack) will break or silently lose that configuration.JsonException. This is arguably a correctness improvement — malformed payloads should not be swallowed — but it converts previously silent/undefined behavior into catchable failures on critical paths. Missing handlers will surface as unhandled exceptions in production flows.endroid/qr-code 6.0 may conflict with other packages pinning 5.x.json_encode-failure fix mean v2 may store different records and raise errors where v1 appeared to succeed. Teams should expect a short tail of "new" failures post-upgrade that are actually corrected behavior.Key questions.
signCms, verify, and extract get called, and what is the exception boundary for the new JsonException?1.2.* still receiving security patches, and for how long is staying there an acceptable, documented risk?endroid/qr-code 6.0 conflict with anything else in our dependency graph?Stack fit. Target state is PHP 8.3+ (8.4/8.5 supported) on Laravel 12 or 13. Confirm the rest of the dependency graph is Laravel-12-compatible before committing — kalkan is rarely the blocker; the surrounding packages (auth, admin panels, queue/observability tooling) usually are.
Migration path. Treat this as two independent workstreams that can run in parallel but must land in order:
kalkan 1.2.*. This isolates framework breakage from package breakage and is the recommended path for anyone starting on Laravel 10/11.2.0.0 once the framework is stable. The README's «Обновление с 1.x» section is the authoritative migration reference; note it is in Russian, so confirm the team can consume it or budget for translation.If the application is already on Laravel 12, the two can combine — but I would still recommend separate branches and separate test runs to keep failure attribution clean.
Compatibility. Laravel 13 and PHP 8.5 are supported on day one, giving a forward runway that most packages of this size do not offer. Staying on 1.2.* is viable only as a short, explicitly time-boxed position, since Laravel 10/11 are out of security support — the framework risk dominates the package risk in that scenario.
Sequencing.
NcanodeHttpClient construction/injection, signCms() calls (check whether TSA policy is explicit or defaulted), and all sign/verify/extract call sites for exception handling.2.0.0 exactly (no ^2.0 free-floating) in the upgrade branch.JsonException.Maintenance. The weekly scheduled CI run and Dependabot configuration are genuine maturity signals — they indicate the maintainer intends to catch transitive breakage early rather than reactively. PHPStan raised from level 5 to 7 raises the static-analysis bar and reduces the odds of type-level regressions landing in patch releases. Counterweights: this appears to be a small-maintainer package with a narrow contributor base (bus factor), documentation is primarily Russian, and the NCANode dependency is a separate operational concern the package cannot absorb.
Support. The dominant support burden is not the PHP package — it is the NCANode service and the PKI around it. Budget for: NCANode deployment/version management, TSA endpoint availability, key store and certificate lifecycle (expiry is the single most common "outage" in signing systems), and an owner for both. Establish a policy on how quickly we can move if NCANode has a breaking change upstream.
Scaling. Cryptography happens in NCANode, so scaling is primarily the service's CPU and memory profile, not the Laravel side. On the PHP side, move signing/verification into queued jobs rather than synchronous request paths — signatures and TSA round-trips are latency-heavy and benefit from retries. Watch request payload sizes for large documents (they traverse the HTTP client as request bodies), and set explicit timeouts and retry policies on the Laravel HTTP client rather than inheriting framework defaults.
Failure modes to design for.
JsonException on malformed responses — new in v2; must be caught at a defined boundary and mapped to a domain error, otherwise it surfaces as an unhandled 500.Ramp-up. Moderate. Engineers need two distinct competencies: Laravel HTTP client idiom (fakes, middleware, retry semantics) and a working mental model of Kazakh PKI — certificates, keystores, CMS structure, and TSA policies. The TSA policy distinction between TSA_GOST_POLICY and TSA_GOST2015_POLICY is not something a generalist can reason about from first principles; assign a named owner and document the choice in the repo. Estimate roughly one sprint for the framework uplift plus a focused half-sprint for the package bump, contract testing, and downstream validation — with the counterparty validation step as the schedule risk, since it depends on an external party's turnaround.
How can I help you explore Laravel packages today?