Shared seahaven-lambda-execution-boundary stays unchanged for live roles.
New named policies plus an enumerated StringEquals allow-list unblock the
next PLAT-71 widen without growing the 6144-character shared document.
Pre-grant delivery.logs write via MealOrderApiAccessLogResourcePolicy on
substrate so the HCP apply role cannot mutate account-wide log resource
policies.
* feat(iam): add hcptf roles and boundary widen for meal-order-manager
Append plan/apply OIDC roles for meal-order-manager-prod and widen the lambda execution boundary with exact prod secret ARN and data-plane statements.
* fix(iam): make meal-order plan role Lambda refresh read-only
Replace plan-role lambda:* with Get*/List* so plan-phase credentials cannot mutate functions or layers.
* feat(waf): add seahaven-prod shared CloudFront WebACL stack
Stand up AppWebAcl in a thin prod stack and widen seahaven-site HCP
roles to read the SSM ARN so CloudFront can associate the ACL in-account.
* fix(deploy): add app-web-acl-prod to deploy.yaml
* feat(iam): add hcptf-seahaven-site plan/apply roles
Static-site HCP substrate for seahaven-site-prod plus boundary widen for
the TF-managed content-deploy role (S3 origin + CloudFront invalidate).
* fix(iam): allow seahaven-site HCP roles to read GitHub OIDC provider
Plan refresh needs iam:GetOpenIDConnectProvider for the content-deploy
role trust data source (PLAT-91 first-plan AccessDenied).
* feat(iam): add hcptf roles and boundary for procurement-ingest
* fix(iam): tighten procurement-ingest apply and plan scopes
Replace kms:* and secret-value writes on shell statements; split IAM
collection APIs onto Resource "*".
* feat(iam): add hcptf roles for sh-openswe-traces-prod
Storage/IAM-user apply and plan roles for the HCP workspace. No Lambda
boundary widen; explicit IAM user CRUD because hcptf-iam-management is
role-path-only.
* fix(iam): pin CreateSecret to exact export secret name
Remove CreateSecret and UpdateSecret from the ARN-prefix shell grant so
apply cannot create longer-named secrets or overwrite SecretString.
* feat(iam): add hcptf front-integrations roles and boundary widen
Add plan/apply OIDC roles for front-integrations-prod and widen the
Lambda execution boundary with exact prod secret ARNs plus DynamoDB
CRUD on front-sla-alerts.
* fix(iam): restrict front-integrations plan role to lambda Get/List
Keep mutate APIs on the apply role so a compromised plan-phase
OIDC session cannot update or delete front-* functions.
Expand the README playbook to steps 0–10 and document the required
plan-refresh sidecar plus prefix-scoped apply-role wildcards so the
next workload copies afi patterns instead of relearning first-apply misses.
* feat(iam): add hcptf roles and boundary widen for afi-backup-monitor
Provision plan/apply OIDC roles for workspace afi-backup-monitor-prod
and widen the prod Lambda boundary with the two exact secret ARNs.
* fix(iam): split DescribeLogGroups and allow afi artifact bucket
logs:DescribeLogGroups cannot be resource-scoped; grant it on *. Add
S3 permissions for the HCP Lambda artifact bucket used by PLAT-56.
Cross-family round 1 plus the /sh-security-review verifier confirmed 11
findings on the floor reduction, all documentation defects; no policy
statement changes. The one HIGH: the Terraform migration checklist never
widened the boundary, so a Lambda-bearing Terraform migration would deploy
green and lose every data-plane call at first invoke. Checklist step 2 now
carries the widening requirement, step 3 verifies deployed boundary content,
and the terraform-substrate header no longer reads as 'Terraform path
unaffected'. Also corrected: Description is a REPLACEMENT property (a
Description edit wedges the custom-named policy and CFN's remedy is the
forbidden rename), the sanctioned-source contradiction, the false
AWSLambdaVPCAccessExecutionRole parity claim, the KMS log-group category
error, stale size numbers (691/5,453), the same-PR widening contradiction,
per-workload residue text, a LoggingConfig silent-log-loss note, the
us-east-1 region pin rationale, and ENI DoS deferral now tracked as
INFRA-200.
Replaces the placeholder 'tracked as its own ticket' references with the real
key, and records the load-bearing constraint inline so the next reader does not
rediscover it: both guardrail policies pin ONE literal boundary ARN inside
StringEquals iam:PermissionsBoundary, and loosening that to a wildcard weakens
the gate rather than merely relaxing it.
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.