---ci---
phase: 22
title: rename-and-production-static-assets-stack
status: complete
verification:
- scripts/run_ci.sh: PASS (CI PIPELINE OK)
- python3 -m pytest tests/ -v: 175 passed
- scripts/run_platform.sh --check-only: PASS (PLATFORM CHECK OK)
- grep -R "static-asset[^s]" . (excl .git/): 0 hits
- grep -R "static-asset$" . (excl .git/): 0 hits
- floating git tags v1.6 + v1 point at v1.6.0 (a90a756)
changed_files:
- Task 1 (rename): contracts/static-asset.yaml→static-assets.yaml (git mv); modules/l2/static-asset→static-assets (git mv); sed replaceAll static-asset→static-assets in 22 files (README, docs, scripts/run_platform.sh, pipelines/deploy.yaml, modules/registry.json, tests/*, .ciagent/* historical narrative)
- Task 2 (cloudfront primitive): modules/l1/cloudfront/interface.json + README.md
- Task 3 (waf primitive): modules/l1/waf/interface.json + README.md
- Task 4 (registry): modules/registry.json (+cloudfront, +waf, static-assets renamed)
- Task 5 (augment static-assets): modules/l2/static-assets/composition.json (s3+cloudfront+waf, depth 1); modules/l1/s3/interface.json +instance.json (+bucket_regional_domain_name output); modules/l2/static-assets/README.md (production stack docs)
- Task 6 (adapter): adapters/terraform/adapter.py (+TYPE_MAP/INPUT_MAP/OUTPUT_MAP for cloudfront distribution+OAC+wafv2 webacl; special handling in _emit_resource for OAC defaults, distribution origin/cache_behavior/restrictions/viewer_certificate/web_acl_id, waf scope/default_action/visibility_config/managed rules)
- Task 7 (contract schema): no change needed (generic inputs object; new module names match ^[a-z][a-z0-9-]*$)
- Task 8 (@v1.6 bump): contracts/static-assets.yaml, .gitea/.github/workflows/deploy.yml (ref: v1.6 + header comments), docs/consumer-guide.md, docs/contracts/index.md, docs/pipeline/versioning.md, docs/pipeline/index.md, docs/architecture.md, README.md, modules/l2/microservice/README.md, tests/test_environment_check.py, tests/test_pipeline_contract.py
- Task 9 (floating tags): git tag -f v1.6 v1.6.0; git tag -f v1 v1.6.0
- Task 10 (tests): tests/test_adapter.py (registry 11 entries/9 L1/2 L2; cloudfront+waf type map tests; TestS3Output bucket_regional_domain_name; TestStaticAssetsStack 4 tests); tests/test_contract_resolver.py (+s3/cloudfront/waf resource assertions)
generated:
- terraform/spike/main.tf + terraform.tf (regenerated by run_platform.sh --check-only; reflect static-assets production stack + backend key spike/static-assets/)
notes:
- D-048 full rewrite of .ciagent/ historical narrative (verbatim phase descriptions, REQ-25/27/50, D-036) — produces intentional tautologies (e.g. "Rename static-assets → static-assets") per the decision to override the v1.6 preservation precedent.
- cloudfront interface.json resources array ordered distribution-first so the resolver (first-match wire resolution) routes bucket_regional_domain_name/waf_web_acl_arn/region to the distribution; the OAC gets adapter-provided defaults (name=acdl-oac, origin_type=s3, signing_behavior=always).
- .ciagent/ @v1.4 references left as historical record (D-048 scope was static-asset rename only; @v1.4 is historical narrative of Phase 20).
- s3 OUTPUT_MAP bucket_regional_domain_name not added (identity fallback in adapt() already handles it; OUTPUT_MAP documents non-identity mappings only).
---ci---
static-assets — Production static asset stack (S3 + CloudFront + WAF)
Module kind: module pattern | Version: 1.0.0
A production-ready pattern that references the s3, cloudfront, and
waf primitives to deploy a static asset site with a CloudFront CDN
edge (S3 origin via Origin Access Control) and WAF protection. A simpler
S3-only variation is documented below.
Resources
The pattern references these primitives:
| Primitive | Purpose | README |
|---|---|---|
s3 |
S3 bucket (origin) | README |
cloudfront |
CloudFront distribution + OAC | README |
waf |
WAFv2 Web ACL (CloudFront-scoped) | README |
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
bucket_name |
string | yes | Globally-unique S3 bucket name |
region |
string | yes | AWS region the bucket is created in |
Outputs
| Name | Type | Description |
|---|---|---|
distribution_domain_name |
string | The CloudFront distribution domain name |
bucket_arn |
arn | The S3 bucket ARN |
web_acl_arn |
arn | The WAF Web ACL ARN |
Usage
Define a contract referencing this module (the production stack — S3 + CloudFront + WAF):
uses: acdl/pipelines/deploy.yaml@v1.6
module: static-assets
environment: dev
inputs:
bucket_name: my-static-assets
region: us-east-1
The composition wires the s3 bucket regional domain name to the CloudFront origin and the WAF web ACL ARN to the CloudFront distribution automatically.
Simpler variation (S3 only)
For a simple S3-only static asset site (no CDN, no WAF), a consumer can
declare a contract that references the s3 primitive directly:
uses: acdl/pipelines/deploy.yaml@v1.6
module: s3
environment: dev
inputs:
bucket_name: my-static-assets
region: us-east-1
This deploys a single S3 bucket (no CloudFront edge, no WAF). Use this for low-traffic internal sites where a CDN edge is not required.
See the consumer guide for a step-by-step walkthrough, and the s3, cloudfront, and waf READMEs for the underlying primitives.
Compliance extension points
The pattern can wire compliance resources when the compliance milestone (GDPR, SOX, SOC2, HIPAA, DORA) lands:
- KMS key — shared encryption key for S3 SSE.
- S3 access logs — access logging to a separate audit bucket.
- Object Lock — 7-year immutable retention for evidence.
- Public access block — prevent data exfiltration.
- CloudFront TLS/HTTPS — viewer protocol policy defaults to
redirect-to-https; a custom ACM certificate can pin TLS to a customer domain. - CloudFront geo restriction — whitelist/blacklist countries for data-residency compliance.
- CloudFront logging — access logs to an S3 bucket for auditability.
- WAF rate limiting / geo blocking / custom rules / logging — see the waf README.
See the per-primitive READMEs for the per-module compliance extension points.
Versioning
1.0.0 — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
require a new registry entry (immutable publication); old entries enter
a 12-month deprecation window.