feat(s3): files.coilysiren.me, a private bucket the public reads through CloudFront #873
No reviewers
Labels
No labels
burndown-2026-06
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/infrastructure!873
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/public-asset-host"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
files.coilysiren.me, the asset host Sirens Dowel publishes to through themcp-beaver serve-s3MCP, plus themcp-beaver-s3workload identity that writes it.Pairs with coilyco-flight-deck/mcp-beaver#90, which adds the serve mode.
A separate stack, not
aws-inventoryThat stack owns the
coilysiren.mezone and all 17 of its records, so a bad apply there breaks DNS for every service. This one creates one hostname and touches nothing that already resolves. Its README also asks it stay S3 and Route53 rather than grow into a mega-stack, and CloudFront plus ACM is neither.The bucket is private
The obvious shape is a public-read policy on a bucket named after the domain, and that shape costs TLS. An S3 website endpoint does not speak it, and the
*.s3.amazonaws.comcertificate does not match a bucket name containing dots, so the pretty hostname and HTTPS are mutually exclusive without something in front.scripts/demo-asset-host.shin the deploy repo hit exactly this and shipped two URLs per object as a result.CloudFront is that something, and once it is there the bucket has no reason to be public. All four public-access-block flags stay on, and the only principal in the bucket policy is
cloudfront.amazonaws.com, narrowed byAWS:SourceArnto this one distribution. Without that condition the service principal admits any distribution in any account, which is the usual way an OAC bucket ends up readable through a stranger's edge.The IAM half
Lands in
aws-iam, where every principal in this account is declared.mcp-beaver-s3getsPutObject,GetObject, andListBucket, and noDeleteObject: publishing is the grant, unpublishing is not. Kai creates the user by hand, so animportblock adopts it rather than racing to create a second one. Versioning makes the overwritePutObjectdoes allow recoverable, with noncurrent versions expiring at 90 days.The two stacks meet only through the bucket name, so neither reads the other's state.
Validation, and what is still owed
pre-commit run --all-filesis green.terraform fmt,validate, andplancould not run in this session and are still owed before any apply. The HCL is hand-checked for alignment against the sibling stacks but nothing has parsed it. Please run:The IAM stack needs its own
plantoo, since the import block formcp-beaver-s3only resolves once that user exists.A first
applywaits on the CloudFront distribution reaching Deployed, several minutes of AWS propagating rather than a hang. ACM validation resolves on its own because the stack writes its own validation records.Cache note
The distribution uses AWS-managed CachingOptimized, so an overwritten key serves stale bytes until its TTL expires. Prefer publishing a new key over replacing one.
403and404cache for 10 seconds so a link shared just before its object lands recovers quickly.