Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Core Laravel Package

laravel-chronicle/core

Cryptographically verifiable audit ledger for Laravel. Append-only entries are hash-chained so tampering, deletion, or reordering is detectable—built for security logging, compliance, and forensic audit trails.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Chronicle is a single-purpose, framework-native package: one Eloquent-backed append-only ledger table plus checkpoints, signed with a key ring, verified by artisan commands and a verifier service. It fits cleanly where an audit trail is a compliance artifact rather than a UI feature — financial postings, access/security events, order lifecycle, admin actions on regulated records. Where a team only needs "who changed this record," a conventional activity-log package is cheaper. The decisive architectural question is whether your auditors actually require tamper evidence, because that requirement is what justifies the hash chain, the key management surface, and the verification runbook. Chronicle does not attempt to replace your primary database or event bus; it sits alongside as a write-path concern with a commit() per entry, which keeps blast radius small and makes it adoptable incrementally rather than as a platform migration.

The design choices a TPM should note as mature: pluggable signing providers so the private key can live in KMS/HSM rather than app env; a key ring with an active key plus retired public keys, so rotation doesn't invalidate historical artifacts; boundary checkpoints created automatically on rotation; anchoring pushed to a separate trust domain (RFC 3161 TSA in core, S3 Object Lock as a companion) to close the "attacker has DB + signing key" gap; and tiered verification (full, --since-last-checkpoint, --from-checkpoint, --checkpoints-only, --resume) that acknowledges O(n) full verification is untenable on a growing ledger. The LedgerSeeder that drives the real write path is a genuine delivery accelerant — teams routinely discover late that fixture-based logs fail verification.

Integration feasibility. Low-to-moderate. Requirements are narrow but non-negotiable: PHP 8.2+, Laravel 12 or 13 only, ext-sodium and ext-openssl. The Laravel 12/13 floor is the most likely blocker — it excludes any application not yet on the current major, and forces an upgrade dependency between Chronicle adoption and framework upgrades. The extension requirements are usually satisfiable locally but need confirming against managed runtimes and container base images. Installation is a single composer require plus chronicle:install, and the README's upgrade note (1.9.x flat signing config still works, auto-adapted to a single-key ring) suggests the maintainers take backward compatibility seriously — a positive signal.

Technical risk. Concentrated in four areas:

  1. Maturity evidence is thin. 128 stars, 0 dependents, and an opportunity score of ~31 mean no public production pedigree. You are an early adopter, not a fast follower. MIT licensing and a compact codebase mitigate this — it is forkable and auditable — but budget for reading the hashing and verification code rather than trusting the docs.
  2. Write-path serialization. A hash chain imposes ordering on writes. Every commit() reads the current head and appends within a transaction. Under high write concurrency this becomes a contention point (row lock or advisory lock on the head) and caps throughput. This needs a load test before it goes anywhere near a hot path.
  3. Cryptographic operations. Loss of the active private key means new checkpoints/exports cannot be signed; loss of a retired public key means historical artifacts can no longer be verified. Both are unrecoverable-by-design and must be handled as secrets- management and DR requirements, not config.
  4. Immutable ledger vs. GDPR erasure. The feature table claims GDPR erasure support, which is in tension with "immutable entries." Whatever mechanism is used (likely crypto-shredding or a recorded redaction entry) must be understood and documented before legal signs off — this is the single highest-probability late-stage surprise.

Key questions for the maintainer / internal review.

  • What are the reference production deployments and observed entry volumes? What does write throughput look like under concurrent commits?
  • Does the package acquire a global lock on the ledger head, and what is the retry/backoff behavior under contention?
  • How exactly is GDPR erasure implemented, and does post-erasure verification still pass?
  • What happens on point-in-time database restore or a partial backup rollback — does the ledger fail closed, and how is the gap detected operationally?
  • Is there a published security review or threat model for the hashing/canonicalization path?
  • What is the maintainer's bus factor and release cadence commitment (semantic versioning, security response SLA)?
  • Are KMS/HSM signing providers a latency concern per checkpoint, and are checkpoints batchable on a schedule?
  • What is the retention policy for the ledger table — is there a supported archival/partitioning story?

Integration Approach

Stack fit. Native Laravel: service provider, published config, migrations, artisan commands, facade, Eloquent trait/observer, container-bound contracts (ReferenceLookup, signing providers). It composes with existing queue, scheduler, and event infrastructure rather than competing with it. The HasChronicle trait and Chronicle::observe() cover owned and vendor models, so coverage can start with two or three high-value models and expand without schema churn.

Migration path. Greenfield ledgers are trivial: install, configure signing, record. Existing ledgers require chronicle:checkpoints:backfill so historical checkpoints gain head/count/link metadata; until that runs, incremental verification modes safely degrade to full verify — a well-behaved fallback. There is no migration path from an existing activity-log table, and I would not build one: importing legacy rows into a hash chain only attests to data you already know is mutable. Run Chronicle in parallel with the incumbent log for a transition period, then decommission.

