fix(fleet): enforce exact comms authority (#787)
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful

This commit was merged in pull request #787.
This commit is contained in:
2026-07-16 00:32:23 +00:00
parent c1aecfabe9
commit adad486b6f
22 changed files with 3534 additions and 859 deletions

View File

@@ -61,25 +61,33 @@ MOSAIC_HOME="$T5" MOSAIC_INSTALL_MODE=bogus MOSAIC_SYNC_ONLY=1 bash "$INSTALL" >
chk "F5 failure: invalid mode rejected (nonzero exit)" "[ $rc -ne 0 ]"
chk "F5 failure: SOUL + credentials intact" "grep -q orig '$T5/SOUL.md' && grep -q keepme '$T5/credentials/c.json'"
# F6 — keep-mode re-seed (the `mosaic update` path) MUST NOT wipe user fleet data.
# Regression for the roster-loss bug: fleet/ was not in PRESERVE_PATHS.
# F6 — keep-mode re-seed (the `mosaic update` path) MUST preserve only the
# exact user-owned roster paths while refreshing framework-owned schema/examples.
T6=$(mktemp -d); mkdir -p "$T6/fleet/examples" "$T6/fleet/run" "$T6/fleet/agents"
printf '# persona\n' > "$T6/SOUL.md" # makes it a recognized existing install (→ keep mode)
printf 'version: 1\nagents:\n - name: coder0\n' > "$T6/fleet/roster.yaml"
printf 'version: 1\nagents:\n - name: custom\n' > "$T6/fleet/my-fleet.yaml"
printf '{"version":1,"agents":[{"name":"json-user"}]}\n' > "$T6/fleet/roster.json"
printf 'version: 1\nagents:\n - name: not-active-roster\n' > "$T6/fleet/my-fleet.yaml"
printf 'ts=x\n' > "$T6/fleet/run/coder0.hb"
printf 'MOSAIC_AGENT_NAME=coder0\n' > "$T6/fleet/agents/coder0.env"
printf '# stale preset\n' > "$T6/fleet/examples/general.yaml"
printf '{"stale":true}\n' > "$T6/fleet/roster.schema.json"
E6=$(mktemp -d)
cp "$T6/fleet/roster.yaml" "$E6/roster-yaml.expected"
cp "$T6/fleet/roster.json" "$E6/roster-json.expected"
cp "$T6/fleet/run/coder0.hb" "$E6/run.expected"
cp "$T6/fleet/agents/coder0.env" "$E6/agent.expected"
echo 3 > "$T6/.framework-version"
run "$T6" keep
chk "F6 reseed: user roster.yaml SURVIVES keep-mode sync" "grep -q coder0 '$T6/fleet/roster.yaml'"
chk "F6 reseed: other user fleet/*.yaml survives (glob)" "[ -f '$T6/fleet/my-fleet.yaml' ]"
chk "F6 reseed: per-agent env (fleet/agents) survives" "[ -f '$T6/fleet/agents/coder0.env' ]"
chk "F6 reseed: heartbeat run dir (fleet/run) survives" "[ -f '$T6/fleet/run/coder0.hb' ]"
chk "F6 reseed: framework examples ARE refreshed (not preserved stale)" "grep -q orchestrator '$T6/fleet/examples/general.yaml'"
chk "F6 reseed: framework roster.schema.json seeded" "[ -f '$T6/fleet/roster.schema.json' ]"
chk "F6 reseed: exact roster.yaml bytes survive keep-mode sync" "cmp -s '$T6/fleet/roster.yaml' '$E6/roster-yaml.expected'"
chk "F6 reseed: exact roster.json bytes survive keep-mode sync" "cmp -s '$T6/fleet/roster.json' '$E6/roster-json.expected'"
chk "F6 reseed: unrelated fleet YAML is not preserved" "[ ! -f '$T6/fleet/my-fleet.yaml' ]"
chk "F6 reseed: per-agent env bytes survive" "cmp -s '$T6/fleet/agents/coder0.env' '$E6/agent.expected'"
chk "F6 reseed: heartbeat bytes survive" "cmp -s '$T6/fleet/run/coder0.hb' '$E6/run.expected'"
chk "F6 reseed: framework examples are refreshed" "grep -q orchestrator '$T6/fleet/examples/general.yaml'"
chk "F6 reseed: framework roster schema is refreshed" "cmp -s '$T6/fleet/roster.schema.json' '$FW/fleet/roster.schema.json'"
rm -rf "$T1" "$T2" "$T3" "$T4" "$T5" "$T6"
rm -rf "$T1" "$T2" "$T3" "$T4" "$T5" "$T6" "$E6"
echo
echo "RESULT: $pass passed, $fail failed"
[ "$fail" -eq 0 ]

View File

@@ -0,0 +1,110 @@
#!/usr/bin/env python3
"""Regression checks for connector-kind-conditional fleet roster schema."""
import json
import sys
from pathlib import Path
from jsonschema import Draft202012Validator
schema_path = Path(__file__).resolve().parents[3] / "fleet" / "roster.schema.json"
schema = json.loads(schema_path.read_text(encoding="utf-8"))
validator = Draft202012Validator(schema)
base = {
"version": 1,
"transport": "tmux",
"agents": [{"name": "orchestrator", "runtime": "pi"}],
}
valid = [
{"kind": "tmux"},
{"kind": "discord", "discord": {"channel_id": "123"}},
{
"kind": "matrix",
"matrix": {
"homeserver_url": "https://matrix.example",
"user_id": "@mosaic:example",
"room_id": "!room:example",
},
},
]
invalid = [
{"kind": "tmux", "discord": {"channel_id": "123"}},
{"kind": "tmux", "matrix": {}},
{"kind": "discord"},
{"kind": "discord", "matrix": {}},
{
"kind": "discord",
"discord": {"channel_id": "123"},
"matrix": {
"homeserver_url": "https://matrix.example",
"user_id": "@mosaic:example",
"room_id": "!room:example",
},
},
{"kind": "matrix"},
{"kind": "matrix", "discord": {"channel_id": "123"}},
{"kind": "discord", "discord": {"channel_id": ""}},
{"kind": "discord", "discord": {"channel_id": " "}},
{
"kind": "matrix",
"matrix": {
"homeserver_url": "",
"user_id": "@mosaic:example",
"room_id": "!room:example",
},
},
{
"kind": "matrix",
"matrix": {
"homeserver_url": "\t",
"user_id": "@mosaic:example",
"room_id": "!room:example",
},
},
{
"kind": "matrix",
"matrix": {
"homeserver_url": "https://matrix.example",
"user_id": "",
"room_id": "!room:example",
},
},
{
"kind": "matrix",
"matrix": {
"homeserver_url": "https://matrix.example",
"user_id": " ",
"room_id": "!room:example",
},
},
{
"kind": "matrix",
"matrix": {
"homeserver_url": "https://matrix.example",
"user_id": "@mosaic:example",
"room_id": "",
},
},
{
"kind": "matrix",
"matrix": {
"homeserver_url": "https://matrix.example",
"user_id": "@mosaic:example",
"room_id": "\n",
},
},
]
for connector in valid:
errors = list(validator.iter_errors({**base, "connector": connector}))
if errors:
print(f"expected valid connector {connector}: {errors}", file=sys.stderr)
raise SystemExit(1)
for connector in invalid:
if not list(validator.iter_errors({**base, "connector": connector})):
print(f"expected invalid connector: {connector}", file=sys.stderr)
raise SystemExit(1)
print("connector schema regression: PASS")