承接 laravel-chronicle/core 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

laravel-chronicle/core

最新稳定版本:1.11.0

Composer 安装命令:

composer require laravel-chronicle/core

包简介

Tamper-evident audit ledger for Laravel applications.

README 文档

README

⭐ If you find Chronicle useful, please consider starring the repository.

Packagist Version Tests License All Contributors

Chronicle is a cryptographically verifiable audit ledger for Laravel.

Unlike traditional activity log packages, Chronicle records events in an append-only ledger protected by hash chaining, allowing audit history to be verified for tampering.

Chronicle is designed for systems that require reliable audit trails such as:

  • security logging
  • financial systems
  • compliance and regulatory reporting
  • forensic analysis
  • operational observability

📚 Full documentation: https://laravel-chronicle.github.io

Why Chronicle?

Most activity-log packages store events in a database table. Those records can usually be modified, deleted, or reordered — which makes them unreliable for security auditing or compliance.

Chronicle takes a different approach. Events are recorded in an append-only ledger protected by cryptographic hashing, and each entry is linked to the previous one through a hash chain. If any entry is modified, deleted, or reordered, ledger verification fails. This makes Chronicle logs tamper-detectable.

Feature Chronicle Traditional Activity Logs
Append-only ledger
Immutable entries
Hash chaining
Tamper detection
Verifiable exports
Signed checkpoints
Key rotation
External anchoring

Requirements

  • PHP ^8.2
  • Laravel ^12.0, or ^13.0
  • The ext-sodium extension (Ed25519 signing)
  • The ext-openssl extension (ECDSA P-256 signing and verification)

Installation

composer require laravel-chronicle/core
php artisan chronicle:install

chronicle:install publishes the config file and migrations and offers to run them. See the Installation guide for signing-key setup and the recommended production configuration.

Recording an entry

Every entry requires an actor, an action, and a subject:

use Chronicle\Facades\Chronicle;

Chronicle::record()
    ->actor($user)
    ->action('order.created')
    ->subject($order)
    ->metadata([
        'total' => 1000,
        'currency' => 'USD',
    ])
    ->tags(['orders', 'billing'])
    ->commit();

Chronicle generates a ULID, resolves the actor and subject, canonicalizes the payload, computes the payload and chain hashes, and persists an immutable entry inside a database transaction.

Automatic model auditing

Add the HasChronicle trait to audit an Eloquent model's lifecycle events automatically:

use Chronicle\Eloquent\HasChronicle;

class Invoice extends Model
{
    use HasChronicle;
}

created, updated, and deleted events are recorded automatically, with a structured diff for updates. For models you don't own, register an observer instead with Chronicle::observe(Invoice::class). See Auditing Eloquent Models.

Hash chaining

Chronicle protects the ledger with a cryptographic hash chain. Each entry references the previous one:

chain_hash(n) = SHA256(chain_hash(n-1) + payload_hash(n))

If any entry is modified or removed, the chain becomes invalid. See Hashing.

Signing and key rotation

Checkpoints, exports, and compliance reports are signed. Chronicle holds its signing keys in a key ring: one key is active and signs new artifacts, while every key (active or retired) remains available to verify the artifacts it produced. Each artifact records the algorithm and key_id it was signed with, and verification resolves the matching key from the ring — so rotating keys never invalidates existing checkpoints or exports.

// config/chronicle.php
'signing' => [
    'active' => env('CHRONICLE_ACTIVE_KEY', 'chronicle-key-1'),

    'keys' => [
        'chronicle-key-1' => [
            'provider'    => Chronicle\Signing\Ed25519SigningProvider::class,
            'algorithm'   => 'ed25519',
            'private_key' => env('CHRONICLE_PRIVATE_KEY'), // null once retired
            'public_key'  => env('CHRONICLE_PUBLIC_KEY'),  // keep for verification
        ],
    ],
],

Chronicle ships two built-in providers: Ed25519SigningProvider (libsodium) and EcdsaSigningProvider (ECDSA P-256 via OpenSSL, verified locally against a cached public key).

Rotating a key

php artisan chronicle:key:generate --id=chronicle-key-2   # mint a new keypair
# add the printed entry to signing.keys, then:
php artisan chronicle:key:rotate chronicle-key-2          # anchors a boundary checkpoint
# set CHRONICLE_ACTIVE_KEY=chronicle-key-2 and deploy

