Repository navigation
feat(disruptions): immediate + scheduled (N分後) red-team fire [ADR-037] - #1687
Conversation
ユーザー要件「障害を即座に実行と、スケジュール実行両方できるように」を実装。 ADR-037 timing モデルの第一弾 (scheduled)。 機構 (新 infra ゼロ): - fire schema に timing(immediate|scheduled) + afterMinutes(1..1440) を追加 (cross-field refine) - fire handler は afterMinutes を published Detail に乗せ、 audit に scheduledFor を記録 - executor は afterMinutes>0 の時、 既存 aws-scheduler one-shot を転用して inject を T+N に 遅延予約 (mode:"inject")。 claim は fired-event 時に取得済 → 遅延 inject は再claim しない - executor の scheduler role / CreateSchedule 権限は revert 用に既存 → IAM 変更なし - operator UI に即座/N分後トグル + 分入力 (defaultAfterMinutes で pre-fill) リファクタ: fire modal を FireModal に抽出 (form state を内包、 panel を薄く保つ)。 ## Test plan - infra: disruption-execute / route / schedule-revert / fire / routes / contract = 全 green - app-admin: DisruptionsPanel 16 tests、 全 953 tests green、 coverage 100% 維持 - make harness green、 tsc green、 biome clean ## Regression analysis - immediate fire は従来と完全同一 (afterMinutes 未指定 → published Detail / audit 不変、 即注入)。 - executor: afterMinutes 無しの fired event は従来どおり即注入。 - 冪等性不変: claim は fired-event 時に取得 → EventBridge 再配送は遅延予約より前に弾く。 - always-ends (ADR-029): 各注入に revert 予約は不変。 ## Physical impact - UPDATE: DisruptionExecutor / EventApi Lambda の関数コード (bundled asset) のみ。 - NO-OP: CFn リソース構成 / IAM ポリシー / DynamoDB capacity に差分なし。 Relates #1417 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…DR-037]
/simplify (altitude) finding: the scheduled-fire deferred-inject path dropped the
immediate path's idempotency guarantee. The immediate path is safe because
claimExecution runs in the SAME invocation that injects (EventBridge redelivery →
duplicate → no double-inject). The deferred mode:"inject" path skipped the claim, but
aws-scheduler is ALSO at-least-once: a Lambda error after sendDispatch → scheduler
retry → double inject.
Fix (parity with the established mechanism): executeScheduledInject claims a distinct
inject-phase key (EXEC#{requestId}#{teamId}#INJECT) at injection time, so scheduler
redelivery is deduped exactly like the immediate path dedupes EventBridge redelivery.
The fire-time event-phase claim is unchanged.
## Test plan
- disruption-execute / route / executor-store: 85 disruption tests green, tsc green,
biome clean, make harness green
## Regression analysis
- Immediate path unchanged (event-phase claim). Deferred path now matches immediate
path's at-least-once posture; event/inject claims use distinct PKs (no interference).
## Physical impact
- UPDATE: DisruptionExecutor Lambda code only. NO-OP: CFn / IAM / DynamoDB capacity.
Relates #1417
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/review follow-up: the scheduled-fire injection time was stored (audit row scheduledFor) but not surfaced in the operator audit table — an operator could see a scheduled fire in history but not WHEN it lands. Add a "Scheduled for" column (ja/en); immediate fires render "-". ## Test plan - DisruptionsPanel: audit-rows test covers both a scheduled row (shows the time) and an immediate row (shows "-"). app-admin coverage 100% (953 tests), tsc + biome + harness green. ## Regression analysis - Display-only addition to the audit table. No API / data-shape change (scheduledFor was already on DisruptionAuditRow). Immediate fires unaffected (render "-"). ## Physical impact - NO-OP: frontend-only; no CFn / IAM / DynamoDB change. Relates #1417 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR implements ADR-037 scheduled disruption injection, enabling Red Team chaos fault injection to be deferred by a configurable delay. The feature spans request validation, fire handler persistence, executor routing with phase-aware idempotency, AWS Scheduler integration, and a frontend fire modal with timing selection UI. ChangesScheduled Disruption Injection
Sequence Diagram(s)See the diagram embedded in the hidden review stack artifact showing immediate vs scheduled injection flows through the executor Lambda and AWS Scheduler. Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1687 +/- ##
==========================================
+ Coverage 92.68% 92.71% +0.02%
==========================================
Files 431 431
Lines 11792 11834 +42
Branches 3620 3641 +21
==========================================
+ Hits 10930 10972 +42
Misses 295 295
Partials 567 567 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Summary
Implements the scheduled-fire slice of ADR-037: an operator can fire a red-team disruption immediately or scheduled N minutes later. First of the {scheduled, recurring, while-undefended} timing modes.
Depends on #1686 (ADR-037 design). Merge #1686 first — this branch references
[ADR-037]throughout and is the implementation of that ADR'sscheduledmode.Mechanism (zero new infra)
timing(immediate|scheduled) +afterMinutes(1–1440), with cross-field refines.afterMinutesinto the publishedDisruptionFireddetail and recordsscheduledForin the audit row.afterMinutes>0, reuses the existing aws-scheduler one-shot (the revert mechanism) to re-invoke itself with{mode:"inject", detail}at T+N. The executor's scheduler role +CreateSchedulealready exist for revert → no IAM/CDK change.SegmentedControl+ minutes input (pre-filled from the disruption'sdefaultAfterMinutes); the fire audit table gains a "Scheduled for" column.Idempotency (parity with the immediate path)
The immediate path is dedupe-safe because
claimExecutionruns in the same invocation that injects (EventBridge redelivery → duplicate). aws-scheduler is also at-least-once, so the deferred inject claims a distinct inject-phase key (EXEC#{requestId}#{teamId}#INJECT) at injection time → scheduler redelivery is fenced exactly like the immediate path.Test plan
disruption-execute / route / schedule-revert / executor-store / fire / routes / contract— 85 disruption tests green (defer, scheduled-inject, inject-phase claim + duplicate, parse guard, scheduledFor, distinct PK).DisruptionsPanel18 tests (timing toggle, out-of-range disable, default pre-fill, scheduledFor column shows time vs "-"); 953 tests, coverage 100%.make harnessgreen, tsc green, biome clean.Review trail
/review: approve (correct, conventions-clean, no security concerns; clean generalization of the scheduler mechanism)./security-review: no findings —afterMinutesdouble-validated + bounded; scheduler payload server-built; schedule-name sanitized; tenant ownership/ExternalId path unchanged./simplify: diff is de-duplicating (extractssendOneShot/oneShotAt/FireModal/teamPicker); altitude review found + fixed the inject-phase idempotency gap (commit 2).Regression analysis
afterMinutesabsent → published detail / audit unchanged → immediate inject. Regression-pinned ("immediate omits afterMinutes").afterMinutes-less fired events take the unchanged inject path; the newmode:"inject"route branch only matches the new scheduler payload.Physical impact
DisruptionExecutor+EventApiLambda function code (bundled assets); frontendapplication-admin-consolebundle.Relates #1417
Summary by CodeRabbit
Release Notes