From c7f02993d00233ade5ed8e46af58d0411ddf0a7a Mon Sep 17 00:00:00 2001 From: iris Date: Tue, 2 Jun 2026 09:23:50 +0200 Subject: [PATCH] chore(#1055): address argus review nits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rename cap-cap-col → cap-col; add CSS rules for .cap-col and .cap-save-col - drop zero-width-space replace in capability header cells (nowrap makes it a no-op) - add Capability::ALL to hive-sh4re; validate incoming cap strings in post_capabilities --- frontend/packages/dashboard/src/dashboard.css | 6 ++++++ frontend/packages/dashboard/src/tabs.js | 4 ++-- hive-c0re/src/dashboard.rs | 6 ++++++ hive-sh4re/src/lib.rs | 8 ++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/frontend/packages/dashboard/src/dashboard.css b/frontend/packages/dashboard/src/dashboard.css index ffd1756b..f6a9bd32 100644 --- a/frontend/packages/dashboard/src/dashboard.css +++ b/frontend/packages/dashboard/src/dashboard.css @@ -2077,6 +2077,12 @@ body.logs-shell { text-align: left !important; min-width: 8em; } +.cap-col { + min-width: 5em; +} +.cap-save-col { + min-width: 4em; +} .cap-agent-name { color: var(--fg); font-weight: 600; diff --git a/frontend/packages/dashboard/src/tabs.js b/frontend/packages/dashboard/src/tabs.js index d9c3ca73..a1ecf14f 100644 --- a/frontend/packages/dashboard/src/tabs.js +++ b/frontend/packages/dashboard/src/tabs.js @@ -1221,7 +1221,7 @@ window.marked = marked; const hrow = el('tr'); hrow.append(el('th', { class: 'cap-agent-col' }, 'agent')); for (const c of caps) { - hrow.append(el('th', { class: 'cap-cap-col', title: c }, c.replace(/_/g, '_​'))); + hrow.append(el('th', { class: 'cap-col', title: c }, c)); } hrow.append(el('th', { class: 'cap-save-col' }, '')); thead.append(hrow); @@ -1240,7 +1240,7 @@ window.marked = marked; const checkboxes = []; for (const c of caps) { const checked = assigned.includes(c); - const td = el('td', { class: 'cap-cap-col' }); + const td = el('td', { class: 'cap-col' }); const cb = el('input', { type: 'checkbox', class: 'cap-cb', diff --git a/hive-c0re/src/dashboard.rs b/hive-c0re/src/dashboard.rs index 84f6ffe2..d2af3218 100644 --- a/hive-c0re/src/dashboard.rs +++ b/hive-c0re/src/dashboard.rs @@ -2595,6 +2595,12 @@ async fn post_capabilities( if let Some(reject) = guard_agent_name(&state, &logical).await { return reject; } + let known: Vec<&str> = hive_sh4re::Capability::ALL.iter().map(|c| c.as_str()).collect(); + for cap in &body.caps { + if !known.contains(&cap.as_str()) { + return error_response(&format!("unknown capability: {cap}")); + } + } if let Err(e) = crate::capabilities::set_caps(&logical, &body.caps) { return error_response(&format!("set capabilities for {logical}: {e}")); } diff --git a/hive-sh4re/src/lib.rs b/hive-sh4re/src/lib.rs index d0b53c04..c611093d 100644 --- a/hive-sh4re/src/lib.rs +++ b/hive-sh4re/src/lib.rs @@ -923,6 +923,14 @@ pub enum Capability { } impl Capability { + /// Every known capability in a stable order. Use this to enumerate + /// columns in the permissions UI or validate incoming capability strings. + pub const ALL: &'static [Self] = &[ + Self::ManageRootAgent, + Self::ReadHostJournal, + Self::QueryAgentState, + ]; + /// Canonical `snake_case` name for this capability (matches serde). #[must_use] pub fn as_str(self) -> &'static str {