Mark Phase A complete, document $PORT convention, update next steps
PLATFORM_EVOLUTION.md: mark gaps #2 and #9 as done, Phase A complete, Phase B in progress. Update sequencing and next steps. engineering-standards.md: add Port Assignment and $PORT Convention section documenting how MCP-deployed services receive assigned ports via environment variables. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ from its current manually-wired state to fully declarative deployment.
|
|||||||
It is a living design document — not a spec, not a commitment, but a
|
It is a living design document — not a spec, not a commitment, but a
|
||||||
record of where we are, where we want to be, and what's between.
|
record of where we are, where we want to be, and what's between.
|
||||||
|
|
||||||
Last updated: 2026-03-27
|
Last updated: 2026-03-27 (Phase A complete)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -188,21 +188,19 @@ mcdsl is already properly versioned and released:
|
|||||||
- Docker builds use standard `go mod download`
|
- Docker builds use standard `go mod download`
|
||||||
- `uses_mcdsl` eliminated from service definitions and docs
|
- `uses_mcdsl` eliminated from service definitions and docs
|
||||||
|
|
||||||
#### 2. MCP Agent: Port Assignment
|
#### 2. MCP Agent: Port Assignment — DONE
|
||||||
|
|
||||||
**Gap**: agent doesn't manage host ports. Service definitions specify
|
Agent allocates host ports automatically at deploy time:
|
||||||
them manually.
|
- Service definitions declare `[[components.routes]]` with name, port,
|
||||||
|
mode, and optional hostname
|
||||||
**Work**:
|
- Agent picks random free ports (10000-60000, availability check,
|
||||||
- Agent picks free host ports at deploy time (random + availability
|
mutex-serialized), records assignments in `component_routes` table
|
||||||
check).
|
- Containers receive `$PORT` / `$PORT_<NAME>` env vars
|
||||||
- Agent records assignments in its registry.
|
- Backward compatible: old-style `ports` strings still work unchanged
|
||||||
- Agent passes `$PORT` / `$PORT_<NAME>` to containers.
|
- Proto: `RouteSpec` message, `routes` + `env` fields on `ComponentSpec`
|
||||||
- Agent releases ports on container stop/removal.
|
- Servicedef: `RouteDef` parsing and validation from TOML
|
||||||
- New service definition format drops `ports` field, adds
|
- Registry: `component_routes` table with `host_port` tracking
|
||||||
`[[components.routes]]`.
|
- Runtime: `Env` field on `ContainerSpec`, `-e` flag generation
|
||||||
|
|
||||||
**Depends on**: nothing (can be developed standalone).
|
|
||||||
|
|
||||||
#### 3. MCP Agent: mc-proxy Route Registration
|
#### 3. MCP Agent: mc-proxy Route Registration
|
||||||
|
|
||||||
@@ -287,19 +285,16 @@ is no API for dynamic record management.
|
|||||||
wrapper, not a full service. This may be the right time to build the
|
wrapper, not a full service. This may be the right time to build the
|
||||||
real MCNS.
|
real MCNS.
|
||||||
|
|
||||||
#### 9. Application $PORT Convention
|
#### 9. Application $PORT Convention — DONE
|
||||||
|
|
||||||
**Gap**: applications read listen addresses from their config files.
|
mcdsl v1.1.0 adds `$PORT` and `$PORT_GRPC` env var support:
|
||||||
They don't check `$PORT` env vars.
|
- `config.Load` checks `$PORT` → overrides `Server.ListenAddr`
|
||||||
|
- `config.Load` checks `$PORT_GRPC` → overrides `Server.GRPCAddr`
|
||||||
**Work**:
|
- Takes precedence over TOML and generic env overrides
|
||||||
- Each service's config layer checks `$PORT` / `$PORT_<NAME>` and
|
(`$MCR_SERVER_LISTEN_ADDR`) — agent-assigned ports are authoritative
|
||||||
overrides the configured listen address if set.
|
- Handles both `config.Base` embedding (MCR, MCNS, MCAT) and direct
|
||||||
- This fits naturally into the existing `$SERVICENAME_*` env override
|
`ServerConfig` embedding (Metacrypt) via struct tree walking
|
||||||
convention — it's just one more env var.
|
- MCR, Metacrypt, MCNS upgraded to mcdsl v1.1.0
|
||||||
- Small change per service, but touches every service.
|
|
||||||
|
|
||||||
**Depends on**: nothing (can be done incrementally).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -308,15 +303,15 @@ They don't check `$PORT` env vars.
|
|||||||
The dependencies form a rough order:
|
The dependencies form a rough order:
|
||||||
|
|
||||||
```
|
```
|
||||||
Phase A — Independent groundwork (parallel):
|
Phase A — Independent groundwork: ✓ COMPLETE
|
||||||
#1 mcdsl proper module versioning ✓ DONE
|
#1 mcdsl proper module versioning ✓ DONE
|
||||||
#2 MCP agent port assignment
|
#2 MCP agent port assignment ✓ DONE
|
||||||
#5 mc-proxy route persistence ✓ DONE
|
#5 mc-proxy route persistence ✓ DONE
|
||||||
#9 $PORT convention in applications
|
#9 $PORT convention in applications ✓ DONE
|
||||||
|
|
||||||
Phase B — MCP route registration:
|
Phase B — MCP route registration: ← IN PROGRESS
|
||||||
#3 Agent registers routes with mc-proxy
|
#3 Agent registers routes with mc-proxy
|
||||||
(depends on #2 + #5)
|
(depends on #2 + #5 — both done)
|
||||||
|
|
||||||
Phase C — Automated TLS:
|
Phase C — Automated TLS:
|
||||||
#7 Metacrypt cert issuance policy
|
#7 Metacrypt cert issuance policy
|
||||||
@@ -329,31 +324,24 @@ Phase D — DNS:
|
|||||||
(depends on #8)
|
(depends on #8)
|
||||||
```
|
```
|
||||||
|
|
||||||
Phase A is partially complete. mcdsl (#1) and mc-proxy route
|
**Phase A is complete.** Services can be deployed with agent-assigned
|
||||||
persistence (#5) are done. The remaining Phase A work (#2, #9) can
|
ports and `$PORT` env vars. mc-proxy routes must still be registered
|
||||||
proceed in parallel.
|
manually via `mcproxyctl` or the gRPC API.
|
||||||
|
|
||||||
After Phase A, services can be deployed with agent-assigned ports
|
**Phase B is next.** The agent will call mc-proxy's gRPC API to
|
||||||
(manually registered in mc-proxy).
|
register/remove routes automatically during deploy/stop. This
|
||||||
|
eliminates the last manual networking step — no more `mcproxyctl`
|
||||||
|
or TOML editing.
|
||||||
|
|
||||||
After Phase B, the manual steps are: cert provisioning and DNS. This
|
After Phase C, cert provisioning is automatic. After Phase D,
|
||||||
is the biggest quality-of-life improvement — no more manual port
|
`mcp deploy` is fully declarative.
|
||||||
picking or mc-proxy TOML editing.
|
|
||||||
|
|
||||||
After Phase C, only DNS remains manual.
|
|
||||||
|
|
||||||
After Phase D, `mcp deploy` is fully declarative.
|
|
||||||
|
|
||||||
Each phase is independently useful and deployable.
|
|
||||||
|
|
||||||
### Immediate Next Steps
|
### Immediate Next Steps
|
||||||
|
|
||||||
1. **MCP agent port assignment (#2)** — new service definition parser,
|
1. **Phase B: MCP agent route registration (#3)** — agent connects to
|
||||||
port allocation, `$PORT_*` injection. With #5 done, this is the
|
mc-proxy via Unix socket, registers routes on deploy, removes on
|
||||||
remaining blocker for Phase B.
|
stop. TLS certs are pre-provisioned (Phase C automates this later).
|
||||||
2. **$PORT convention (#9)** — small per-service config change. Can
|
2. **mcdoc implementation** — fully designed, no platform evolution
|
||||||
start incrementally now, but only useful once #2 is deployed.
|
|
||||||
3. **mcdoc implementation** — fully designed, no platform evolution
|
|
||||||
dependency. Deployable with a manually assigned port today.
|
dependency. Deployable with a manually assigned port today.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -810,6 +810,28 @@ registry. If a tag is missing and the source tree is available, it
|
|||||||
builds and pushes automatically. If the source tree is not available,
|
builds and pushes automatically. If the source tree is not available,
|
||||||
it fails with a clear error directing the operator to build first.
|
it fails with a clear error directing the operator to build first.
|
||||||
|
|
||||||
|
### Port Assignment and $PORT Convention
|
||||||
|
|
||||||
|
When deployed via MCP, the agent assigns host ports automatically and
|
||||||
|
passes them to containers via environment variables:
|
||||||
|
|
||||||
|
| Env var | When set | Example |
|
||||||
|
|---------|----------|---------|
|
||||||
|
| `$PORT` | Component has a single route | `PORT=8913` |
|
||||||
|
| `$PORT_<NAME>` | Component has multiple routes | `PORT_REST=8913`, `PORT_GRPC=9217` |
|
||||||
|
|
||||||
|
Route names come from the `name` field in `[[components.routes]]`.
|
||||||
|
Names are uppercased for the env var (e.g., `name = "rest"` →
|
||||||
|
`$PORT_REST`).
|
||||||
|
|
||||||
|
Services using mcdsl v1.1.0+ get this automatically — `config.Load`
|
||||||
|
checks `$PORT` and `$PORT_GRPC` and overrides `Server.ListenAddr` and
|
||||||
|
`Server.GRPCAddr` respectively. These take precedence over TOML values
|
||||||
|
and generic env overrides (`$MCR_SERVER_LISTEN_ADDR`).
|
||||||
|
|
||||||
|
Services not using mcdsl must check `$PORT` manually in their config
|
||||||
|
loading.
|
||||||
|
|
||||||
### TLS
|
### TLS
|
||||||
|
|
||||||
- **Minimum TLS version: 1.3.** No exceptions, no fallback cipher suites.
|
- **Minimum TLS version: 1.3.** No exceptions, no fallback cipher suites.
|
||||||
|
|||||||
Reference in New Issue
Block a user