NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Sentinel for Laravel

Denník, kontrolné body a kotvy

Samotná pečať dokazuje, že riadok zodpovedá nejakej pečati. Denník dokazuje, že zodpovedá tej najnovšej: každá udalosť pečatenia pridá záznam do sentinel_ledger chránený MAC nad jeho auditnými poľami a plánovaný sentinel:checkpoint nové záznamy zloží do zreťazených kľúčovaných kontrolných bodov a najnovší publikuje do nakonfigurovaných kotiev.

Sentinel::ledger()->checkpoint();                    // CheckpointResult or null
$report = Sentinel::ledger()->verify();             // LedgerReport
$report->clean();
$report->findings;                                  // list<LedgerFinding>
Sentinel::ledger()->history($invoice);              // list<LedgerRecord>
Sentinel::ledger()->head();                         // the newest checkpoint
Sentinel::ledger()->anchors();                      // ['cache']

Záznamy denníka

  • Pridávajú sa v tej istej transakcii ako udalosť pečatenia — sealed, resealed, acknowledged, baseline, rotated, deleted, unsealed — jedinečne pre (model, pečať, verzia), so súvislými verziami, ktoré prežijú zmazanie aj opätovné vytvorenie.
  • Každý záznam má vlastný MAC nad identitou, verziou, udalosťou, kľúčom, MAC pečate, predošlým digestom, názvami zmenených atribútov, predošlým stavom, aktérom a dôvodom. Úprava ktoréhokoľvek auditného poľa je EntryInvalid.
  • Len na pripájanie: aktualizácia či zmazanie LedgerEntry alebo Checkpoint cez Eloquent vyhodí LedgerIsAppendOnlyException — aj pri vypnutých udalostiach modelu.
  • Nikdy sa nečistí — je to dôkaz. Vypnutím (SENTINEL_LEDGER=false) stratíte detekciu podstrčenia a návratu.

Kontrolné body

sentinel:checkpoint (predvolene každú minútu) zamkne najnovší kontrolný bod, vyberie dávku nepriradených záznamov v poradí id, zreťazí ich od predošlého rootu, vloží kontrolný bod s vlastným MAC (podpísaný aktuálnym kľúčom ledger.ring) a záznamy si priradí — ich id vloží priamo ako celé čísla, nie cez parametre, takže dávka až 100 000 záznamov ostane pod limitom parametrov každého enginu. Záznamy potvrdené neskôr sa pridajú do ďalšieho kontrolného bodu; súbežné behy a obete deadlockov sa opakujú. LedgerCheckpointed sa spustí po commite a kontrolný bod sa publikuje do kotiev — tiež až po commite: kontrolný bod vytvorený v otvorenej transakcii sa do kotiev dostane, až keď sa transakcia potvrdí, a pri rollbacku nikdy (CheckpointResult::$anchors je vtedy prázdne). Ak nič nečaká, beh publikuje najnovší kontrolný bod znova do kotiev, ktoré držia starší alebo žiadny (prvé publikovanie zlyhalo, cache sa vyprázdnila) — nikdy do kotvy len na zápis.

use RoundlyConsulting\Sentinel\DataTransferObjects\CheckpointOptions;
use RoundlyConsulting\Sentinel\DataTransferObjects\LedgerVerifyOptions;

Sentinel::checkpoint(new CheckpointOptions(connection: null, batchSize: 500));   // one batch; null = nothing pending
Sentinel::verifyLedger(new LedgerVerifyOptions(entities: false));               // skip the per-entity head scan
Sentinel::verifyLedger(new LedgerVerifyOptions(manualAnchor: $payload));        // compare an AnchorPayload you kept
Sentinel::ledgerHead();                                                         // ?CheckpointRecord, unverified
Sentinel::anchors();                                                            // the configured anchor names

História jedného modelu

$entries = Sentinel::ledger()->history($invoice, 'financial', limit: 20);   // list<LedgerRecord>, newest first
$entries = Sentinel::for($invoice)->history();                             // the handle's seal
$entries = Sentinel::ledgerHistory($invoice);                              // flat form

LedgerRecord má id, event, version, ring, keyId, changed, previousStatus, actorType, actorId, reason, occurredAt a checkpointId (null, kým nie je v kontrolnom bode). Záznamy sa čítajú tak, ako sú uložené — na ich kontrolu spustite verifyLedger().

Kotvy

Kotva ukladá najnovší kontrolný bod mimo databázy. Bez nej sa obnova celej databázy (vrátane denníka a kontrolných bodov) zo staršieho snapshotu ani zmazanie konca kontrolných bodov odhaliť nedá.

