Skip to content

Design: reset and replay from the CloudTrail log - #54

Merged
alsmola merged 5 commits into
mainfrom
design/cloudtrail-replay
Jul 26, 2026
Merged

Design: reset and replay from the CloudTrail log#54
alsmola merged 5 commits into
mainfrom
design/cloudtrail-replay

Conversation

@alsmola

@alsmola alsmola commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Design doc for #49.

Frames CloudTrail as the transaction log and TrailTool's DynamoDB tables as a derived, disposable projection.

Treats CloudTrail as the transaction log and TrailTool's DynamoDB
tables as a derived, disposable projection. Two primitives: replay
(re-ingest historical S3 objects through the existing Lambda path)
and reset (drop the projection so it can be rebuilt cleanly).

Part of #49

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the scripts/ fallback; reset and replay ship as trailtool reset
and trailtool replay, with a combined --reset rebuild path.

Part of #49

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removes overstated safety claims and scopes v1 to a correct offline
rebuild:

- The ingestor marker is a sequential-redelivery guard, not general
  idempotency (racy read-then-unconditional-write). Drop "idempotency
  comes for free"; overlap with live delivery is a non-goal needing an
  atomic claim (deferred).
- Replay is sequential. Cross-file attribution is order-sensitive and
  never repaired, so concurrency is deferred until aggregation is
  order-independent. No worker pool, no reorder window.
- Day-only ranges; no sub-day instants that would silently replay whole
  boundary days into the projection.
- No persistent resume cursor in v1 (the earlier one survived reset yet
  did not survive a kill). A generation-bound checkpoint is a follow-up.
- Reset is explicitly offline; cross-table truncation is not atomic. An
  ingestion fence is the principled fix (deferred). --yes skips the
  count query.
- Note that raw-key order is chronological only within one
  account/region prefix.

Part of #49

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alsmola

alsmola commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Amended after review. The doc now describes a correct offline-rebuild v1 rather than overstating what the reused Lambda path gives for free:

  • Idempotency is not free. The ingestor marker is a read-then-unconditional-write with warning-only error handling, so it guards sequential redelivery but not two invocations racing on the same object. §3 and §8 say this plainly; overlap with live delivery is now an explicit non-goal, with an atomic marker claim as the deferred prerequisite.
  • Replay is sequential. Cross-file attribution is order-sensitive and never repaired, so §6/§7 make sequential the correctness contract and defer concurrency until aggregation is order-independent.
  • Day-only ranges (§5), no sub-day instants that would replay whole boundary days into the projection.
  • No persistent cursor in v1 (§7); a generation-bound checkpoint that can't outlive a reset is a follow-up.
  • Reset is offline (§4): cross-table truncation isn't atomic; an ingestion fence is the principled fix (§11).
  • Raw-key order is chronological only within one account/region prefix.

The implementation PRs (#55, #56) are updated to match.

Rewrites the doc to lead with what gets built (two CLI commands) in
plain terms. The transaction-log/projection idea is now a single
line of inspiration, not the vocabulary.

- Removes the "why invoke the Lambda vs. re-ingest locally" section:
  it argued against an option no one proposed.
- Replaces the "offline rebuild / no overlap / atomic claim required"
  framing with the actual rule: replay past (closed) days, whose
  objects are disjoint from live delivery, so replay and live
  ingestion can run concurrently without double-counting.
- Reset simply asks that live delivery be quiet (infrequent, deliberate
  action); drops the labored cross-table-atomicity argument.

Part of #49

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alsmola

alsmola commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Simplified the framing:

  • Cut the "why invoke the Lambda vs. re-ingest locally" section entirely — it defended against an option no one proposed.
  • Replaced the "offline / no-overlap / atomic-claim-required" story with the actual rule: replay closed (past) days. Their objects are disjoint from what live delivery writes to today's prefix, so replay and live ingestion can run concurrently without double-counting. The atomic marker claim moves to a follow-up (only needed to replay the current day, which is out of scope).
  • Reset just asks that live delivery be quiet — it's an infrequent, deliberate action, so no elaborate cross-table-atomicity machinery.
  • Leads with what gets built (two CLI commands) in plain terms; the transaction-log/projection idea is one line of inspiration, not the vocabulary.

Command help on #55 and #56 updated to match. Issue #49 rewritten in the same plain terms.

--bucket is optional; replay reads the bucket name from the ingestor
CloudFormation stack (CloudTrailBucketName output, parameter fallback)
rather than making the operator retype what the deployment knows.

Part of #49

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alsmola
alsmola merged commit 86b35cd into main Jul 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant