d103a37419
---ci--- project: acdl phase: 14 milestone: v1.2 status: verify verdict: VERIFIED requirements: covered: [REQ-32] ---/ci--- Phase 14 plan-as-execute + verify. scripts/verify_phase14.sh green. l2-microservice composition (6 L1s, 2 wire kinds); contract schema extended (inputs allow objects + healthcheck); resolver extended (array-form wires, child->child refs, multi-resource L1 expansion); adapter extended (ref: interpolation translation). v1.2 IR: 11 resources. v1.1 S3 regression byte-identical. Ready to ship v1.2.4.
85 lines
4.1 KiB
Markdown
85 lines
4.1 KiB
Markdown
# l2-microservice — thin-composition (ECS Fargate microservice)
|
|
|
|
The v1.2 L2. A thin-composition that references 6 L1s (depth 1):
|
|
`l1-vpc`, `l1-ecs-cluster`, `l1-ecr`, `l1-iam-role`, `l1-alb`,
|
|
`l1-ecs-service`. The contract's inputs (`name`, `cidr`, `azs`,
|
|
`image`, `port`, `cpu`, `memory`, `env`, `protocol`, `region`,
|
|
`role_name`, `assume_role_policy`, `managed_policies`) map to the
|
|
children's inputs through two wire kinds.
|
|
|
|
## Composition (the IR-typed thin-composition tree)
|
|
|
|
See `composition.json`: `kind=l2`, `depth=1`, six children.
|
|
|
|
### Children
|
|
|
|
| child id | L1 module | IR type(s) |
|
|
|----------|-----------|------------|
|
|
| `vpc` | `l1-vpc@1.0.0` | `aws:ec2:vpc`, `aws:ec2:subnet`, `aws:ec2:routetable` |
|
|
| `cluster` | `l1-ecs-cluster@1.0.0` | `aws:ecs:cluster` |
|
|
| `ecr` | `l1-ecr@1.0.0` | `aws:ecr:repository` |
|
|
| `roles` | `l1-iam-role@1.0.0` | `aws:iam:role` |
|
|
| `alb` | `l1-alb@1.0.0` | `aws:elbv2:loadbalancer`, `aws:elbv2:listener`, `aws:elbv2:targetgroup` |
|
|
| `service` | `l1-ecs-service@1.0.0` | `aws:ecs:task_definition`, `aws:ecs:service` |
|
|
|
|
Multi-resource L1s (`vpc`, `alb`, `service`) declare a `resources`
|
|
array in their `interface.json`; the resolver expands each child into
|
|
one IR resource per `resources` entry (id scheme `<child_id>-<type_suffix>`
|
|
where `type_suffix` is the last segment of the IR type with underscores
|
|
stripped — e.g. `vpc-vpc`, `vpc-subnet`, `vpc-routetable`,
|
|
`alb-loadbalancer`, `alb-targetgroup`, `alb-listener`,
|
|
`service-taskdefinition`, `service-service`. The hyphen separator keeps
|
|
the id valid against `schemas/ir.schema.json`'s
|
|
`^[a-z][a-z0-9-]*$` resource id pattern). Single-resource L1s keep the
|
|
child id verbatim (`cluster`, `ecr`, `roles`).
|
|
|
|
### Wire kinds
|
|
|
|
1. **Contract→child passthrough** — wire name = contract input name;
|
|
target = child id, input = child's input name. For contract inputs
|
|
that fan out to multiple children (`name`, `port`, `region`), the
|
|
wire value is an array of `{target, input}` objects; otherwise a
|
|
single object. Resolves to the concrete contract value.
|
|
|
|
2. **Child→child references** — wire with `source: "child:<id>.<output>"`.
|
|
The value is only known at apply time, so the resolver emits the IR
|
|
input as the string `ref:<ir_resource_id>.<output>` (the IR resource
|
|
id of the *producing* child's first resource — for single-resource
|
|
L1s that is the child id, for multi-resource L1s it is
|
|
`<child_id>-<type_suffix>` of the first resource in the `resources`
|
|
array that declares the output). The adapter translates `ref:` to a
|
|
Terraform interpolation.
|
|
|
|
Wires used by this composition:
|
|
|
|
- Passthrough: `name` (→vpc/cluster/ecr/alb), `cidr` (→vpc), `azs`
|
|
(→vpc), `image` (→service), `port` (→service/alb), `cpu` (→service),
|
|
`memory` (→service), `env` (→service), `protocol` (→alb), `region`
|
|
(→all 6), `role_name` (→roles), `assume_role_policy` (→roles),
|
|
`managed_policies` (→roles).
|
|
- Child→child: `cluster_arn` (cluster→service), `subnet_ids`
|
|
(vpc→service/alb `subnets`), `target_group_arn` (alb→service
|
|
`lb_target_group_arn`), `role_arn` (roles→service/alb
|
|
`security_group`).
|
|
|
|
## IR → Terraform mapping (D-P10-1)
|
|
|
|
The Terraform adapter consumes the *resolved IR instance* (which has
|
|
`kind=l2` + all 6 L1s expanded into one IR resource per entry in each
|
|
L1's `resources` array, with `ref:` strings on the consumer inputs).
|
|
For a depth-1 thin-composition, the L2 root module **IS** the union of
|
|
the L1 resources — no separate `module "l1_x" { source = "..." }`
|
|
blocks. The existing adapter `TYPE_MAP` + `INPUT_MAP` + `OUTPUT_MAP`
|
|
tables handle every IR type. `ref:<id>.<output>` inputs are translated
|
|
to `${<tf_type>.<id>.<attr>}` (attribute mapped through `OUTPUT_MAP`
|
|
for the referenced resource's type). The `relationships` array records
|
|
the parent composition tree; ordering is implicit in the resource list.
|
|
|
|
v1.3+ may emit real `module "l1_x" { source = "..." }` blocks once L1s
|
|
are published Terraform modules rather than inline resources.
|
|
|
|
## Versioning (W3.D)
|
|
|
|
`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. |