gatewayd: config, [approvals] users and socket

Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
2026-09-24 04:28:26 -07:00
parent e0560ab996
commit b45ca14c14
4 changed files with 118 additions and 5 deletions
+40
View File
@@ -17,6 +17,18 @@ pub struct Config {
pub paths: Paths,
#[serde(default)]
pub limits: Limits,
#[serde(default)]
pub approvals: ApprovalsConfig,
}
/// `[approvals]`: who may answer approvals, and where `brokerd` brings them.
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Default)]
#[serde(deny_unknown_fields, default)]
pub struct ApprovalsConfig {
/// Mattermost user ids; empty means everyone in `[allow] users`.
pub users: Vec<String>,
/// Empty: `<home>/run/gateway/gateway.sock`.
pub socket: PathBuf,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
@@ -184,6 +196,13 @@ impl Config {
));
}
}
for id in &self.approvals.users {
if !self.allow.users.contains(id) {
return Some(format!(
"[approvals] {id:?} is not in [allow] users: an approver who is not heard could never answer"
));
}
}
if self.limits.queue == 0 {
return Some("[limits] queue must be at least 1".to_string());
}
@@ -221,6 +240,27 @@ impl Config {
self.loop_.socket.clone()
}
/// Who may answer approvals: `[approvals] users`, or `[allow] users` when that is empty.
pub fn approvers(&self) -> &[String] {
if self.approvals.users.is_empty() {
return &self.allow.users;
}
&self.approvals.users
}
/// The first approver, or `None` when there are none.
pub fn first_approver(&self) -> Option<&str> {
self.approvers().first().map(String::as_str)
}
/// `gateway.sock`: `[approvals] socket`, or `<home>/run/gateway/gateway.sock` when empty.
pub fn gateway_socket(&self) -> PathBuf {
if self.approvals.socket.as_os_str().is_empty() {
return self.paths.home.join("run/gateway/gateway.sock");
}
self.approvals.socket.clone()
}
pub fn state_path(&self) -> PathBuf {
// <home>/gateway/state.json.
self.paths.home.join("gateway/state.json")