DriverUkladáČíta späť
cacheput('{key}:{connection}', payload) natrvalo v anchor_drivers.cache.store — Redis, ktorý nie je databázou aplikácie.áno
filesystem{path}/{connection}/{seq}.json (zapíše sa raz) + latest.json na anchor_drivers.filesystem.disk — ideálne objektové úložisko s object lock alebo verziovaním.áno
logLog::channel()->info('sentinel.anchor', payload) — WriteOnlyAnchor, nikdy sa neposiela znova.nie — len zápis; porovnáte cez sentinel:verify --ledger --anchor='<json>'
vlastnýSentinel::extendAnchor()podľa vás
SENTINEL_ANCHORS=cache,filesystem
SENTINEL_ANCHOR_CACHE_STORE=anchor-redis
SENTINEL_ANCHOR_DISK=s3-locked

Obsah (sentinel.anchor/1: connection, seq, root, at, ring, keyId, algorithm, mac) nesie MAC kontrolného bodu, takže zmenená kotva sa odhalí; podvrhnutá kotva, ktorá tvrdí, že je napred, spôsobí len planý poplach. Publikovanie prebieha po commite a bez záruky: zlyhanie spustí AnchorPublishFailed, zaloguje sa a ďalší beh publikuje znova do kotiev, ktoré zaostávajú. Za zlyhanie sa počíta aj úložisko, ktoré neúspešný zápis ohlási vrátením false namiesto výnimky (disk s vypnutým throw — predvolené v Laraveli — alebo cache store null): AnchorPublishException. Vlastné kotvy nájdete v časti Rozšírenie.

Kotva si ponechá dôkaz

Kontrolný bod nikdy neprepíše kotvu takým, ktorý nenadväzuje na to, čo drží. Pred publikovaním sa latest() každej kotvy porovná s databázou: ak databáza ukotvené seq už nemá (obnova) alebo ho má s iným rootom, publikovanie sa odmietne — published false, AnchorPublishFailed s AnchorPublishException, varovanie v logu — a kotva si svoju kópiu ponechá, takže sentinel:verify --ledger ďalej hlási anchor_ahead (alebo anchor_mismatch, keď má databáza pri tom seq iný kontrolný bod). Každý ďalší beh odmietne znova, kým to niekto nepreskúma. Po zámernej obnove zistite, čo sa stalo, a potom kotvu vyčistite (zmažte latest.json alebo kľúč v cache), aby sa ďalší kontrolný bod publikoval nanovo. Kotva, ktorá už tento kontrolný bod alebo novší z tej istej reťaze drží, sa počíta ako publikovaná a ostane nedotknutá.

Overenie denníka

$report = Sentinel::ledger()->verify();            // every connection, entity heads included
$report = Sentinel::ledger()->verify('tenant', entities: false, chunk: 5000);

$report->checkpoints;                              // checkpoints verified
$report->entries;                                  // ledger entries verified
$report->anchorsChecked;                           // anchors compared
$report->findings;                                 // list<LedgerFinding>

$report->clean();
$report->violations();                             // findings except backlog and unreachable anchors
$report->has(LedgerFindingKind::AnchorAhead);
$report->throwIfViolated();                        // LedgerIntegrityException

Pre každé pripojenie v ledger.connections overenie kontroluje:

  • Kontrolné body v poradí seq: súvislé (CheckpointGap), zreťazené (ChainBroken), s MAC od použiteľného kľúča kruhu denníka (CheckpointInvalid) a každý root prepočítaný nad jeho záznamami s kontrolou MAC každého záznamu (EntryInvalid, CheckpointMismatch).
  • Kotvy: nedostupná (AnchorUnreachable), neplatný MAC či kľúč (AnchorInvalid), napred pred databázou (AnchorAhead), iný root pri tom istom seq (AnchorMismatch). Ukotvené seq sa v databáze vyhľadá až pri porovnaní, takže kontrolný bod potvrdený počas dlhého overovania nespôsobí planý AnchorAhead.
  • Čakajúce záznamy: ich MAC, Backlog, ak sú záznamy staršie než ledger.backlog_warning_seconds stále neukotvené, a OrphanEntry pre záznam, ktorého checkpoint_id neukazuje na žiadny kontrolný bod.
  • Hlavy entít (s entities): každý model, ktorého posledný záznam nie je tombstone, musí stále existovať (EntityDeleted) so svojím riadkom pečate (SealMissing) v danej verzii (SealRolledBack).

Každé zistenie okrem Backlog a AnchorUnreachable je porušenie a spustí LedgerIntegrityViolated. Dôkazy v denníku podpísané kľúčom, ktorý bol neskôr vyradený, sa stále overia; odvolané, čakajúce a neznáme kľúče nikdy.

Viac pripojení

Pečate, denník a kontrolné body žijú na pripojení každého zapečateného modelu. Ak ich máte na viacerých pripojeniach, spustite migrácie 0002–0004 na každom a uveďte ich:

'ledger' => ['connections' => [null, 'tenant_archive']],

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.