refactor(maestro): share cookie name + extraction across CLI and registry (NAP-273 F)
ci / rust (push) Successful in 6m45s
ci / rust (push) Successful in 6m45s
Promote `COOKIE_NAME` and a robust `extract_cookie` (iterates every `;`-pair, so it works on both `Cookie:` and `Set-Cookie:` headers regardless of position) into `maestro-protocol`. The registry re-exports them; the CLI drops its weaker `extract_cookie_value` (which only inspected the first pair) and its duplicate `COOKIE_NAME`. Both ends of the wire now agree on one definition. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -463,6 +463,29 @@ pub struct JwtClaims {
|
||||
/// secret (NAP-266).
|
||||
pub const REGISTRY_ISSUER: &str = "maestro-registry";
|
||||
|
||||
/// Name of the auth cookie the registry sets and the CLI persists. Defined
|
||||
/// once here so both ends of the wire agree (NAP-273).
|
||||
pub const COOKIE_NAME: &str = "maestro_session";
|
||||
|
||||
/// Find a named cookie's value inside a `Cookie:` / `Set-Cookie:` header value.
|
||||
///
|
||||
/// Iterates every `;`-separated `name=value` pair, so it works whether the
|
||||
/// target pair is first or buried among other cookies or `Set-Cookie`
|
||||
/// attributes (`HttpOnly`, `Path=/`, …). Returns the first match, or `None`.
|
||||
/// Shared by the registry's inbound-cookie check and the CLI's `Set-Cookie`
|
||||
/// capture (NAP-273).
|
||||
pub fn extract_cookie<'a>(header_value: &'a str, name: &str) -> Option<&'a str> {
|
||||
for part in header_value.split(';') {
|
||||
let part = part.trim();
|
||||
if let Some((k, v)) = part.split_once('=') {
|
||||
if k.trim() == name {
|
||||
return Some(v.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Pair-scoped attach credential. Issued by the registry inside
|
||||
/// [`AttachCandidates::jwt`]; verified by the target daemon for direct
|
||||
/// transports (T1/T2) and gated by `allow_inbound` after JWT verification.
|
||||
@@ -488,6 +511,20 @@ pub struct PairAttachClaims {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn extract_cookie_finds_named_value_anywhere() {
|
||||
// Cookie: header — pair may be buried among others.
|
||||
let h = "foo=1; maestro_session=abc.def.ghi; bar=2";
|
||||
assert_eq!(extract_cookie(h, COOKIE_NAME), Some("abc.def.ghi"));
|
||||
assert_eq!(extract_cookie(h, "foo"), Some("1"));
|
||||
assert_eq!(extract_cookie(h, "missing"), None);
|
||||
// Set-Cookie: header — cookie first, attributes (no `=` or other keys)
|
||||
// after it must be skipped, not matched.
|
||||
let sc = "maestro_session=xyz; HttpOnly; SameSite=Strict; Path=/; Max-Age=2592000";
|
||||
assert_eq!(extract_cookie(sc, COOKIE_NAME), Some("xyz"));
|
||||
assert_eq!(extract_cookie("other=1; HttpOnly", COOKIE_NAME), None);
|
||||
}
|
||||
|
||||
fn round_trip<T>(value: &T) -> T
|
||||
where
|
||||
T: Serialize + for<'de> Deserialize<'de>,
|
||||
|
||||
Reference in New Issue
Block a user