feat: connectivity redesign phase 5 — one container per connection instance
Unit Tests / test (push) Successful in 13m5s

instanceable rendering, per-instance up/down on create/delete,
store-service-installed gate, per-instance health

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 22:56:31 -04:00
parent d39c091cec
commit 603225694c
8 changed files with 688 additions and 8 deletions
+16 -1
View File
@@ -33,6 +33,13 @@ _RESERVED_CONTAINER_NAMES = frozenset({
'cell-dnsmasq', 'cell-wireguard', 'cell-chrony',
})
_CONTAINER_NAME_RE = re.compile(r'^cell-[a-z0-9][a-z0-9-]{0,30}$')
# Instanceable services template their container name with the connection's
# short id, e.g. "cell-wgext-${INSTANCE_ID}". The literal prefix is validated;
# ${INSTANCE_ID} is substituted at up-time with a hex token that itself matches
# the per-instance naming rules.
_INSTANCEABLE_CONTAINER_NAME_RE = re.compile(
r'^cell-[a-z0-9][a-z0-9-]{0,22}-\$\{INSTANCE_ID\}$'
)
_ENV_VALUE_RE = re.compile(r'^[A-Za-z0-9._@:/+\-]{0,256}$')
_HOOK_BINARY_RE = re.compile(r'^[a-z][a-z0-9_-]{0,31}$')
_CAP_NAME_RE = re.compile(r'^[A-Z_]+$')
@@ -93,7 +100,15 @@ def validate_manifest(manifest: dict) -> tuple:
# container_name structural check
cname = manifest.get('container_name')
if cname is not None:
if not _CONTAINER_NAME_RE.match(cname):
instanceable = bool(manifest.get('instanceable'))
if instanceable:
if not _INSTANCEABLE_CONTAINER_NAME_RE.match(cname):
errors.append(
'instanceable container_name must match '
"^cell-[a-z0-9][a-z0-9-]{0,22}-${INSTANCE_ID}$, "
f'got: {cname!r}'
)
elif not _CONTAINER_NAME_RE.match(cname):
errors.append(
f'container_name must match ^cell-[a-z0-9][a-z0-9-]{{0,30}}$, got: {cname!r}'
)