Picker review fixes: validate stream_id on stop; accurate offline + no-system copy

- POST /discord/nodes/{id}/streams/stop: stream_id must be guild:channel
  snowflakes, so a malformed id is a 422 instead of a Firestore path error.
- Offline footer said channels resume on reconnect; ad-hoc ones stop once
  the node is gone past the lease grace (reconcile_once). Say so.
- Picker: say why Start is disabled when the node has no system.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Logan Cusano
2026-10-04 21:36:30 -04:00
co-authored by Claude Opus 5.5
parent 2457d2d734
commit d2437e3a0b
3 changed files with 19 additions and 2 deletions
+3 -1
View File
@@ -274,7 +274,9 @@ async def start_node_stream(node_id: str, body: NodeStreamStart, decoded: dict =
class NodeStreamStop(BaseModel):
stream_id: Optional[str] = None
# guild:channel snowflakes (leases.stream_id_for). Validated so a malformed
# id (e.g. one with "/") is a 422, not a Firestore path error / 500.
stream_id: Optional[str] = Field(None, pattern=r"^[0-9]{1,25}:[0-9]{1,25}$")
@router.post("/nodes/{node_id}/streams/stop")
@@ -205,3 +205,13 @@ def test_legacy_raw_id_join_refuses_other_orgs_server(fs):
with pytest.raises(HTTPException) as e:
run(nodes_router.send_command("n1", cmd, ADMIN))
assert e.value.status_code == 404
def test_stop_rejects_malformed_stream_id():
# "a/b" would otherwise reach Firestore as a document path and 500.
from pydantic import ValidationError
for bad in ("100/1001", "../x", "100:1001/extra", ""):
with pytest.raises(ValidationError):
web.NodeStreamStop(stream_id=bad)
assert web.NodeStreamStop(stream_id="100:1001").stream_id == "100:1001"
assert web.NodeStreamStop().stream_id is None