seahaven-org-baseline/lib/deploy-substrate
Adam Moussa 32f06e74eb
refactor(iam): reduce boundary to the fleet-wide floor, defer per-workload scope
Adam's call after review: the security win of INFRA-186 comes from DELETING the
account-wide wildcards, not from enumerating replacements. Per-workload prefixes
add no security -- they only keep a workload functional -- and widening a
boundary is the safe direction (adding a resource never breaks a running Lambda;
only tightening does). So the per-workload scope moves to each migration PR,
which has the stack's real template open in front of it.

Removed all nine per-workload data-plane statements (DynamoDB, S3 x3, Secrets
Manager, SSM, SQS, Lambda invoke, SES, scheduler x2, KMS). Kept the fleet-wide
floor: CloudWatchLogsWrite (/aws/lambda*), CloudWatchLogsDescribe, XRay, Ec2Eni
-- the statements every Lambda needs regardless of workload, and also the
silent-failure classes, which is why they belong in the floor.

KMS dropped entirely: both accounts have ZERO CMK-encrypted log groups
(verified). A workload bringing a CMK adds the statement plus the matching
kms:ViaService principal in its own PR.

Why not keep the enumeration: it required predicting five stacks' needs from
this file's own permission-source comment block, and /sh-security-review found
SIX errors in the result -- three silent. The block is a secondary record, not
an authority. Deriving scope per-migration from the owning template removes the
whole error class.

Effect on the security objective: unchanged. secret:*, table/*, function:*,
sqs:* and the s3:::*-<acct> name-suffix filter are gone either way, so the
amplifier is closed identically.

Size: 5,457 chars / 16 statements -> 703 / 4. Headroom 687 -> 5,441, so the cap
stops being a forcing function. Header, SCOPING RULE and WIDENING PATH all
updated to match; widening path now leads with 'read the stack's own template',
names the silent-failure classes to check, and moves the version-budget check to
a precondition instead of a trailing step.

Verified unchanged: logical id and ManagedPolicyName, so all eight pinning
conditions across both guardrail policies still resolve. Both accounts synth
identically at 703 chars.
2026-07-30 19:07:09 -04:00
..
deploy-substrate.template.yaml refactor(iam): reduce boundary to the fleet-wide floor, defer per-workload scope 2026-07-30 19:07:09 -04:00