fix: add transition: scopes to owner-level delegates

Signed-off-by: Trezy <tre@trezy.com>
This commit is contained in:
Trezy
2026-08-28 20:28:54 +00:00
committed by Tangled
parent 97224551bf
commit dc2f924130
2 changed files with 45 additions and 6 deletions
+34 -5
View File
@@ -14,8 +14,10 @@ pub struct ScopePreset {
pub scopes: &'static str,
}
pub const OWNER_FULL_SCOPES: &str =
"atproto repo:* blob:*/* rpc:* identity:* account:*?action=manage";
pub const OWNER_FULL_SCOPES: &str = concat!(
"atproto repo:* blob:*/* rpc:* identity:* account:*?action=manage ",
"transition:generic transition:chat.bsky transition:email"
);
pub const ADMIN_FULL_SCOPES: &str = "atproto repo:* blob:*/* rpc:* account:*?action=manage";
@@ -341,6 +343,9 @@ mod tests {
("rpc", "rpc:app.bsky.actor.getProfile?aud=*"),
("account", "account:email?action=manage"),
("identity", "identity:handle"),
("transition:generic", "transition:generic"),
("transition:chat.bsky", "transition:chat.bsky"),
("transition:email", "transition:email"),
];
/// The taxonomy label a scope type must be represented by, or `None` for scope types
@@ -352,10 +357,10 @@ mod tests {
ParsedScope::Rpc(_) => Some("rpc"),
ParsedScope::Account(_) => Some("account"),
ParsedScope::Identity(_) => Some("identity"),
ParsedScope::TransitionGeneric => Some("transition:generic"),
ParsedScope::TransitionChat => Some("transition:chat.bsky"),
ParsedScope::TransitionEmail => Some("transition:email"),
ParsedScope::Atproto => None,
ParsedScope::TransitionGeneric
| ParsedScope::TransitionChat
| ParsedScope::TransitionEmail => None,
ParsedScope::Include(_) => None,
ParsedScope::Unknown(_) => None,
}
@@ -437,3 +442,27 @@ mod tests {
);
}
}
#[cfg(test)]
mod scratch_transition_probe {
use super::*;
#[test]
fn probe() {
let g = "atproto repo:* blob:*/* rpc:* identity:* account:*?action=manage transition:generic transition:chat transition:email";
println!(
"validate mixed grant: {:?}",
ValidatedDelegationScope::new(g).is_ok()
);
for s in ["transition:generic", "transition:chat", "transition:email"] {
println!(" {s} -> {:?}", grant_coverage(g, s));
println!(
" {s} under CURRENT owner -> {:?}",
grant_coverage(OWNER_FULL_SCOPES, s)
);
}
println!(
"intersect(transition:generic, mixed grant) = {:?}",
intersect_scopes("atproto transition:generic", g)
);
}
}
+11 -1
View File
@@ -534,7 +534,13 @@ fn migrate_delegation_preset_scopes(metastore: &tranquil_store::metastore::Metas
const V2_LEGACY_EDITOR: &str =
"atproto repo:*?action=create repo:*?action=update repo:*?action=delete blob:*/*";
let passes: [(&str, &[(&str, &str)]); 2] = [
// v3 adds the `transition:` scopes to the owner preset
// Without them an owner-level delegation withholds all transition scopes
const V3_MARKER: &str = "migration:delegation_preset_scopes_v3";
const V3_LEGACY_OWNER: &str =
"atproto repo:* blob:*/* rpc:* identity:* account:*?action=manage";
let passes: [(&str, &[(&str, &str)]); 3] = [
(
V1_MARKER,
&[
@@ -550,6 +556,10 @@ fn migrate_delegation_preset_scopes(metastore: &tranquil_store::metastore::Metas
(V2_LEGACY_EDITOR, crate::delegation::EDITOR_FULL_SCOPES),
],
),
(
V3_MARKER,
&[(V3_LEGACY_OWNER, crate::delegation::OWNER_FULL_SCOPES)],
),
];
let infra = metastore.infra_ops();