From 61a94da4fc7152f22e683f035b5f161c236c37c8 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Mon, 27 Jul 2026 18:55:10 -0400 Subject: [PATCH] fix(iam): reconcile the remaining substrate divergences from the mgmt copy Review of the DenySelfMutation port found the header's 'reconciled' claim was not yet true: mgmt Phase A also added the CloudWatch Logs metric-filter actions (afterhours-shift-manager creates an AWS::Logs::MetricFilter through this role), and without them a migrating SAM stack fails mid-deploy with AccessDenied. Ports those three actions and corrects two stale header notes. Every IAM statement in the three shared resources is now byte-identical across both files, verified programmatically; the only delta left is the DependsOn ordering line. --- .../deploy-substrate.template.yaml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/deploy-substrate/deploy-substrate.template.yaml b/lib/deploy-substrate/deploy-substrate.template.yaml index 29f48d2..ce16245 100644 --- a/lib/deploy-substrate/deploy-substrate.template.yaml +++ b/lib/deploy-substrate/deploy-substrate.template.yaml @@ -30,16 +30,21 @@ Description: >- # first deploy failed with ServiceLimitExceeded (2026-07-27). Effective # permissions are unchanged — verified by comparing the full 27-statement # set before and after the move (identical), since identity policies are -# unioned and an explicit Deny still wins. NOTE for the mgmt remediation: -# mgmt needs this same restructure before its Deny statements can be added, +# unioned and an explicit Deny still wins. mgmt received this same +# restructure in Phase B (.github PR #98), so this is no longer a +# divergence, # - SECURITY FIX (now in BOTH copies): iam:DeleteRolePermissionsBoundary # removed from Sid IAMPutPermissionsBoundary and explicit Deny statements # (DenyBoundaryTampering / DenyBoundaryPolicyEdit / DenySelfMutation) # added. The mgmt copy was remediated 2026-07-27 (.github PRs #95 Phase A # + #98 Phase B); DenySelfMutation and the widened policy/seahaven-* # DenyBoundaryPolicyEdit scope were then ported back here, so the two -# copies' statement sets are reconciled as of that date. If a substrate -# statement changes again, change BOTH files in the same piece of work. +# copies' statement sets are reconciled as of that date — every IAM +# statement in LambdaExecutionBoundary, SamCfnIamManagementPolicy and +# SamCfnExecutionRole is byte-identical across the two files; the only +# remaining delta is the DependsOn line above, which is ordering, not +# permission. If a substrate statement changes again, change BOTH files +# in the same piece of work. # # This template is deployed via lib/deploy-substrate-stack.ts # (cloudformation-include) as stack seahaven-deploy-substrate, once per @@ -525,6 +530,12 @@ Resources: - logs:DescribeDestinations - logs:AssociateKmsKey - logs:DisassociateKmsKey + # Ported from the mgmt copy (Phase A): afterhours-shift-manager + # creates an AWS::Logs::MetricFilter through this role, so a + # SAM stack migrating here fails mid-deploy without these. + - logs:PutMetricFilter + - logs:DeleteMetricFilter + - logs:DescribeMetricFilters Resource: "*" # ── EventBridge / CloudWatch Events (scheduled Lambdas) ───────────