chronicle:key:rotate always creates a boundary checkpoint at the current ledger head before handing over, so the epoch boundary between keys is itself verifiable. When you eventually retire a key, keep its public_key in the ring — drop only the private_key. See Signing and Keys and the key rotation guide.

External signing providers (KMS / HSM)

Signing providers are pluggable, so the private key can live outside the application entirely. Providers sign remotely and verify locally against a cached public key, keeping verification offline and fast. An official AWS KMS adapter is available as a companion package:

composer require laravel-chronicle/kms-aws

To build your own (GCP KMS, Vault, HSM, …), see Custom Signing Providers.

Upgrading from 1.9.x? The previous flat signing config (a single provider / private_key / public_key / key_id) continues to work unchanged — Chronicle adapts it to a single-key ring automatically. Migrating to the signing.active + signing.keys shape is recommended but not required.

Querying the ledger

Chronicle provides an expressive query API with database-indexed scopes:

use Chronicle\Entry\Entry;

Entry::forActor($user)->get();
Entry::forSubject($order)->get();
Entry::action('order.created')->get();
Entry::withTag('orders')->get();

For large ledgers, Chronicle supports cursor pagination and constant-memory streaming:

Entry::stream()->each(fn ($entry) => /* process */);
Entry::cursorPaginateLedger(50);

See the Query API reference.

Checkpoints

Chronicle can create cryptographic checkpoints that anchor the ledger. A checkpoint signs the current chain head along with an entry count and timestamp, so auditors can verify integrity even if the database is later compromised.

php artisan chronicle:checkpoint

See Checkpoints.

External anchoring

Hash chaining and signed checkpoints detect tampering by anyone who can't forge a checkpoint signature. But an attacker holding both the database and the signing key could rewrite the chain and re-sign every checkpoint. External anchoring closes that gap: each checkpoint's digest is published to an append-only sink in a separate trust domain, so a rewritten ledger fails verification at the first anchored checkpoint — the attacker cannot forge the external attestation.

Chronicle ships an RFC 3161 trusted-timestamp anchor in core (standards-based, no cloud SDK; verified offline against the TSA certificate). Anchoring is opt-in and runs after each checkpoint commits — an anchor failure never invalidates the checkpoint.

// config/chronicle.php
'anchoring' => [
    'enabled' => env('CHRONICLE_ANCHORING_ENABLED', false),
    'providers' => [
        'tsa' => [
            'provider' => Chronicle\Anchoring\Rfc3161TimestampAnchor::class,
            'tsa_url' => env('CHRONICLE_TSA_URL'),
            'tsa_certificate' => env('CHRONICLE_TSA_CERTIFICATE'),
        ],
    ],
],
php artisan chronicle:checkpoint --anchor   # anchor synchronously
php artisan chronicle:anchor:retry          # retry pending/failed anchors
php artisan chronicle:anchor:verify         # attest stored anchors against their sinks

An official AWS S3 Object Lock (WORM) adapter is available as a companion package:

composer require laravel-chronicle/anchor-s3

See Anchoring.

Scalable verification

A full chronicle:verify recomputes every entry's hash — the ground-truth check. On large, ever-growing ledgers you usually don't need to re-walk all of history on every run. Because checkpoints now form a verifiable chain and record the entries they cover, Chronicle can verify incrementally:

php artisan chronicle:verify                        # full ledger (default)
php artisan chronicle:verify --since-last-checkpoint # trust the last checkpoint, verify only the tail
php artisan chronicle:verify --from-checkpoint=<id>  # verify a single segment (add --to-checkpoint=<id>)
php artisan chronicle:verify --checkpoints-only      # checkpoint-chain attestation, O(checkpoints)
php artisan chronicle:verify --resume                # continue from the last recorded run

Combine --checkpoints-only with --anchors for a fast, externally-rooted integrity proof: an anchored checkpoint is a trusted fast-forward point, so verifying the recent tail since one gives strong assurance without re-walking the whole ledger.

php artisan chronicle:verify --checkpoints-only --anchors

Upgrading an existing ledger? Run chronicle:checkpoints:backfill once so historical checkpoints gain their head/count/link metadata; until then the incremental modes safely fall back to a full verify. See Scalable Verification.

Verifiable exports

Chronicle can export the ledger as a verifiable dataset (entries.ndjson, manifest.json, signature.json) that can be verified independently of the application:

php artisan chronicle:export storage/app/chronicle-export
php artisan chronicle:verify-export storage/app/chronicle-export

