refactor(modules): remove thin-composition layer; rewrite all module READMEs
The L2 thin-composition layer (composition.json + contract_resolver.py + contract schema + sample contracts) has been removed completely. The implementation was unsatisfactory and is deferred for a later redesign. - Delete: composition.json x2, contract_resolver.py, contracts/ x2, contract.schema.json - Patch: run_platform.sh now loads a pre-existing IR instance instead of resolving a contract (the downstream adapter/checkov/confidence/outbox pipeline is unchanged) - Prune: L2 entries removed from registry.json (L1 entries unchanged) - Rewrite: all 7 L1 module READMEs in plain language (no jargon), each with Resources/Inputs/Outputs/Usage/Compliance-extension-points/Versioning sections derived from interface.json - Add: 2 L2 placeholder READMEs noting the composition is under redesign - Add: modules-ir/README.md catalog index + README-TEMPLATE.md ---ci--- project: acdl phase: 17 milestone: v1.3 status: execute ---/ci---
This commit is contained in:
@@ -1,55 +1,70 @@
|
||||
# l1-alb — Application Load Balancer primitive (multi-resource L1)
|
||||
# l1-alb — Application Load Balancer (load balancer + target group + listener)
|
||||
|
||||
An L1 module for an Application Load Balancer (load balancer + target
|
||||
group + listener). Substrate-agnostic (the IR types are
|
||||
`aws:elbv2:loadbalancer`, `aws:elbv2:listener`, `aws:elbv2:targetgroup`,
|
||||
not Terraform resource types). This is a multi-resource L1: the
|
||||
interface declares the group's inputs/outputs plus a `resources` array
|
||||
listing the IR types it emits. The IR instance (Phase 14/15) will have
|
||||
multiple `resources` entries all with `module: "l1-alb@1.0.0"`.
|
||||
> **Module kind:** L1 primitive | **Version:** 1.0.0
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
An Application Load Balancer with a target group and a listener. This is
|
||||
a multi-resource module: it creates a load balancer, a target group, and
|
||||
a listener that forwards traffic to the target group. The target group
|
||||
is what `l1-ecs-service` registers its tasks with.
|
||||
|
||||
See `interface.json`: inputs `name` (string), `subnets` (string,
|
||||
comma-separated, ref to l1-vpc), `security_group` (string), `port`
|
||||
(number, default 80), `protocol` (string, default "HTTP"), `region`
|
||||
(string); outputs `lb_arn` (arn) + `listener_arn` (arn) +
|
||||
`target_group_arn` (arn); no NFRs.
|
||||
## Resources
|
||||
|
||||
The `resources` array lists the emitted IR types:
|
||||
| Resource | Type | Purpose |
|
||||
|----------|------|---------|
|
||||
| load_balancer | `aws_lb` | Application load balancer in the VPC subnets |
|
||||
| target_group | `aws_lb_target_group` | Target group for the ECS service tasks |
|
||||
| listener | `aws_lb_listener` | Listener forwarding the LB port to the target group |
|
||||
|
||||
- `aws:elbv2:loadbalancer` — application load balancer in the VPC
|
||||
subnets.
|
||||
- `aws:elbv2:targetgroup` — target group for the ECS service tasks.
|
||||
- `aws:elbv2:listener` — listener forwarding the LB port to the target
|
||||
group.
|
||||
## Inputs
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| `name` | string | yes | — | Name tag for the load balancer and child resources |
|
||||
| `subnets` | string | yes | — | Comma-separated subnet ids (from `l1-vpc`) |
|
||||
| `security_group` | string | yes | — | Security group id for the load balancer |
|
||||
| `port` | number | no | 80 | Listener port |
|
||||
| `protocol` | string | no | `HTTP` | Listener protocol |
|
||||
| `region` | string | yes | — | AWS region the load balancer is created in |
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates each
|
||||
emitted IR resource to Terraform:
|
||||
## Outputs
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:elbv2:loadbalancer` | `resource "aws_lb" "<id>" { ... }` |
|
||||
| `resource.inputs.name` | `name = <value>` arg |
|
||||
| `resource.inputs.subnets` | `subnets = [<value>]` arg (comma-split) |
|
||||
| `resource.inputs.security_group` | `security_groups = [<value>]` arg (comma-split) |
|
||||
| `resource.outputs.lb_arn` | `output "lb_arn" { value = aws_lb.<id>.id }` |
|
||||
| `resource.type = aws:elbv2:targetgroup` | `resource "aws_lb_target_group" "<id>" { ... }` |
|
||||
| `resource.inputs.port` | `port = <value>` arg |
|
||||
| `resource.inputs.protocol` | `protocol = <value>` arg |
|
||||
| `resource.outputs.target_group_arn` | `output "target_group_arn" { value = aws_lb_target_group.<id>.arn }` |
|
||||
| `resource.type = aws:elbv2:listener` | `resource "aws_lb_listener" "<id>" { ... }` |
|
||||
| `resource.inputs.lb_arn` | `load_balancer_arn = <value>` arg (identity) |
|
||||
| `resource.inputs.port` | `port = <value>` arg |
|
||||
| `resource.inputs.protocol` | `protocol = <value>` arg |
|
||||
| `resource.outputs.listener_arn` | `output "listener_arn" { value = aws_lb_listener.<id>.id }` |
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `lb_arn` | arn | The load balancer ARN |
|
||||
| `listener_arn` | arn | The listener ARN |
|
||||
| `target_group_arn` | arn | The target group ARN |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
## Usage
|
||||
|
||||
## Versioning (W3.D)
|
||||
```json
|
||||
{
|
||||
"id": "alb",
|
||||
"type": "aws:elbv2:loadbalancer",
|
||||
"module": "l1-alb@1.0.0",
|
||||
"inputs": {
|
||||
"name": "acdl-microservice",
|
||||
"subnets": "ref:vpc.subnet_ids",
|
||||
"security_group": "ref:roles.role_arn",
|
||||
"port": 8080,
|
||||
"protocol": "HTTP",
|
||||
"region": "us-east-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `target_group_arn` output is referenced by `l1-ecs-service` as its
|
||||
`lb_target_group_arn` input to wire the service to the ALB.
|
||||
|
||||
## Compliance extension points
|
||||
|
||||
- **TLS / HTTPS listener** — add `aws_acm_certificate` + `ssl_policy` + `certificate_arn` for encryption in transit (SOC2 CC6.1, PCI-DSS 4.1, HIPAA §164.312(e)(1), GDPR Art.32).
|
||||
- **Access logs** — add `access_logs { bucket = ..., prefix = ... }` to the load balancer (SOX, SOC2 CC7.2, DORA ICT audit trail).
|
||||
- **Security group rules** — add ingress/egress rules restricting traffic to known sources (SOC2 CC6.6, PCI-DSS 1.2).
|
||||
- **Health check** — add a `health_check` block to the target group (SOC2 CC7.3 monitoring, DORA operational resilience).
|
||||
- **WAF** — add `aws_wafv2_web_acl_association` for application-layer protection (SOC2 CC7.6, PCI-DSS 6.5, DORA ICT risk).
|
||||
- **Deregistration delay** — add `deregistration_delay` for graceful draining (SOC2 CC9.1 resilience).
|
||||
|
||||
## Versioning
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
|
||||
@@ -1,31 +1,57 @@
|
||||
# l1-ecr — ECR repository primitive
|
||||
# l1-ecr — ECR repository
|
||||
|
||||
An L1 module for an ECR repository that hosts the ECS task image.
|
||||
Single-purpose, substrate-agnostic (the IR type is
|
||||
`aws:ecr:repository`, not a Terraform resource type).
|
||||
> **Module kind:** L1 primitive | **Version:** 1.0.0
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
A single ECR repository that hosts the container image for the ECS
|
||||
task. The simplest container-registry module — one resource, two
|
||||
inputs, two outputs.
|
||||
|
||||
See `interface.json`: inputs `name` + `region` (strings), outputs
|
||||
`repository_url` (string) + `repository_arn` (arn), no NFRs.
|
||||
## Resources
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
| Resource | Type | Purpose |
|
||||
|----------|------|---------|
|
||||
| repository | `aws_ecr_repository` | The ECR repository |
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||
L1's IR shape to Terraform:
|
||||
## Inputs
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ecr:repository` | `resource "aws_ecr_repository" "<id>" { ... }` |
|
||||
| `resource.inputs.name` | `name = <value>` arg |
|
||||
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||
| `resource.outputs.repository_url` | `output "repository_url" { value = aws_ecr_repository.<id>.repository_url }` |
|
||||
| `resource.outputs.repository_arn` | `output "repository_arn" { value = aws_ecr_repository.<id>.arn }` |
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| `name` | string | yes | — | The ECR repository name |
|
||||
| `region` | string | yes | — | AWS region the repository is created in |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
## Outputs
|
||||
|
||||
## Versioning (W3.D)
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `repository_url` | string | The ECR repository URL |
|
||||
| `repository_arn` | arn | The ECR repository ARN |
|
||||
|
||||
## Usage
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "ecr",
|
||||
"type": "aws:ecr:repository",
|
||||
"module": "l1-ecr@1.0.0",
|
||||
"inputs": {
|
||||
"name": "acdl-microservice",
|
||||
"region": "us-east-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `repository_url` output is used to build the `image` input for
|
||||
`l1-ecs-service` (e.g. `<repository_url>:latest`).
|
||||
|
||||
## Compliance extension points
|
||||
|
||||
- **Image scanning** — add `image_scanning_configuration { scan_on_push = true }` for vulnerability scanning (SOC2 CC7.6, DORA ICT risk testing, HIPAA security monitoring).
|
||||
- **Encryption** — add `encryption_configuration { encryption_type = "KMS", kms_key = ... }` with a customer-managed key (SOC2 CC6.1, HIPAA §164.312(a)(2)(iv), GDPR Art.32).
|
||||
- **Image tag immutability** — add `image_tag_mutability = "IMMUTABLE"` to prevent tag overwriting (SOX §802, SOC2 CC6.1 integrity, DORA audit integrity).
|
||||
- **Lifecycle policy** — add `aws_ecr_lifecycle_policy` to enforce image retention / cleanup (GDPR Art.5(2) data minimization, SOC2 CC5.2).
|
||||
- **Access policy** — add a repository policy restricting pull/push to known roles (SOC2 CC6.1, HIPAA §164.308(a)(4)).
|
||||
|
||||
## Versioning
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
|
||||
@@ -1,31 +1,55 @@
|
||||
# l1-ecs-cluster — ECS Fargate cluster primitive
|
||||
# l1-ecs-cluster — ECS Fargate cluster
|
||||
|
||||
An L1 module for an ECS Fargate cluster. Single-purpose,
|
||||
substrate-agnostic (the IR type is `aws:ecs:cluster`, not a Terraform
|
||||
resource type).
|
||||
> **Module kind:** L1 primitive | **Version:** 1.0.0
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
An ECS Fargate cluster. The simplest ECS module — one resource, two
|
||||
inputs, two outputs. The cluster is the container orchestration
|
||||
boundary that `l1-ecs-service` references for task placement.
|
||||
|
||||
See `interface.json`: inputs `name` + `region` (strings), outputs
|
||||
`cluster_arn` (arn) + `cluster_id` (string), no NFRs.
|
||||
## Resources
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
| Resource | Type | Purpose |
|
||||
|----------|------|---------|
|
||||
| cluster | `aws_ecs_cluster` | The ECS Fargate cluster |
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||
L1's IR shape to Terraform:
|
||||
## Inputs
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ecs:cluster` | `resource "aws_ecs_cluster" "<id>" { ... }` |
|
||||
| `resource.inputs.name` | `name = <value>` arg |
|
||||
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||
| `resource.outputs.cluster_arn` | `output "cluster_arn" { value = aws_ecs_cluster.<id>.arn }` |
|
||||
| `resource.outputs.cluster_id` | `output "cluster_id" { value = aws_ecs_cluster.<id>.id }` |
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| `name` | string | yes | — | The ECS cluster name |
|
||||
| `region` | string | yes | — | AWS region the cluster is created in |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
## Outputs
|
||||
|
||||
## Versioning (W3.D)
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `cluster_arn` | arn | The ECS cluster ARN |
|
||||
| `cluster_id` | string | The ECS cluster id (name) |
|
||||
|
||||
## Usage
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "cluster",
|
||||
"type": "aws:ecs:cluster",
|
||||
"module": "l1-ecs-cluster@1.0.0",
|
||||
"inputs": {
|
||||
"name": "acdl-microservice",
|
||||
"region": "us-east-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `cluster_arn` output is referenced by `l1-ecs-service` as its
|
||||
`cluster_arn` input.
|
||||
|
||||
## Compliance extension points
|
||||
|
||||
- **Container Insights** — add `configuration { container_insights = "enabled" }` for observability (SOC2 CC7.3, DORA ICT risk monitoring).
|
||||
- **CloudWatch Logs** — add a log group with retention policy for cluster-level audit logs (SOX, SOC2 CC7.2, HIPAA §164.312(b)).
|
||||
- **Encryption** — add `settings { name = "containerInsights", value = "enabled" }` and KMS-based encryption for container data (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
|
||||
|
||||
@@ -1,54 +1,77 @@
|
||||
# l1-ecs-service — ECS Fargate service primitive (multi-resource L1)
|
||||
# l1-ecs-service — ECS Fargate service (task definition + service)
|
||||
|
||||
An L1 module for an ECS Fargate service (task definition + service).
|
||||
Substrate-agnostic (the IR types are `aws:ecs:task_definition` and
|
||||
`aws:ecs:service`, not Terraform resource types). This is a
|
||||
multi-resource L1: the interface declares the group's inputs/outputs
|
||||
plus a `resources` array listing the IR types it emits. The IR instance
|
||||
(Phase 14/15) will have multiple `resources` entries all with
|
||||
`module: "l1-ecs-service@1.0.0"`.
|
||||
> **Module kind:** L1 primitive | **Version:** 1.0.0
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
An ECS Fargate service with its task definition. Runs a container image
|
||||
on Fargate, optionally behind an ALB target group. This is a
|
||||
multi-resource module: it creates a task definition and a service that
|
||||
runs it.
|
||||
|
||||
See `interface.json`: inputs `image` (string, ECR image URL), `port`
|
||||
(number), `cpu` (number, default 256), `memory` (number, default 512),
|
||||
`env` (optional JSON map string), `cluster_arn` (arn, ref to
|
||||
l1-ecs-cluster), `subnets` (string, ref to l1-vpc), `security_group`
|
||||
(string), `lb_target_group_arn` (arn, optional, ref to l1-alb), `region`
|
||||
(string); outputs `service_arn` (arn) + `task_def_arn` (arn); no NFRs.
|
||||
## Resources
|
||||
|
||||
The `resources` array lists the emitted IR types:
|
||||
| Resource | Type | Purpose |
|
||||
|----------|------|---------|
|
||||
| task_definition | `aws_ecs_task_definition` | Fargate task definition with container image, CPU, memory, port, env |
|
||||
| service | `aws_ecs_service` | Fargate service running the task definition in a cluster + subnets |
|
||||
|
||||
- `aws:ecs:task_definition` — Fargate task definition. The adapter
|
||||
jsonencodes `image`/`port`/`env` into `container_definitions`.
|
||||
- `aws:ecs:service` — Fargate service running the task definition in the
|
||||
cluster + subnets (+ optional ALB target group wiring).
|
||||
## Inputs
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| `image` | string | yes | — | ECR image URL for the task container |
|
||||
| `port` | number | yes | — | Container port the service listens on |
|
||||
| `cpu` | number | no | 256 | Task CPU units (Fargate) |
|
||||
| `memory` | number | no | 512 | Task memory in MiB (Fargate) |
|
||||
| `env` | string | no | — | Environment variables as a JSON map string |
|
||||
| `cluster_arn` | arn | yes | — | ECS cluster ARN (from `l1-ecs-cluster`) |
|
||||
| `subnets` | string | yes | — | Comma-separated subnet ids (from `l1-vpc`) |
|
||||
| `security_group` | string | yes | — | Security group id for the service ENIs |
|
||||
| `lb_target_group_arn` | arn | no | — | Optional ALB target group ARN (from `l1-alb`) |
|
||||
| `region` | string | yes | — | AWS region the service is created in |
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates each
|
||||
emitted IR resource to Terraform:
|
||||
## Outputs
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ecs:task_definition` | `resource "aws_ecs_task_definition" "<id>" { ... }` |
|
||||
| `resource.inputs.image` + `port` + `env` | `container_definitions = jsonencode(...)` (adapter-built) |
|
||||
| `resource.inputs.cpu` | `cpu = <value>` arg |
|
||||
| `resource.inputs.memory` | `memory = <value>` arg |
|
||||
| `resource.outputs.task_def_arn` | `output "task_def_arn" { value = aws_ecs_task_definition.<id>.arn }` |
|
||||
| `resource.type = aws:ecs:service` | `resource "aws_ecs_service" "<id>" { ... }` |
|
||||
| `resource.inputs.cluster_arn` | `cluster = <value>` arg (identity) |
|
||||
| `resource.inputs.subnets` | `network_configuration { subnets = [...] }` (emit as-is) |
|
||||
| `resource.inputs.security_group` | `network_configuration { security_groups = [...] }` (emit as-is) |
|
||||
| `resource.inputs.lb_target_group_arn` | `load_balancer { target_group_arn = <value> }` (emit as-is) |
|
||||
| `resource.outputs.service_arn` | `output "service_arn" { value = aws_ecs_service.<id>.id }` |
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `service_arn` | arn | The ECS service ARN |
|
||||
| `task_def_arn` | arn | The ECS task definition ARN |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates. The `container_definitions` JSON is built
|
||||
by the adapter from the IR `image`/`port`/`env` inputs (the one
|
||||
transformation the adapter owns for ECS task definitions).
|
||||
## Usage
|
||||
|
||||
## Versioning (W3.D)
|
||||
```json
|
||||
{
|
||||
"id": "service",
|
||||
"type": "aws:ecs:task_definition",
|
||||
"module": "l1-ecs-service@1.0.0",
|
||||
"inputs": {
|
||||
"image": "581513795199.dkr.ecr.us-east-1.amazonaws.com/acdl-microservice:latest",
|
||||
"port": 8080,
|
||||
"cpu": 256,
|
||||
"memory": 512,
|
||||
"cluster_arn": "ref:cluster.cluster_arn",
|
||||
"subnets": "ref:vpc.subnet_ids",
|
||||
"security_group": "ref:roles.role_arn",
|
||||
"region": "us-east-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `image`, `port`, and `env` inputs are compiled into a
|
||||
`container_definitions` JSON block by the adapter. The service is
|
||||
placed in the cluster with the given subnets and security group, and
|
||||
optionally wired to the ALB target group if `lb_target_group_arn` is
|
||||
provided.
|
||||
|
||||
## Compliance extension points
|
||||
|
||||
- **CloudWatch Logs** — add `logConfiguration` to the container definition with a log group + retention policy (SOX, SOC2 CC7.2, HIPAA §164.312(b), DORA ICT incident logging).
|
||||
- **Task execution role separation** — add a separate `aws_iam_role` for execution vs. the task role (SOC2 CC6.3 segregation of duties at runtime).
|
||||
- **Secrets injection** — add `secrets` block referencing AWS Secrets Manager / SSM Parameter Store with KMS encryption (SOC2 CC6.1, HIPAA §164.312(a)(2)(iv)).
|
||||
- **Execute command** — add `enable_execute_command` with KMS encryption for session audit (SOC2 CC7.2).
|
||||
- **Deployment circuit breaker** — add `deployment_circuit_breaker` block for resilience (SOC2 CC9.1, DORA operational resilience).
|
||||
- **Health check** — add a `health_check` block to the target group (currently missing despite the contract schema having a healthcheck field).
|
||||
|
||||
## Versioning
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
|
||||
@@ -1,35 +1,63 @@
|
||||
# l1-iam-role — IAM role primitive
|
||||
# l1-iam-role — IAM role
|
||||
|
||||
An L1 module for an IAM role (used as the ECS task execution role).
|
||||
Single-purpose, substrate-agnostic (the IR type is `aws:iam:role`, not a
|
||||
Terraform resource type).
|
||||
> **Module kind:** L1 primitive | **Version:** 1.0.0
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
A single IAM role with an assume-role policy and optional managed
|
||||
policy attachments. Used as the ECS task execution role.
|
||||
|
||||
See `interface.json`: inputs `role_name` (string), `assume_role_policy`
|
||||
(JSON string), `managed_policies` (optional comma-separated ARNs),
|
||||
`region` (string); outputs `role_arn` (arn) + `role_id` (string), no
|
||||
NFRs.
|
||||
## Resources
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
| Resource | Type | Purpose |
|
||||
|----------|------|---------|
|
||||
| role | `aws_iam_role` | The IAM role with assume-role policy |
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||
L1's IR shape to Terraform:
|
||||
## Inputs
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:iam:role` | `resource "aws_iam_role" "<id>" { ... }` |
|
||||
| `resource.inputs.role_name` | `name = <value>` arg |
|
||||
| `resource.inputs.assume_role_policy` | `assume_role_policy = <value>` arg (JSON string) |
|
||||
| `resource.inputs.managed_policies` | `managed_policy_arns = [<arns>]` arg (comma-split) |
|
||||
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||
| `resource.outputs.role_arn` | `output "role_arn" { value = aws_iam_role.<id>.arn }` |
|
||||
| `resource.outputs.role_id` | `output "role_id" { value = aws_iam_role.<id>.id }` |
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| `role_name` | string | yes | — | The IAM role name |
|
||||
| `assume_role_policy` | string | yes | — | Assume-role policy document (JSON string) |
|
||||
| `managed_policies` | string | no | — | Comma-separated list of managed policy ARNs to attach |
|
||||
| `region` | string | yes | — | AWS region the role is created in |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
## Outputs
|
||||
|
||||
## Versioning (W3.D)
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `role_arn` | arn | The IAM role ARN |
|
||||
| `role_id` | string | The IAM role id |
|
||||
|
||||
## Usage
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "roles",
|
||||
"type": "aws:iam:role",
|
||||
"module": "l1-iam-role@1.0.0",
|
||||
"inputs": {
|
||||
"role_name": "acdl-microservice-exec",
|
||||
"assume_role_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ecs-tasks.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}",
|
||||
"managed_policies": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
|
||||
"region": "us-east-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `assume_role_policy` is a JSON string — the adapter jsonencodes it
|
||||
into the Terraform `assume_role_policy` argument. The
|
||||
`managed_policies` input is a comma-separated list of ARNs, emitted as
|
||||
`managed_policy_arns = [...]`.
|
||||
|
||||
## Compliance extension points
|
||||
|
||||
- **Permissions boundary** — add `permissions_boundary` to enforce least-privilege guardrails (SOC2 CC6.1, SOX ITGC, DORA ICT access control).
|
||||
- **Inline policy** — add `aws_iam_role_policy` for fine-grained least-privilege instead of broad managed policies (SOC2 CC6.1, HIPAA §164.308(a)(4)).
|
||||
- **MFA conditions** — add `condition` blocks requiring MFA for assume-role (SOC2 CC6.1, HIPAA §164.312(d)).
|
||||
- **Source IP / region conditions** — add `aws:SourceIp` / `aws:RequestedRegion` conditions for data residency enforcement (GDPR Art.44-49, DORA ICT third-party risk).
|
||||
- **Access Analyzer** — add `aws_accessanalyzer_analyzer` to verify least-privilege (SOC2 CC6.1, GDPR Art.32).
|
||||
- **Role separation** — add a separate task role vs. execution role (SOC2 CC6.3 segregation of duties).
|
||||
|
||||
## Versioning
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
|
||||
@@ -1,39 +1,62 @@
|
||||
# l1-s3 — S3 bucket primitive
|
||||
# l1-s3 — S3 bucket
|
||||
|
||||
The first real L1 module for the v1.1 spike. Single-purpose,
|
||||
substrate-agnostic (the IR type is `aws:s3:bucket`, not a Terraform
|
||||
resource type).
|
||||
> **Module kind:** L1 primitive | **Version:** 1.0.0
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
A single S3 bucket for object storage. The simplest module — one
|
||||
resource, two inputs, two outputs. Versioning is enabled by default.
|
||||
|
||||
See `interface.json`: inputs `bucket_name` + `region` (strings), outputs
|
||||
`bucket_arn` (arn) + `bucket_name` (string), NFR `versioning` (bool,
|
||||
default true).
|
||||
## Resources
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
| Resource | Type | Purpose |
|
||||
|----------|------|---------|
|
||||
| bucket | `aws_s3_bucket` | The S3 bucket itself |
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||
L1's IR shape to Terraform:
|
||||
## Inputs
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:s3:bucket` | `resource "aws_s3_bucket" "<id>" { ... }` |
|
||||
| `resource.inputs.bucket_name` | `bucket = <value>` arg |
|
||||
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||
| `resource.outputs.bucket_arn` | `output "bucket_arn" { value = aws_s3_bucket.<id>.arn }` |
|
||||
| `resource.outputs.bucket_name` | `output "bucket_name" { value = aws_s3_bucket.<id>.id }` |
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| `bucket_name` | string | yes | — | Globally-unique S3 bucket name |
|
||||
| `region` | string | yes | — | AWS region the bucket is created in |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
## Outputs
|
||||
|
||||
## Spike instance
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `bucket_arn` | arn | The S3 bucket ARN |
|
||||
| `bucket_name` | string | The bucket name (echoes the input) |
|
||||
|
||||
`spike_instance.json` is a concrete stack instance (with values
|
||||
`bucket_name=acdl-spike-bucket`, `region=us-east-1`) that validates
|
||||
against `schemas/ir.schema.json`. The adapter consumes this instance
|
||||
(not the interface contract) to emit Terraform.
|
||||
## NFRs
|
||||
|
||||
## Versioning (W3.D)
|
||||
| Name | Type | Default | Description |
|
||||
|------|------|---------|-------------|
|
||||
| `versioning` | boolean | true | Enable S3 versioning |
|
||||
|
||||
## Usage
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "s3",
|
||||
"type": "aws:s3:bucket",
|
||||
"module": "l1-s3@1.0.0",
|
||||
"inputs": {
|
||||
"bucket_name": "acdl-spike-bucket",
|
||||
"region": "us-east-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A concrete instance is at `spike_instance.json` (used by the platform
|
||||
pipeline as the regression baseline).
|
||||
|
||||
## Compliance extension points
|
||||
|
||||
- **Encryption at rest** — add `aws_s3_bucket_server_side_encryption_configuration` with a customer-managed KMS key (SOC2 CC6.1, HIPAA §164.312(a)(2)(iv), GDPR Art.32).
|
||||
- **Object Lock** — add `aws_s3_bucket_object_lock_configuration` in compliance mode with 7-year retention for immutable evidence (SOX §802, DORA audit trail).
|
||||
- **Access logging** — add `aws_s3_bucket_logging` to a target logging bucket (SOC2 CC7.2).
|
||||
- **Public access block** — add `aws_s3_bucket_public_access_block` to prevent data exfiltration (SOC2 CC6.1, GDPR Art.32).
|
||||
- **Lifecycle policy** — add `aws_s3_bucket_lifecycle_configuration` for retention enforcement (GDPR Art.5(2), HIPAA §164.530(j)).
|
||||
|
||||
## Versioning
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
|
||||
@@ -1,51 +1,66 @@
|
||||
# l1-vpc — VPC primitive (multi-resource L1)
|
||||
# l1-vpc — VPC with subnets and routing
|
||||
|
||||
An L1 module for a VPC with subnets and a route table. Substrate-agnostic
|
||||
(the IR types are `aws:ec2:vpc`, `aws:ec2:subnet`, `aws:ec2:routetable`,
|
||||
not Terraform resource types). This is a multi-resource L1: the
|
||||
interface declares the group's inputs/outputs plus a `resources` array
|
||||
listing the IR types it emits. The IR instance (Phase 14/15) will have
|
||||
multiple `resources` entries all with `module: "l1-vpc@1.0.0"`.
|
||||
> **Module kind:** L1 primitive | **Version:** 1.0.0
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
A VPC with one subnet per availability zone and a route table with a
|
||||
default route through an internet gateway. The networking foundation
|
||||
that other modules (ALB, ECS service) reference for subnet ids.
|
||||
|
||||
See `interface.json`: inputs `cidr` (string, e.g. "10.0.0.0/16"), `azs`
|
||||
(string, comma-separated, e.g. "us-east-1a,us-east-1b"), `name` (string,
|
||||
used for tagging), `region` (string); outputs `vpc_id` (string),
|
||||
`subnet_ids` (string, comma-separated), `igw_id` (string); no NFRs.
|
||||
## Resources
|
||||
|
||||
The `resources` array lists the emitted IR types:
|
||||
| Resource | Type | Purpose |
|
||||
|----------|------|---------|
|
||||
| vpc | `aws_vpc` | The VPC itself |
|
||||
| subnet | `aws_subnet` | One subnet per availability zone |
|
||||
| route_table | `aws_route_table` | Route table with default route 0.0.0.0/0 |
|
||||
| internet_gateway | `aws_internet_gateway` | IGW for public internet access |
|
||||
| route_table_association | `aws_route_table_association` | Binds subnet to route table |
|
||||
|
||||
- `aws:ec2:vpc` — the VPC itself (cidr → cidr_block, name → tag).
|
||||
- `aws:ec2:subnet` — one subnet per availability zone (`azs` split on
|
||||
comma); inputs include the parent VPC id.
|
||||
- `aws:ec2:routetable` — route table bound to the VPC with an internet
|
||||
gateway + default route (0.0.0.0/0 → igw).
|
||||
## Inputs
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
| Name | Type | Required | Default | Description |
|
||||
|------|------|----------|---------|-------------|
|
||||
| `cidr` | string | yes | — | VPC CIDR block, e.g. `10.0.0.0/16` |
|
||||
| `azs` | string | yes | — | Comma-separated availability zones, e.g. `us-east-1a,us-east-1b` |
|
||||
| `name` | string | yes | — | Name tag for the VPC and child resources |
|
||||
| `region` | string | yes | — | AWS region the VPC is created in |
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates each
|
||||
emitted IR resource to Terraform:
|
||||
## Outputs
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ec2:vpc` | `resource "aws_vpc" "<id>" { ... }` |
|
||||
| `resource.inputs.cidr` | `cidr_block = <value>` arg |
|
||||
| `resource.inputs.name` | `tags = { Name = <value> }` (emit as-is) |
|
||||
| `resource.outputs.vpc_id` | `output "vpc_id" { value = aws_vpc.<id>.id }` |
|
||||
| `resource.type = aws:ec2:subnet` | `resource "aws_subnet" "<id>" { ... }` |
|
||||
| `resource.inputs.cidr` | `cidr_block = <value>` arg |
|
||||
| `resource.inputs.az` | `availability_zone = <value>` arg |
|
||||
| `resource.outputs.subnet_id` | `output "subnet_id" { value = aws_subnet.<id>.id }` |
|
||||
| `resource.type = aws:ec2:routetable` | `resource "aws_route_table" "<id>" { ... }` |
|
||||
| `resource.inputs.vpc_id` | `vpc_id = <value>` arg |
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `vpc_id` | string | The VPC id |
|
||||
| `subnet_ids` | string | Comma-separated subnet ids |
|
||||
|
||||
The internet gateway + default route are emitted as part of the route
|
||||
table resource's IR (the `igw_id` output is wired via the route table's
|
||||
inputs). The adapter is a thin layer (ARCHITECTURE.md §12.2); it does
|
||||
not own L1 content — it only translates.
|
||||
## Usage
|
||||
|
||||
## Versioning (W3.D)
|
||||
```json
|
||||
{
|
||||
"id": "vpc",
|
||||
"type": "aws:ec2:vpc",
|
||||
"module": "l1-vpc@1.0.0",
|
||||
"inputs": {
|
||||
"cidr": "10.0.0.0/16",
|
||||
"azs": "us-east-1a,us-east-1b",
|
||||
"name": "acdl-microservice",
|
||||
"region": "us-east-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `azs` input is split on comma; one subnet is created per zone. The
|
||||
route table gets a default route `0.0.0.0/0` → internet gateway. Other
|
||||
modules reference `subnet_ids` for their network placement.
|
||||
|
||||
## Compliance extension points
|
||||
|
||||
- **VPC Flow Logs** — add `aws_flow_log` + CloudWatch Logs group / S3 destination (SOX ITGC, SOC2 CC7.2, HIPAA §164.312(b), DORA ICT risk logging).
|
||||
- **Private subnets + NAT gateway** — add private subnets with a NAT gateway so ECS tasks don't need public IPs (SOC2 CC6.6, PCI-DSS 1.3, HIPAA network isolation).
|
||||
- **VPC endpoints** — add S3, ECR, KMS, DynamoDB, CloudWatch interface/gateway endpoints to keep traffic off the public internet (SOC2 CC6.7, GDPR Art.32(1)(a), DORA ICT third-party risk).
|
||||
- **Security groups** — add `aws_security_group` as a first-class sub-resource (currently missing; needed for all regulated deployments) (SOC2 CC6.6, PCI-DSS 1.2).
|
||||
- **Network ACLs** — add `aws_network_acl` for subnet-level segmentation (PCI-DSS 1.3).
|
||||
|
||||
## Versioning
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
|
||||
Reference in New Issue
Block a user