brokerd: recall and memory, decided under built-in grants

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-25 16:41:44 -07:00
committed by kyle
parent 0c8d136c6b
commit fcfd590687
10 changed files with 267 additions and 9 deletions
+29 -5
View File
@@ -26,6 +26,9 @@ pub struct LoadedGrant {
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct GrantSet {
grants: Vec<LoadedGrant>,
/// The built-in grants of the memory tools, which every set from `from_grants` has. They are
/// not the owner's, so `grants` does not list them; matching sees them (`matchable`).
builtin: Vec<LoadedGrant>,
}
impl GrantSet {
@@ -49,17 +52,24 @@ impl GrantSet {
check_grant(grant, &mut problems);
}
if problems.is_empty() {
Ok(GrantSet { grants })
} else {
Err(problems)
if !problems.is_empty() {
return Err(problems);
}
// The built-ins join only a set that passed: an owner's grant for a memory tool is a
// problem above, never a replacement.
let builtin = crate::builtin::grants().map_err(|problem| vec![problem])?;
Ok(GrantSet { grants, builtin })
}
/// The grants in id order.
/// The owner's grants in id order.
pub fn grants(&self) -> &[LoadedGrant] {
&self.grants
}
/// Every grant a call is matched against: the owner's, then the built-ins.
pub fn matchable(&self) -> impl Iterator<Item = &LoadedGrant> {
self.grants.iter().chain(self.builtin.iter())
}
}
/// A file name is a valid grant id when it is 1 to 64 characters of `a-z`, `0-9` and `-`.
@@ -220,7 +230,18 @@ fn check_grant(grant: &LoadedGrant, problems: &mut Vec<GrantProblem>) {
);
}
// Rule 2b: ids starting `builtin-` are the built-in grants'.
if id.starts_with(crate::builtin::RESERVED) {
push(
problems,
file.clone(),
None,
"grant ids starting builtin- are reserved",
);
}
// Rule 3: the tool must be one of the four; an unknown tool skips rule 6 but not the others.
// The memory tools' grants are built in (M5a spec, section 8).
match ToolName::parse(&grant.grant.tool) {
None => push(
problems,
@@ -228,6 +249,9 @@ fn check_grant(grant: &LoadedGrant, problems: &mut Vec<GrantProblem>) {
None,
"unknown tool; only read_file, write_file, shell and http_fetch",
),
Some(tool) if tool.is_memory() => {
push(problems, file.clone(), None, crate::builtin::BUILT_IN)
}
Some(tool) => check_tool_constraints(tool, &file, inner, problems),
}