Rekor Checkpoint Sync Configuration and Operations
Audience: Operators configuring offline/air-gapped attestation verification in Stella Ops.
This guide covers the configuration and operational procedures for the Rekor periodic checkpoint synchronization service, which maintains a local mirror of transparency-log checkpoints and tiles. For the submission/retry side of the Attestor’s Rekor integration, see the companion Rekor Submission & Retry Policy.
Implementation status (verified against source 2026-05-30). The sync engine (
RekorSyncBackgroundService), checkpoint store (PostgresRekorCheckpointStore), and tile cache (FileSystemRekorTileCache) are implemented insrc/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core/Rekor/(plus…/StellaOps.Attestor.Storage/Rekor/). However, as of this writing the background service is not yet registered as a hosted service and its options (RekorSyncOptions,PostgresCheckpointStoreOptions,FileSystemTileCacheOptions) are not yet bound to any configuration section inAttestorWebServiceComposition. The configuration tree shown below documents the option records as they exist in code; the binding/wiring is roadmap work. Likewise, the onlystella attestor …CLI surface that currently exists is the external transparency mirror group (stella attestor transparency …, see CLI reference) — thecheckpoint-store/sync/tiles/export/importcommands referenced in older drafts of this guide are NOT IMPLEMENTED. Sections that describe unimplemented surfaces are flagged inline.
Overview
The Rekor sync service maintains a local mirror of Rekor transparency log checkpoints and tiles. This enables:
- Offline verification: Verify attestations without network access to Sigstore
- Air-gapped operation: Run in environments without internet connectivity
- Performance: Reduce latency by using local checkpoint data
- Auditability: Maintain local evidence of log state at verification time
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ RekorSyncBackgroundService │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Checkpoint │ │ Signature │ │ Tile │ │
│ │ Fetcher │────▶│ Verifier │────▶│ Syncer │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ HTTP Tile │ │ Checkpoint │ │ Tile │
│ Client │ │ Store │ │ Cache │
└──────────────┘ │ (PostgreSQL) │ │(File System) │
│ └──────────────┘ └──────────────┘
▼
┌──────────────┐
│ Rekor │
│ Server │
└──────────────┘
Configuration
Draft / not yet wired. The option records below exist in code, but no
Configure<…>(GetSection(…))binding currently exists for them. Section names and binding semantics are therefore provisional — the keys are derived from the C# property names (.NET configuration binds case-insensitively), but the root section path is not fixed by code yet. Treat this as the target shape, not a working configuration.
Basic Configuration (RekorSyncOptions)
Source: RekorSyncOptions in src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core/Rekor/RekorSyncBackgroundService.cs.
# Provisional section path — not yet bound in AttestorWebServiceComposition.
rekorSync:
# Enable or disable sync service. Default: true.
enabled: true
# Interval between sync cycles (TimeSpan). Default: 00:05:00 (5 minutes).
syncInterval: "00:05:00"
# Delay before first sync after startup (TimeSpan). Default: 00:00:30 (30 seconds).
initialDelay: "00:00:30"
# Sync tiles in addition to checkpoints, for full offline support. Default: true.
enableTileSync: true
# Maximum number of tiles to fetch per sync cycle. Default: 100.
maxTilesPerSync: 100
# Rekor backends to sync (RekorBackend). Defaults to a single sigstore-prod entry.
backends:
- name: sigstore-prod # required
url: "https://rekor.sigstore.dev" # required (absolute URI)
tileBaseUrl: "https://rekor.sigstore.dev/api/v1/log/tiles"
# version: Auto | V2 (default Auto, which selects v2 tiles)
# logId: "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
# publicKey: <byte[]> (PEM/SPKI bytes; if omitted, checkpoint signatures are NOT verified)
# proofTimeout: "00:00:15" (TimeSpan; default 15s — inclusion-proof fetch timeout)
# pollInterval: "00:00:00.250" (TimeSpan; default 250ms — proof poll cadence)
# maxAttempts: 60 (int; default 60 — proof poll attempts)
Field-name note. A backend is identified by
nameandurl— there are noid,origin,baseUrl, orpublicKeyPathfields onRekorBackend. The full property set onRekorBackend(source:RekorBackend.cs) is:Name,Url,Version,TileBaseUrl,LogId,ProofTimeout(default 15s),PollInterval(default 250ms),MaxAttempts(default 60), andPublicKey. The logoriginis read from each fetched checkpoint (RekorTileCheckpoint.Origin), not from backend configuration. The trusted log key is supplied as in-memory bytes viaPublicKey(no file-path option exists in code today).ProofTimeout/PollInterval/MaxAttemptsgovern inclusion-proof fetching and are not consumed by the checkpoint/tile sync loop.
Checkpoint Store Configuration (PostgresCheckpointStoreOptions)
Source: PostgresCheckpointStoreOptions in src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Storage/Rekor/PostgresRekorCheckpointStore.cs.
checkpointStore:
connectionString: "Host=localhost;Database=stella;Username=stella;Password=secret" # required
schema: attestor # default: "attestor"
autoInitializeSchema: true # default: true
Checkpoints are stored in attestor.rekor_checkpoints with a unique (origin, tree_size) constraint; re-fetching the same (origin, tree_size) updates fetched_at / verified / verified_at via ON CONFLICT … DO UPDATE.
Schema-creation correction (verified against source 2026-05-30). A source comment in
PostgresRekorCheckpointStore.csclaims the table is “handled by the central migration runner (AttestorMigrationModulePlugin)”, but that is not accurate:AttestorMigrationModulePlugin(src/Platform/__Libraries/StellaOps.Platform.Database/MigrationModulePlugins.cs) manages theproofchainschema, and theAddStartupMigrations(schemaName: "attestor", …)runner only applies the nine embedded SQL files underStellaOps.Attestor.Persistence/Migrations/(the_archived/**subtree is excluded by the.csprojglob). Those files cover the verdict ledger, the consolidated001_initial_schemaproofchain/queue bootstrap, the predicate-type registry, the artifact-canonical-record materialized view, the deprecated-audit-log drop, runtime entries/watchlist, and the local-transparency-entries/external-transparency-sync tables — and span both theproofchainandattestorschemas — but none of them createsrekor_checkpoints. No migration anywhere insrc/creates this table. The only code path that createsattestor.rekor_checkpointsisPostgresRekorCheckpointStore.InitializeSchemaAsync(), which issues an idempotentCREATE TABLE IF NOT EXISTS(plus the two indexes shown below) whenAutoInitializeSchemaistrue. Because the store is not yet registered/called by a running service (see the status note at the top of this guide), even that path is not exercised today — the table must be created out of band until the wiring lands.
Tile Cache Configuration (FileSystemTileCacheOptions)
Source: FileSystemTileCacheOptions in src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core/Rekor/FileSystemRekorTileCache.cs.
tileCache:
# Base directory for tile storage.
# Default: <LocalApplicationData>/StellaOps/RekorTiles
basePath: /var/lib/stella/attestor/tiles
# Maximum cache size in bytes (0 = unlimited). Default: 0.
# NOTE: persisted as an option but NOT currently enforced by the file-system cache.
maxCacheSizeBytes: 10737418240 # 10 GB
# Auto-prune duration (TimeSpan, optional/nullable). Default: unset.
# NOTE: the cache exposes PruneAsync(...) but does not auto-schedule it from this value today.
autoPruneAfter: "30.00:00:00" # 30 days
Tiles are laid out on disk as {basePath}/{sanitized-origin}/{level}/{index}.tile with a sibling {index}.meta.json. Standard tile width is 256 hashes (32 bytes each); tiles narrower than 256 hashes are recorded as partial.
Operational Behaviour
The sync service runs as a hosted BackgroundService (once registered). Its loop, implemented in RekorSyncBackgroundService.ExecuteAsync, is:
- If
Enabledisfalse, log and return without doing anything. - Wait
InitialDelay, then enter the sync loop. - Each cycle iterates every configured backend (
SyncAllBackendsAsync); a failure in one backend is logged as a warning and does not abort the cycle. - For each backend (
SyncBackendAsync):- Fetch the latest checkpoint via
IRekorTileClient.GetCheckpointAsync. If none is available, log a warning and skip. - Verify the checkpoint signature via
IRekorCheckpointVerifier.VerifyCheckpointAsync. On failure, log an error and do not store the checkpoint. - If an
IRekorConsistencySyncCoordinatoris wired, run an online consistency cycle (G9-REK-02). If the verdict is not healthy (suspected fork/truncation), refuse to store so the consumer-facing “last good” pin does not advance. - Store the checkpoint via
IRekorCheckpointStore.StoreCheckpointAsync(idempotent on(origin, tree_size)). - If
EnableTileSyncistrue, perform incremental tile sync (SyncTilesAsync): compute the new-entry range from the previously stored checkpoint’s tree size, ask the cache for missing tiles, and fetch up toMaxTilesPerSyncof them per cycle.
- Fetch the latest checkpoint via
- Sleep
SyncIntervaland repeat until cancellation.
There is no built-in “full” or “initial” sync mode and no per-cycle forced-resync switch — the loop always performs an incremental tile fetch bounded by MaxTilesPerSync, catching up over successive cycles. Backfill therefore happens implicitly across multiple cycles rather than via a one-shot --full flag.
CLI commands — NOT IMPLEMENTED
The following commands appeared in earlier drafts of this guide but do not exist in the
stellaCLI today. There is nocheckpoint-store,backend,sync,sync-status,checkpoints,tiles,export,import, orconfig validatesubcommand understella attestorfor the checkpoint/tile sync engine:stella attestor checkpoint-store init # NOT IMPLEMENTED stella attestor backend add … # NOT IMPLEMENTED stella attestor sync … # NOT IMPLEMENTED (see transparency sync below) stella attestor sync-status # NOT IMPLEMENTED stella attestor checkpoints list|prune|verify # NOT IMPLEMENTED stella attestor tiles stats|prune|clear # NOT IMPLEMENTED stella attestor export / import # NOT IMPLEMENTED (see transparency exchange below) stella attestor config validate # NOT IMPLEMENTEDOperationally, the checkpoint/tile sync engine is driven by the background service and its configuration, not by interactive CLI commands. Checkpoint history is inspected directly in PostgreSQL (
attestor.rekor_checkpoints); tile-cache contents are inspected on disk under the configuredbasePath.One nuance on export/import: a
rekor checkpoint export|import|statuscommand group is implemented inCheckpointCommands.csbut is not registered inCommandFactory.cs, so it is unreachable from the shipped CLI (see Export checkpoints for air-gap under Maintenance Tasks). It is therefore effectively unavailable, even though the C# code exists.
CLI reference: stella attestor transparency
The CLI surface that does exist under stella attestor is the external transparency mirror group (source: src/Cli/StellaOps.Cli/Commands/AttestorTransparencyCommandGroup.cs). This governs mirroring local attestations to external transparency logs — it is related to, but distinct from, the local checkpoint/tile sync described above.
stella attestor transparency targets list [--enabled <bool>] [--json]
stella attestor transparency targets show <target> [--json]
stella attestor transparency targets upsert --name … --required-crypto-profile … --operator-label … [--kind …] [--endpoint-url …] [--trust-root-ref …] [--auth-ref …] [--metadata-json …] [--disabled] [--json]
stella attestor transparency targets enable|disable <target> [--json]
stella attestor transparency sync run --target <name|id> … [--live] [--confirm-egress-window] [--dry-run] [--max-entries N] [--max-runtime-seconds N] [--stop-on-first-hard-error] [--operator-label …] [--json]
stella attestor transparency sync report [--target …] [--batch-id <guid>] [--operator-label …] [--limit N] [--json]
stella attestor transparency receipts list [filters…] [--json]
stella attestor transparency receipts show <uuid> [--refresh] [--json]
stella attestor transparency exchange schedule create …
stella attestor transparency exchange relay-import create …
stella attestor transparency exchange import validate|apply …
stella attestor transparency exchange status …
Notes:
transparency sync rundefaults to a safe dry-run (--dry-rundefaults true and is overridden only by--live); a live connected sync requires both--liveand--confirm-egress-window, and is refused when the CLI is in offline/sealed mode.--auth-refmust be a secret reference (secret:,vault:,authref:,stellaops-secret:,urn:stellaops:secret:); raw credential material is rejected by the CLI’sLooksLikeRawSecretguard and again by the API.- Server-side enable gate. The backing
POST /api/v1/transparency/external-sync:runendpoint returns a 409 “External transparency sync is disabled” problem (code=external_transparency_sync_disabled) whenattestor:transparency:externalSync:enabledis nottrue(AttestorWebServiceEndpoints.cs). ThatEnabledflag is the only condition the endpoint actually checks before running; the problemdetailalso advises configuring enabled external targets, but having at least one enabled target is guidance, not a separately enforced gate at this endpoint (a sync with no enabled targets simply does no work rather than 409-ing). The backgroundTransparencySyncWorkeris registered only when bothTransparency.ExternalSync.Enabledand.WorkerEnabledare true (AttestorWebServiceComposition). - Required scopes (source:
AttestorWebServiceEndpoints.csRequireAuthorization(...)+AttestorWebServiceComposition.cspolicy registration). The endpoints declare ASP.NET policy names in colon form (attestor:read,attestor:write), but the actual scope-claim values a token must carry are dot-form:attestor.read,attestor.write,attestor.verify. Read-only commands —targets list/show,sync report,receipts list/show— map to theattestor:readpolicy, satisfied by any ofattestor.read,attestor.verify, orattestor.write. Mutating/egress commands —targets upsert/enable/disable,sync run, and allexchangeschedule/relay-import/import commands — map to theattestor:writepolicy, satisfied only byattestor.write(or an in-cluster Attestor service bypass). Note theseattestor.*dot-form values are service-local string literals inAttestorWebServiceComposition.cs(HasAnyScope(context.User, "attestor.write"), etc.) — they are not declared as constants in the canonical scope catalog (StellaOpsScopes.cs), which instead definesattest:createandattest:admin(governing attestation create/admin rather than this transparency mirror surface).
Metrics
The sync service emits four OpenTelemetry instruments from the StellaOps.Attestor.RekorSync meter (source: RekorSyncBackgroundService.cs). All instrument names use dots; the names below are the raw OTel instrument names. The Prometheus exporter conventionally replaces dots with underscores and appends _total to monotonic counters, so the exported series names are shown in the comments. All series are tagged with origin (the log origin from the checkpoint), not backend.
# Counter (long): checkpoints fetched from remote.
# Prometheus: attestor_rekor_sync_checkpoints_fetched_total{origin="rekor.sigstore.dev"}
attestor.rekor_sync_checkpoints_fetched
# Counter (long): tiles fetched from remote.
# Prometheus: attestor_rekor_sync_tiles_fetched_total{origin="rekor.sigstore.dev"}
attestor.rekor_sync_tiles_fetched
# Histogram (double, unit "s"): age of the latest synced checkpoint at sync time.
# Prometheus: attestor_rekor_sync_checkpoint_age_seconds_bucket/_sum/_count{origin="rekor.sigstore.dev"}
attestor.rekor_sync_checkpoint_age_seconds
# Observable gauge (long): number of tiles currently cached (last observed value).
# Prometheus: attestor_rekor_sync_tiles_cached{origin="rekor.sigstore.dev"}
attestor.rekor_sync_tiles_cached
Removed/never-existed metrics. Earlier drafts listed
attestor_rekor_sync_checkpoints_stored_total,attestor_rekor_sync_tiles_cached_total,attestor_rekor_sync_last_success_seconds, andattestor_rekor_sync_errors_total. None of these instruments exist in code. There is no “checkpoints stored” counter (storage is logged, not metered), no “time since last successful sync” gauge, and no sync-error counter on the sync meter.
Divergence-detection metrics (separate meter)
Checkpoint divergence/anomaly detection (CheckpointDivergenceDetector) emits from a different meter, StellaOps.Attestor.Divergence. These are already-_total counters in code:
attestor.rekor_checkpoint_mismatch_total{origin,backend}
attestor.rekor_checkpoint_rollback_detected_total{origin}
attestor.rekor_cross_log_divergence_total{primary,mirror}
attestor.rekor_anomalies_detected_total{origin}
Alerting Recommendations
Because there is no last_success_seconds gauge or errors_total counter, build freshness alerting on the checkpoint-age histogram and lack of fetch progress instead.
groups:
- name: attestor-rekor-sync
rules:
# Latest synced checkpoint is aging — derive from the age histogram.
- alert: RekorCheckpointAgeHigh
expr: histogram_quantile(0.95, rate(attestor_rekor_sync_checkpoint_age_seconds_bucket[15m])) > 900
for: 5m
labels:
severity: warning
annotations:
summary: Rekor checkpoint age is high
description: "p95 checkpoint age > 900s for {{ $labels.origin }}"
# No checkpoints fetched in the last 15m — sync may be stalled.
- alert: RekorSyncStalled
expr: increase(attestor_rekor_sync_checkpoints_fetched_total[15m]) == 0
for: 10m
labels:
severity: warning
annotations:
summary: Rekor sync appears stalled
description: "No checkpoints fetched for {{ $labels.origin }} in 15m"
# Integrity anomalies — wire to the divergence meter.
- alert: RekorCheckpointDivergence
expr: increase(attestor_rekor_checkpoint_mismatch_total[5m]) > 0
or increase(attestor_rekor_checkpoint_rollback_detected_total[5m]) > 0
labels:
severity: critical
annotations:
summary: Rekor checkpoint divergence/rollback detected
description: "Integrity anomaly for {{ $labels.origin }} — see checkpoint-divergence-runbook.md"
Maintenance Tasks
No CLI/scheduler surface today. Pruning is exposed only as code-level APIs; there are no
stella attestor checkpoints prune,tiles prune,checkpoints verify, orexportcommands, and the background service does not auto-schedule pruning.
Prune old checkpoints — code API: IRekorCheckpointStore.PruneOldCheckpointsAsync(olderThan, keepLatestPerOrigin = true). Deletes checkpoint rows older than the cutoff; with keepLatestPerOrigin = true (default) it always retains the newest checkpoint per origin. To prune manually in the absence of a CLI, delete from attestor.rekor_checkpoints by fetched_at.
Prune old tiles — code API: IRekorTileCache.PruneAsync(origin, olderThan). Deletes .tile files (and their .meta.json siblings) whose file creation time is older than the cutoff, scoped to one origin or all origins. The FileSystemTileCacheOptions.AutoPruneAfter value is stored but not auto-applied by the cache; pruning must be invoked explicitly.
Verify checkpoint store integrity — there is no dedicated verify command. Signature verification happens at sync time (IRekorCheckpointVerifier); divergence and rollback detection is handled by CheckpointDivergenceDetector (see the divergence runbook).
Export checkpoints for air-gap — there is no reachable CLI for native checkpoint bundle export/import. A rekor checkpoint export|import|status command group does exist in code (src/Cli/StellaOps.Cli/Commands/CheckpointCommands.cs: BuildCheckpointCommand, with export --instance --output [--include-tiles --tile-count], import --input [--verify-signature --force], and status [--output table|json]), but BuildCheckpointCommand is never registered in CommandFactory.cs, so it is unreachable from the stella CLI today — treat it as roadmap/dead code, not a usable surface. For external transparency mirroring, use the stella attestor transparency exchange commands (see the CLI reference); for general offline distribution see the Offline Kit documentation under docs/modules/airgap/ and docs/modules/scanner/operations/offline-kit-assembly.md.
Troubleshooting
Sync Not Running
Confirm the service is actually wired. The most common reason for “no sync” today is that
RekorSyncBackgroundServiceis not yet registered as a hosted service andRekorSyncOptionsis not yet bound to configuration (see the status note at the top of this guide). Until that wiring lands, the loop never starts regardless of configuration.Check service logs (the loop logs “Rekor sync service started …” on start, or “Rekor sync service is disabled” when
Enabledisfalse):journalctl -u stella-attestor -fCheck database connectivity directly (there is no
checkpoint-store testcommand):psql -h localhost -U stella -d stella -c "SELECT count(*) FROM attestor.rekor_checkpoints"
Signature Verification Failing
When IRekorCheckpointVerifier.VerifyCheckpointAsync returns invalid, the service logs Checkpoint signature verification failed for {Origin} at error level and skips storing the checkpoint.
Verify the configured trusted key. The log key is supplied as
RekorBackend.PublicKeybytes (noverify-keycommand exists). IfPublicKeyis omitted, checkpoint signatures are not verified at all.Check for key rotation:
- Monitor Sigstore announcements.
- Update
PublicKey(andLogIdif applicable) if the upstream log key rotated.
Compare with a direct fetch (only when not in offline/sealed mode; web access is user-initiated per the offline-first policy):
curl -s https://rekor.sigstore.dev/api/v1/log | jq
Tile Cache Issues
Check disk space:
df -h /var/lib/stella/attestor/tilesVerify permissions:
ls -la /var/lib/stella/attestor/tilesClear and resync. There is no
stella attestor tiles clearorstella attestor sync --full-tilescommand (see CLI commands — NOT IMPLEMENTED). To clear the cache, delete the on-disk tiles for an origin (or the whole tree) under the configuredbasePath; the next background sync cycle re-fetches the missing tiles incrementally (bounded bymaxTilesPerSync) once the sync service is wired:# Remove cached tiles for one origin (sanitized-origin subdir under basePath)… rm -rf /var/lib/stella/attestor/tiles/<sanitized-origin>/ # …or clear all origins: rm -rf /var/lib/stella/attestor/tiles/*
Database Issues
Check PostgreSQL connectivity:
psql -h localhost -U stella -d stella -c "SELECT 1"Verify schema/columns exist (the table schema is:
checkpoint_id UUID PK, origin TEXT, tree_size BIGINT, root_hash BYTEA, raw_checkpoint TEXT, signature BYTEA, fetched_at TIMESTAMPTZ, verified BOOLEAN, verified_at TIMESTAMPTZ, withUNIQUE(origin, tree_size)):SELECT origin, tree_size, verified, fetched_at FROM attestor.rekor_checkpoints ORDER BY fetched_at DESC LIMIT 1;Schema creation is not owned by a migration. Despite a misleading source comment,
AttestorMigrationModulePluginmanages theproofchainschema and theattestor-schema migration runner does not createrekor_checkpoints(see the schema-creation correction under Checkpoint Store Configuration above). The only code that creates the table isPostgresRekorCheckpointStore.InitializeSchemaAsync(idempotentCREATE TABLE IF NOT EXISTSwhenAutoInitializeSchemaistrue), and that store is not yet wired into a running service. There is nocheckpoint-store init --forcecommand. Until the background service/store are registered, create the table out of band with the DDL listed in step 2 above.
Air-Gap Operations
No reachable CLI for checkpoint/tile bundle export/import. The
stella attestor …commands shown in older drafts (stella attestor sync --full-tiles,stella attestor export,stella attestor import,stella attestor sync-status) do not exist under theattestornamespace. A separaterekor checkpoint export|import|statusgroup is coded inCheckpointCommands.csbut is not registered inCommandFactory.cs, so it cannot be invoked from the shipped CLI (see Maintenance Tasks). For now, treat checkpoint/tile bundle export/import as unavailable.
For air-gapped transparency operations, use the implemented external-transparency controlled-media exchange flow instead (source: AttestorTransparencyCommandGroup):
On the connected/sealed site, create a schedule package:
stella attestor transparency exchange schedule create \ --target <name|id> --out ./pkg --media-id <id> --operator-label <label>On a connected relay, build the import package from the schedule package:
stella attestor transparency exchange relay-import create \ --schedule ./pkg --out ./import-pkg --relay-id <id> --operator-label <label>Validate and apply the returned import package on the sealed site:
stella attestor transparency exchange import validate --package ./import-pkg stella attestor transparency exchange import apply --package ./import-pkg --operator-label <label>Inspect exchange/sync status:
stella attestor transparency exchange status --schedule-id <guid> stella attestor transparency sync report --target <name|id>
For populating local checkpoint/tile state in an air-gapped install, the engine relies on the configured tile cache (basePath) being pre-seeded out of band, since no first-class export/import tool exists yet. See the Offline Kit documentation under docs/modules/airgap/ and docs/modules/scanner/operations/offline-kit-assembly.md for distribution mechanics.
See Also
- Rekor Submission & Retry Policy — durable submission queue, dead-lettering, and metrics (the companion to this sync guide)
- Rekor Verification Design
- Checkpoint Divergence Detection
- Offline Kit Assembly and the air-gap module docs
- Sigstore Rekor Documentation
