dniccum/secret-stash-cli
A command-line companion for Laravel's secret stash, offering artisan commands to add, list, rotate, and remove encrypted secrets without leaving the terminal. Keep API keys and credentials organized, encrypted at rest, and easy to manage across environments.
secret-stash-cli is a PHP CLI tool for secret storage built around an envelope-encryption model: a master secret is unlocked once and then wrapped per device as individual "envelopes." The v1.1.1 patch is narrow in scope but diagnostically useful — it repairs a state where unlocking on one device failed to materialize envelopes for the account's other registered devices, leaving those devices unable to decrypt shared secrets until a repair pass runs. That is a data-consistency defect in the key-distribution layer, not a cosmetic bug, and it tells us the envelope lifecycle is the highest-risk surface in the package.
Architecture fit. This is a standalone PHP CLI rather than a Laravel-native package. It will not drop into config/ and a service provider and start managing env secrets out of the box. The realistic integration is as a subprocess or thin wrapper invoked from Artisan commands, deploy scripts, or CI steps, with Laravel owning orchestration and the package owning cryptographic state. That is an acceptable fit if your team already treats secrets as an external system of record; it is a poor fit if you expect Eloquent-style ergonomics or per-request secret resolution inside the framework.
Integration feasibility. Composer-installable and versioned under semver, which makes pinning straightforward. The real feasibility question is environmental: which PHP versions are supported, whether it assumes an interactive TTY for unlock passphrases, and where envelope state is persisted (local file, remote store, or both). The multi-device envelope model implies shared remote state; if that store is a bespoke backend, you inherit its availability and access-control characteristics.
Technical risk. Moderate. Three concerns rank highest. First, the fix itself indicates that a previously released 1.1.0 could leave accounts in a partially provisioned state — teams that adopted 1.1.0 should assume some devices may hold stale or missing envelopes and verify rather than assume the upgrade alone heals them. Second, per-device key wrapping is a pattern where "works on my machine" hides failures until a second device or a CI runner tries to decrypt; the blast radius of a lifecycle bug is total decryption failure, not a degraded feature. Third, a CLI-first tool typically has no framework-level audit hooks, so secret access logging must be built around it.
Key questions. Does the repair run automatically on unlock, or is an explicit command required? What is the persistence backend for envelopes, and is it encrypted at rest and access-controlled per identity? Are there Laravel service-provider bindings, or is process invocation the only supported path? What is the key-rotation story when a device is decommissioned? What PHP versions and non-interactive/CI unlock modes are supported? Is there a documented recovery path if all device envelopes are lost?
Stack fit. Best suited to teams running Laravel on containerized infrastructure with an external secrets workflow already in place — deploys, scheduled jobs, and CI pipelines that need secrets injected at boot. It is a weak fit for applications that resolve secrets per request at runtime or that expect first-party framework integration. Treat it as infrastructure tooling that a Laravel app consumes, not as an application dependency.
Migration path. Start read-only. Install at a pinned 1.1.1, run the unlock flow against a non-production account, and confirm envelope provisioning across at least two distinct devices plus one CI runner — that multi-device scenario is exactly what 1.1.1 addresses, so it is the correct smoke test. Migrate secrets in a single environment first, keeping the existing store authoritative until the new path has run cleanly through two full deploy cycles. Only then cut over, and keep the old store readable for a defined rollback window.
Compatibility. Pin the patch version explicitly and avoid floating constraints for now; 1.1.0 demonstrated that a patch-level fix can be required for correctness. Verify PHP runtime parity between developer machines, CI images, and production containers — CLI tools frequently diverge on extensions and TTY behavior before they diverge on application logic.
Sequencing. (1) Pin and install. (2) Run the envelope repair/verification step on any account touched by 1.1.0. (3) Validate multi-device decrypt on a staging account. (4) Wire the CLI into CI as a non-interactive step with credentials sourced from the existing secret store. (5) Add an Artisan wrapper command so application-level callers never shell out ad hoc. (6) Cut over one environment at a time, lowest criticality first. Do not parallelize cutover across environments; envelope state issues surface per-account and are easier to isolate in sequence.
Maintenance. Low ongoing code surface, but non-trivial procedural discipline. The package is maintained by a single author and is pre-2.0; expect infrequent releases with occasionally outsized impact relative to semver. Budget for reading changelogs rather than trusting patch-version semantics.
Support. No commercial support. Internal ownership must be explicit — ideally one engineer who understands the envelope model well enough to diagnose a decryption failure under pressure. That is a bus-factor risk worth naming to stakeholders.
Scaling. Cryptographic operations are cheap; the scaling constraint is the shared envelope store and the coordination it requires as device count grows. Every new CI runner, developer laptop, or ephemeral container that needs decrypt access becomes another device with its own envelope and its own lifecycle. Without a decommissioning and rotation process, the device roster grows monotonically and the attack surface with it.
Failure modes. Ranked by severity: (1) envelope state drift after unlock, the exact class fixed in 1.1.1, presenting as "works for me, fails in CI"; (2) lost passphrase or all-envelopes-lost, which is unrecoverable by design; (3) interactive unlock prompts hanging non-interactive CI jobs; (4) shared-store unavailability blocking deploys, since secret injection typically sits on the critical path to boot. Mitigation for (1) is a mandatory post-upgrade verification step; for (3), confirm a non-interactive unlock mode before CI integration; for (4), decide in advance whether deploys fail closed or fall back to the prior store.
Ramp-up. A developer can invoke the CLI productively in under an hour. Genuine fluency — envelope semantics, device provisioning, rotation, recovery — is closer to two to three days and should be treated as a prerequisite for whoever owns the integration, not discovered during an incident. Because the package is CLI-first with no framework affordances, there is no service provider to read as documentation; the onboarding path runs through the README and the changelog, which makes the changelog itself an operational artifact worth tracking deliberately.
How can I help you explore Laravel packages today?