1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! CTL-002 (E2E report) — cellctl detects UUID-vs-name and routes to
//! the right server-side path.
//!
//! Bug shape: `cellctl describe formation <name>` previously assembled
//! `/v1/formations/<name>` and got a 400 from the server's UUID
//! extractor. The fix is a client-side shape probe:
//!
//! * UUID-parseable input → `/v1/formations/{uuid}` (existing route)
//! * everything else → `/v1/formations/by-name/{name}` (new route)
//!
//! This is the public-API pin for that shape probe. The hot path the
//! E2E report exercises is `describe formation <name>` and
//! `delete formation <name>`; both share the same routing helper
//! `cellos_ctl::client::formation_path` so we test it once at the
//! boundary.
use formation_path;
/// CTL-002 happy path: a kubectl-style name routes to `by-name`. This
/// is the regression the E2E report opened — `describe formation demo`
/// used to assemble `/v1/formations/demo` and hit the 400.
/// CTL-002 compatibility pin: a real UUID still goes to the existing
/// `/v1/formations/{uuid}` route. Existing operator workflows
/// (`cellctl describe formation <uuid>`) MUST NOT regress. This is the
/// "no client breaking changes" property the directive calls out.
/// Case-tolerant probe: `Uuid::parse_str` accepts uppercase per
/// RFC 4122 §3 and so does `axum`'s extractor. Pin that an operator
/// pasting an uppercase UUID still hits the UUID route, not by-name.
/// Names with reserved URL characters (`/`, ` `, etc.) MUST be encoded
/// before they become path segments. Without encoding, a name like
/// `ns/team` would silently truncate to `ns` at the server's router.
/// Garbage that *looks* like a UUID but isn't (wrong length, wrong
/// hyphenation) MUST fall through to the by-name route — the by-name
/// route at the server returns a clean 404, which is the right
/// operator-UX answer ("no such name"). The bug was the 400
/// "UUID parsing failed" leaking through; this pins that it cannot
/// regress.