feat(P22): rename static-asset→static-assets + cloudfront/waf primitives + production stack + @v1.6 bump

---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---
This commit is contained in:
Jon Chery
2026-07-22 19:56:52 +00:00
parent 2732abb23f
commit dca35c78ec
37 changed files with 804 additions and 191 deletions
+78
View File
@@ -0,0 +1,78 @@
# cloudfront — CloudFront distribution
> **Module kind:** primitive | **Version:** 1.0.0
A CloudFront distribution with an S3 origin via Origin Access Control
(OAC). The distribution serves the bucket's static content from the
global edge network with HTTPS redirection by default. An optional WAF
web ACL can be associated to filter traffic before it reaches the
origin.
## Resources
| Resource | Type | Purpose |
|----------|------|---------|
| `oac` | `aws_cloudfront_origin_access_control` | Origin Access Control signing the S3 origin |
| `distribution` | `aws_cloudfront_distribution` | The CloudFront distribution with an S3 origin via OAC |
## Inputs
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `bucket_regional_domain_name` | string | yes | — | The S3 bucket regional domain name (ref to s3 origin) |
| `price_class` | string | no | `PriceClass_100` | CloudFront price class |
| `viewer_protocol_policy` | string | no | `redirect-to-https` | Viewer protocol policy |
| `default_ttl` | number | no | 3600 | Default TTL in seconds |
| `max_ttl` | number | no | 86400 | Max TTL in seconds |
| `waf_web_acl_arn` | string | no | — | WAF web ACL ARN to associate (ref to waf) |
| `region` | string | yes | — | AWS region (CloudFront is global but the provider region is used for the OAC) |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| `distribution_arn` | arn | The CloudFront distribution ARN |
| `distribution_domain_name` | string | The CloudFront distribution domain name (e.g. d111111abcdef8.cloudfront.net) |
| `oac_id` | string | The Origin Access Control ID |
## Usage
```json
{
"id": "cloudfront",
"type": "aws:cloudfront:distribution",
"module": "cloudfront@1.0.0",
"inputs": {
"bucket_regional_domain_name": "ref:s3.bucket_regional_domain_name",
"price_class": "PriceClass_100",
"viewer_protocol_policy": "redirect-to-https",
"default_ttl": 3600,
"max_ttl": 86400,
"waf_web_acl_arn": "ref:waf.web_acl_arn",
"region": "us-east-1"
}
}
```
The `bucket_regional_domain_name` and `waf_web_acl_arn` inputs are
typically wired as `ref:` expressions from the `s3` and `waf` primitives
inside a module composition (see `modules/l2/static-assets`).
## Compliance extension points
- **TLS/HTTPS** — viewer protocol policy defaults to `redirect-to-https`;
a custom ACM certificate + `viewer_certificate` block can pin TLS to a
customer domain (SOC2 CC6.1, GDPR Art.32).
- **Geo restriction** — the `restrictions.geo_restriction` block can
whitelist/blacklist countries for data-residency compliance (GDPR
Art.44, SOC2 CC6.1).
- **Logging** — CloudFront access logs to an S3 bucket for auditability
(SOC2 CC7.2, DORA audit trail).
- **Field-level encryption** — add field-level encryption for PII fields
in POST bodies (HIPAA §164.312(a)(2)(iv), GDPR Art.32).
## 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.
+80
View File
@@ -0,0 +1,80 @@
{
"name": "cloudfront",
"version": "1.0.0",
"kind": "l1",
"type": "aws:cloudfront:distribution",
"description": "CloudFront distribution primitive (substrate-agnostic stack types aws:cloudfront:distribution + aws:cloudfront:originaccesscontrol; the Terraform adapter translates to aws_cloudfront_distribution + aws_cloudfront_origin_access_control).",
"inputs": {
"bucket_regional_domain_name": {
"type": "string",
"description": "The S3 bucket regional domain name (ref to s3 origin).",
"required": true
},
"price_class": {
"type": "string",
"description": "CloudFront price class (default PriceClass_100).",
"required": false,
"default": "PriceClass_100"
},
"viewer_protocol_policy": {
"type": "string",
"description": "Viewer protocol policy (default redirect-to-https).",
"required": false,
"default": "redirect-to-https"
},
"default_ttl": {
"type": "number",
"description": "Default TTL in seconds (default 3600).",
"required": false,
"default": 3600
},
"max_ttl": {
"type": "number",
"description": "Max TTL in seconds (default 86400).",
"required": false,
"default": 86400
},
"waf_web_acl_arn": {
"type": "string",
"description": "WAF web ACL ARN to associate (optional, ref to waf).",
"required": false
},
"region": {
"type": "string",
"description": "AWS region (CloudFront is global but the provider region is used for the OAC).",
"required": true
}
},
"outputs": {
"distribution_arn": {
"type": "arn",
"description": "The CloudFront distribution ARN."
},
"distribution_domain_name": {
"type": "string",
"description": "The CloudFront distribution domain name (e.g. d111111abcdef8.cloudfront.net)."
},
"oac_id": {
"type": "string",
"description": "The Origin Access Control ID."
}
},
"nfrs": {},
"resources": [
{
"type": "aws:cloudfront:distribution",
"description": "CloudFront distribution with S3 origin via OAC.",
"inputs": ["bucket_regional_domain_name", "price_class", "viewer_protocol_policy", "default_ttl", "max_ttl", "waf_web_acl_arn", "oac_id"],
"outputs": ["distribution_arn", "distribution_domain_name"]
},
{
"type": "aws:cloudfront:originaccesscontrol",
"description": "Origin Access Control for the S3 origin.",
"inputs": ["name", "origin_type", "signing_behavior"],
"outputs": ["oac_id"]
}
],
"intra_refs": [
{"from": "aws:cloudfront:distribution.oac_id", "to": "aws:cloudfront:originaccesscontrol.oac_id"}
]
}
+2 -1
View File
@@ -16,7 +16,8 @@
},
"outputs": {
"bucket_arn": {"type": "arn", "description": "The S3 bucket ARN."},
"bucket_name": {"type": "string", "description": "The bucket name."}
"bucket_name": {"type": "string", "description": "The bucket name."},
"bucket_regional_domain_name": {"type": "string", "description": "The bucket regional domain name."}
}
}
]
+4
View File
@@ -24,6 +24,10 @@
"bucket_name": {
"type": "string",
"description": "The bucket name (echoes the input)."
},
"bucket_regional_domain_name": {
"type": "string",
"description": "The bucket regional domain name (e.g. acdl-spike-bucket.s3.us-east-1.amazonaws.com)."
}
},
"nfrs": {
+67
View File
@@ -0,0 +1,67 @@
# waf — WAFv2 Web ACL
> **Module kind:** primitive | **Version:** 1.0.0
A WAFv2 Web ACL scoped to CloudFront. It applies managed rule groups by
default and can be associated with a CloudFront distribution to filter
traffic before it reaches the origin. CloudFront-scoped Web ACLs are
always created in `us-east-1`.
## Resources
| Resource | Type | Purpose |
|----------|------|---------|
| `webacl` | `aws_wafv2_web_acl` | WAFv2 Web ACL with managed rules |
## Inputs
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `name` | string | yes | — | Name of the Web ACL |
| `scope` | string | no | `cloudfront` | Scope of the Web ACL (default cloudfront for CloudFront associations) |
| `default_action` | string | no | `allow` | Default action (default allow) |
| `rules` | string | no | — | Optional custom rules as JSON (default: managed rules only) |
| `region` | string | yes | — | AWS region (CloudFront-scoped WAF is always us-east-1; the adapter ignores this for cloudfront scope) |
## Outputs
| Name | Type | Description |
|------|------|-------------|
| `web_acl_arn` | arn | The WAF Web ACL ARN |
## Usage
```json
{
"id": "waf",
"type": "aws:wafv2:webacl",
"module": "waf@1.0.0",
"inputs": {
"name": "acdl-static-assets-waf",
"scope": "cloudfront",
"default_action": "allow",
"region": "us-east-1"
}
}
```
The `web_acl_arn` output is typically wired as a `ref:` expression into
the `cloudfront` primitive's `waf_web_acl_arn` input inside a module
composition (see `modules/l2/static-assets`).
## Compliance extension points
- **Rate limiting** — add a rate-based rule to cap requests per IP
(SOC2 CC6.1, DORA operational resilience).
- **Geo blocking** — add a geo-match statement to block/allow countries
for data-residency compliance (GDPR Art.44, SOC2 CC6.1).
- **Custom rules** — add custom rule statements for application-specific
filtering (e.g. block SQLi/IP allow-lists) (SOC2 CC6.1).
- **Logging** — enable WAF access logging to S3/CloudWatch/Kinesis for
auditability (SOC2 CC7.2, DORA audit trail).
## 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.
+51
View File
@@ -0,0 +1,51 @@
{
"name": "waf",
"version": "1.0.0",
"kind": "l1",
"type": "aws:wafv2:webacl",
"description": "WAFv2 Web ACL primitive for CloudFront (substrate-agnostic stack type aws:wafv2:webacl; the Terraform adapter translates to aws_wafv2_web_acl). CloudFront-scoped WAF is always in us-east-1.",
"inputs": {
"name": {
"type": "string",
"description": "Name of the Web ACL.",
"required": true
},
"scope": {
"type": "string",
"description": "Scope of the Web ACL (default cloudfront for CloudFront associations).",
"required": false,
"default": "cloudfront"
},
"default_action": {
"type": "string",
"description": "Default action (default allow).",
"required": false,
"default": "allow"
},
"rules": {
"type": "string",
"description": "Optional custom rules as JSON (default: managed rules only).",
"required": false
},
"region": {
"type": "string",
"description": "AWS region (CloudFront-scoped WAF is always us-east-1; the adapter ignores this for cloudfront scope).",
"required": true
}
},
"outputs": {
"web_acl_arn": {
"type": "arn",
"description": "The WAF Web ACL ARN."
}
},
"nfrs": {},
"resources": [
{
"type": "aws:wafv2:webacl",
"description": "WAFv2 Web ACL with managed rules.",
"inputs": ["name", "scope", "default_action", "rules"],
"outputs": ["web_acl_arn"]
}
]
}