Repository navigation
feat(disruption): executor Lambda entry + CDK construct — Phase B deployable (ADR-031) [#1419] - #1645
susumutomita wants to merge 3 commits into
Conversation
…mposes [#1419] Integration fix surfaced while wiring the handler entry: ExecutorDeps.scheduleRevert omitted `detail`, but the concrete scheduleRevert (#1642) needs it to build the idempotent schedule name (EXEC# twin = requestId/teamId) and the revert invocation payload. The dep is built once at module load, so detail must arrive at call time — executeDisruptionAction now passes it: scheduleRevert(detail, revert, target, afterSeconds). Without this the inject-time orchestration and the revert scheduler did not type-compose in the real wiring. execute.test.ts updated to assert detail is forwarded. Relates #1419 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…DRY) [#1419] The cross-account AssumeRole-into-CompetitorDeployRole logic (with the #856/#1245 rotation-race ExternalId-mismatch retry + grace-fallback trace) lived inline in describe-stack-handler and was near-duplicated in competitor-accounts/verify.ts + participant SSO. Extract the canonical implementation to handlers/shared/assume-competitor-role.ts so credential-path code has a single audited home (consolidating security-critical auth = a security improvement, not just dedup) and the upcoming disruption executor (#1419) can reuse it instead of copying it. Behavior-preserving: only caller-cosmetic bits are parameterized — `sessionNamePrefix` (RoleSessionName) and `graceFallbackTraceEvent` (the operator alarm key). describe-stack passes its exact prior values, so its trace event name and session name are byte-identical. Verified by describe-stack's existing 20 tests (incl. the grace-fallback trace-name pin + retry/rethrow cases) passing UNCHANGED, plus 9 new direct tests of the shared module (undefined/one-sided/ no-value/happy session-name/incomplete-creds/grace-fallback-fires-trace/ non-AccessDenied-rethrow/no-previous-version-rethrow + the retry predicate). verify.ts / SSO keep their own variants for now (different deps/return shape) — noted as a follow-up; this PR extracts the describe-stack path that the executor reuses. Infra suite 2377 pass. Relates #1419 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…loyable [#1419] The #1419 capstone: wires the tested executor modules into a deployable Lambda and its CDK construct. With this, ADR-031 Phase B is code-complete (modulo make deploy + a target-account E2E). - handlers/disruption-executor-handler/index.ts: real-deps entry (DI composition root, like describe-stack-handler/index.ts). Constructs the SDK clients + the shared assumeCompetitorRole, wires claimExecution/resolveDeployment/sendDispatch/ scheduleRevert, exports the Lambda handler over routeDisruptionInvocation. The SDK imports are baselined as a composition root (parity with describe-stack / generic-scoring entries). - disruption-executor-lambda.ts: the construct. NodejsFunction + an EventBridge rule on tenkacloud.disruptions + a scheduler execution role. Least-privilege IAM: sts:AssumeRole only on TenkaCloud-* (not *), ssm:GetParameter + kms:Decrypt only for the tenant ExternalId (describe-stack pattern), dynamodb Query (GSI1) + PutItem (EXEC#), scheduler:CreateSchedule + scoped iam:PassRole. The destructive SendCommand/Invoke/UpdateStack are NOT on the executor's own role — they ride the assumed CompetitorDeployRole — pinned by a Template assertion test. - wired into ProblemDeployBackendStack; the EventBridge-rule-count test goes 7→8. - carries the execute.ts compose fix + the shared assumeCompetitorRole extraction (from #1640 / #1644) so the stack composes; they dedupe when those merge. Verified: 4 Template assertion tests (Lambda+env / sts scope / no-destructive-own-IAM / rule+scheduler-role); full infra suite 2442 pass; tsc / biome / make harness (0 errors) / check-no-conflicts / cdk synth (exit 0) all green. Relates #1419 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 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❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## feat/1419-executor-route #1645 +/- ##
=========================================================
Coverage 93.39% 93.39%
=========================================================
Files 397 399 +2
Lines 10867 10885 +18
Branches 3335 3337 +2
=========================================================
+ Hits 10149 10166 +17
Misses 222 222
- Partials 496 497 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Summary
The #1419 capstone: wires the tested executor modules into a deployable Lambda + its CDK construct. With this, ADR-031 Phase B is code-complete — the only thing left is
make deploy+ a target-account E2E (yours).What it adds
handlers/disruption-executor-handler/index.ts— the real-deps entry (DI composition root, exactly likedescribe-stack-handler/index.ts). Constructs the SDK clients + the sharedassumeCompetitorRole, wiresclaimExecution/resolveDeployment/sendDispatch/scheduleRevert, and exports the LambdahandleroverrouteDisruptionInvocation. (SDK imports baselined as a composition root, parity with the describe-stack / generic-scoring entries.)disruption-executor-lambda.ts— the construct:NodejsFunction+ an EventBridge rule ontenkacloud.disruptions+ a scheduler execution role. Least-privilege IAM:sts:AssumeRoleonly onarn:aws:iam::*:role/TenkaCloud-*(not*),ssm:GetParameter+kms:Decryptonly for the tenant ExternalId (describe-stack pattern),dynamodb:Query(GSI1) +dynamodb:PutItem(EXEC#),scheduler:CreateSchedule+ scopediam:PassRole.SendCommand/Invoke/UpdateStackare not on the executor's own role — they ride the assumedCompetitorDeployRole— pinned by a Template assertion test.ProblemDeployBackendStack; the EventBridge-rule-count test goes 7→8.Security shape
The executor's own IAM is minimal and Template-asserted; the destructive power is the pre-existing competitor-account
CompetitorDeployRole(AdministratorAccess, consented at bootstrap), gated by operator-authenticated fire → problem-authoraction(validated by #1639/#32) → ExternalId-scoped AssumeRole → ADR-029-INV-2 auto-revert. No new IAM danger beyond the describe-stack cross-account pattern.Test plan
sts:AssumeRolescoped toTenkaCloud-*; the executor's own role has no SendCommand/Invoke/UpdateStack; thetenkacloud.disruptionsrule + the scheduler-assumable revert role.tsc --noEmit, biome,make harness(0 errors),check-no-conflicts,cdk synthexit 0 (the construct synthesizes in the real stack): all green.Regression analysis
action-less disruptions stay Phase A audit-only (the executor returnsno_action), so existing disruption behavior is unchanged.ProblemDeployBackendStack.cdk synthconfirms the rest of the template is unchanged.scheduleRevert(detail, …)) corrects a real defect where the orchestration dep didn't type-compose with the concrete scheduler — now verified end-to-end by the wiring + tsc.assumeCompetitorRoleis behavior-preserving (describe-stack's 20 tests unchanged, from refactor(problem-deploy): extract shared assumeCompetitorRole (SOLID/DRY) [#1419] #1644).Physical impact
CFn: CREATE — one new
AWS::Lambda::Function(the executor), oneAWS::Events::Rule(tenkacloud.disruptions→ executor), twoAWS::IAM::Roles (the executor's least-privilege role + the scheduler execution role) inProblemDeployBackendStack. No table/capacity change (DynamoDbLowCapacity unaffected). NO-OP on all other stacks. The fault-injection path is inert until a problem declares anactionand an operator fires it.Relates #1419