Compatibility. Pin the package version explicitly and wrap access behind your own thin service/facade rather than sprinkling Chronicle::record() through domain code — you want the option to swap or fork. The Laravel 12/13 constraint should be sequenced after any framework upgrade completes and soaks. Confirm ext-sodium/ext-openssl in CI, all container images, and every managed environment (staging, DR, and developer onboarding docs) — extension drift between environments is a classic silent failure.

Sequencing.

  1. Spike (1 sprint): install in a scratch app, record entries, run chronicle:checkpoint and all chronicle:verify modes, deliberately corrupt a row and confirm detection fails closed. Validate the extension and Laravel-version prerequisites.
  2. Threat model + policy: agree with security/legal on which events are auditable, retention, erasure semantics, and whether anchoring is required (it usually is if the "attacker has DB and key" threat is in scope).
  3. Key management: generate keys, store private material in your secret manager or KMS before any production write. Do not defer this — a ledger signed by a key that later moves is a migration headache.
  4. Pilot: enable on 2–3 models in one bounded domain, with anchored checkpoints scheduled and --anchors --checkpoints-only verification on a cron, alerting on failure.
  5. Load test the write path at expected peak concurrency; decide on queueing or write-shaping if the head lock bites.
  6. Generalize: expand trait/observer coverage, add dashboards, write the rotation and restore runbooks.
  7. Enable anchoring in production once the retry path (chronicle:anchor:retry) is scheduled and monitored.

Operational Impact

Maintenance. Ongoing cost is modest but real and cryptographic in nature: key rotation (generate → add to ring → chronicle:key:rotate → flip CHRONICLE_ACTIVE_KEY → deploy → retire private key, keeping the public key), scheduled checkpoints, scheduled verification, and anchor retry. Treat each of these as a runbook with an owner, not a wiki page. Upgrades should be pinned and staged; the 1.9.x compatibility story suggests low breakage risk, but with a small maintainer base, assume you may need to patch the code yourself.

Support. No commercial support tier is evident. Supportability therefore comes from: MIT license (fork rights), a compact auditable codebase, and the fact that failures are verifiable rather than silent. The counterweight is 0 dependents — you should expect to be the one discovering edge cases, and should staff accordingly rather than assuming community answers will exist.

Scaling. Three distinct scaling dimensions, each with a different answer:

  • Write volume: serialized appends are the ceiling. Measure it early; if it binds, reduce audited event volume, batch non-critical events, or offload recording to a queue with backpressure.
  • Storage: entries with metadata plus per-entry hashes accumulate monotonically and are not deletable by design. Plan partitioning and archival retention from day one; get legal/records-management to agree a horizon.
  • Verification cost: full chronicle:verify is O(n) and grows forever. The supported answer is incremental verification — run --checkpoints-only --anchors frequently (fast, externally rooted) and reserve full verification for periodic or post-incident runs. Query paths are fine: cursor pagination and Entry::stream() are constant-memory, and reference resolution avoids DB hits unless hydrate: true.

Failure modes and mitigations.

  • Corruption/tampering → verification fails loudly (intended). Alert on it; failing closed is the feature, but it will page someone at 3am, so define triage.
  • Anchor provider outage → non-fatal by design (anchor failure never invalidates a checkpoint); requires chronicle:anchor:retry scheduled and monitored, or anchors silently lag.
  • Signing key loss → cannot sign new artifacts; halt-and-escalate, not retry. Back up private keys under the same rigor as any root credential.
  • DB restore / PITR rollback → the tail of the ledger may disappear, leaving a valid-but-stale chain that passes verification. External anchoring is the actual defense here; without it you cannot distinguish "restored" from "never written." This is the strongest argument for enabling anchoring in production.
  • Head contention / deadlocks → commit retries under load; without instrumented retry metrics this presents as sporadic 500s on business operations.
  • Environment drift on ext-sodium/ext-openssl → install-time hard failure; catch it in CI, not in production deploy.

Ramp-up. Budget roughly: one sprint for the spike and threat model, one sprint for key management setup plus the pilot domain, and 2–3 weeks for runbooks, dashboards, verification scheduling, and load testing. The engineering learning curve is small — the API is pleasant — but the organizational ramp is the real work: security owns key custody, legal/records owns retention and erasure, SRE owns verification alerting, and audit liaison owns explaining the chain to an external auditor. Assign those owners before the pilot, because the first external audit question ("prove this log wasn't altered") is the point of the whole exercise, and answering it ad hoc is expensive.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics
robbiep/afterthedeadline
frankkessler/incontact-laravel-oauth2-rest
jlxh/laravel-userlog
davidmgilo/timetables
qylinfly/role-permission
reflect-digital/conduit
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr