Skip to main content

agentmux_srv/backend/agent_session/
zone_naming.rs

1// Copyright 2026, AgentMux Corp.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Zone-name validation + builders for agent session zones.
5
6/// Returns true if `s` matches `[A-Za-z0-9_-]+`. Rejects empty.
7///
8/// We're embedding `definition_id` into a zone name (a string the
9/// frontend can supply via RPC), so anything outside the safe set would
10/// let an attacker write/read arbitrary zones. UUIDs (the production
11/// definition_id shape) are a strict subset of this character class.
12pub fn is_valid_definition_id(s: &str) -> bool {
13    if s.is_empty() {
14        return false;
15    }
16    s.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
17}
18
19/// `agent:<definition_id>:current`. Panics in debug if `definition_id`
20/// is invalid; callers should check `is_valid_definition_id` first (or use
21/// `validate_and_current`) in release.
22pub fn agent_current_zone(definition_id: &str) -> String {
23    debug_assert!(
24        is_valid_definition_id(definition_id),
25        "agent_current_zone: invalid definition_id"
26    );
27    format!("agent:{}:current", definition_id)
28}
29
30/// `agent:<definition_id>:archive:<ts_ms>`.
31pub fn agent_archive_zone(definition_id: &str, ts_ms: u64) -> String {
32    debug_assert!(
33        is_valid_definition_id(definition_id),
34        "agent_archive_zone: invalid definition_id"
35    );
36    format!("agent:{}:archive:{}", definition_id, ts_ms)
37}
38
39/// Convenience: validate + build the current-zone string. Returns
40/// `Err` with a stable error prefix on bad input so RPC callers see a
41/// consistent message.
42pub fn validate_and_current(definition_id: &str) -> Result<String, String> {
43    if !is_valid_definition_id(definition_id) {
44        return Err(format!(
45            "INVALID_DEFINITION_ID: must match [A-Za-z0-9_-]+, got {:?}",
46            definition_id
47        ));
48    }
49    Ok(agent_current_zone(definition_id))
50}