Verification checks the dataset hash, digital signature, hash-chain integrity, and dataset boundaries — resolving the signing key from the key ring, so exports signed by a now-retired key still verify. See Exports and the Export Format.

Artisan commands

Command Purpose
chronicle:install Publish config and migrations (--force, --migrate)
chronicle:checkpoint Create a signed checkpoint
chronicle:export {path} Export the ledger as a verifiable dataset
chronicle:verify Verify the full ledger (or one entry with --entry=<ULID>)
chronicle:verify-export {path} Verify an exported dataset
chronicle:stats Display ledger statistics (--json)
chronicle:show {id} Display a single entry by ULID
chronicle:prune Prune entries by retention policy (--older-than, --before, --dry-run, --force)
chronicle:report {path} Generate a signed compliance report (--from, --to)
chronicle:checkpoints:backfill Backfill head/count/link metadata on existing checkpoints (--chunk, --dry-run)
chronicle:anchor:retry Re-attempt outstanding checkpoint anchors (--status=pending|failed)
chronicle:anchor:verify Verify stored checkpoint anchors against their providers (--checkpoint=)
chronicle:key:generate Generate an Ed25519 keypair for signing.keys (--id)
chronicle:key:list List the signing keys in the key ring (--with-counts)
chronicle:key:rotate {keyId} Create a boundary checkpoint and print activation instructions for a new key

See the Artisan Commands reference.

Features at a glance

  • Append-only ledger with immutable Eloquent entries
  • Hash chaining and deterministic canonical-payload hashing
  • Signing with Ed25519 or ECDSA P-256; signed checkpoints, exports, and compliance reports
  • Key rotation with a multi-key ring — retired keys keep verifying their own artifacts
  • External signing providers (e.g. AWS KMS) with remote signing and local verification
  • External anchoring of checkpoints (RFC 3161 timestamping in core; S3 Object Lock adapter) to detect tampering even under full internal compromise
  • Scalable verification — incremental, segment, and checkpoint-only modes for large ledgers
  • Verifiable exports with independent verification
  • Automatic model auditing via the HasChronicle trait or observers
  • Transactions & correlation IDs for grouping related events
  • Diff engine for capturing field-level changes
  • Extensible pipeline — validators, policies, and context resolvers
  • Storage driverseloquent/database, queued, array, null
  • Retention & pruning with checkpoint-aware deletion
  • Read-only web UI (optional Blade interface)
  • EventsEntryRecorded and EntryRejected
  • Testing helpersChronicle::fake() with fluent assertions

Design principles

  • Append-only. Entries cannot be modified or deleted; corrections are recorded as new entries.
  • Explicit intent. Every entry names an actor, action, and subject — no ambiguous "something changed" logs.
  • Cryptographic integrity. Entries are protected with hash chaining and signatures.
  • Low magic. Automatic auditing is opt-in; nothing is logged behind your back.
  • Transport agnostic. Works in HTTP requests, queue workers, CLI commands, and scheduled jobs.

Read more in Philosophy and the Architecture and Security Model docs.

Extending Chronicle

Chronicle is designed to be extended. You can write custom validators, policies, and context resolvers, swap in custom storage drivers or signing providers (for example, AWS KMS), and listen to ledger events. See the Extending Chronicle guide.

Roadmap

Planned for upcoming releases:

  • additional anchor adapters (Sigstore/Rekor transparency log)
  • additional external signing adapters (GCP KMS, HashiCorp Vault)
  • a dedicated Filament admin integration

Contributing

Contributions are welcome. Please read: CONTRIBUTING before submitting pull requests.

Contributors

Poorna Chandra Dinesh
Poorna Chandra Dinesh

💻
Vasileios Ntoufoudis
Vasileios Ntoufoudis

💻
James King
James King

📖
Carlos Alexandre
Carlos Alexandre

💻

Security

If you discover a security vulnerability, please report it responsibly. See: SECURITY for details.

License

Chronicle is open-source software licensed under the MIT license.

Credits

Chronicle was created to provide verifiable audit logging for Laravel applications.

If you find Chronicle useful, consider starring the repository ⭐

统计信息

  • 总下载量: 1.06k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 88
  • 点击次数: 1
  • 依赖项目数: 2
  • 推荐数: 0

GitHub 信息

  • Stars: 88
  • Watchers: 1
  • Forks: 4
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-06

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固