swarm-controller grants internal/docs read to agents; hives stop doing it
Agent creation gains a GrantDocsRead node (after CreateForgeUser) that adds the agent as a read collaborator on internal/docs, and forge::docs_grant runs a pass over the store's hive-agent-* roster at start and every five minutes that queues the same job for any agent that is not one. The pass only adds; an unreadable roster or forge read changes nothing. hive-c0re drops shared_docs_access, its call in sync_agent, and the SHARED_ORG / SHARED_DOCS_REPO constants only it used.
This commit is contained in:
parent
4e7142ae53
commit
1ca758daa7
7 changed files with 643 additions and 59 deletions
|
|
@ -1,9 +1,9 @@
|
|||
//! Optional Forgejo wiring — the `core/meta` repo, meta read-access
|
||||
//! grants, and each agent's read-only grant on `internal/docs` (the
|
||||
//! swarm-controller creates that repo, with the other swarm-wide orgs,
|
||||
//! teams and repos). Those writes, as `core`, run only beside a local
|
||||
//! `hive-forge` container; reads of the forge go through [`reader_token`] on
|
||||
//! every hive. Full design: `docs/integrations/forge.md`.
|
||||
//! Optional Forgejo wiring — the `core/meta` repo and meta read-access
|
||||
//! grants. Those writes, as `core`, run only beside a local `hive-forge`
|
||||
//! container; reads of the forge go through [`reader_token`] on every hive.
|
||||
//! The swarm-wide orgs, teams and repos, and each agent's read grant on
|
||||
//! `internal/docs`, are swarm-controller's. Full design:
|
||||
//! `docs/integrations/forge.md`.
|
||||
|
||||
mod pr_comment;
|
||||
mod reader;
|
||||
|
|
@ -16,7 +16,7 @@ pub use reader::reader_token;
|
|||
pub use reconcile::{fetch_forge_main, reconcile_config_apply, reconcile_config_status};
|
||||
pub use repos::{
|
||||
clone_config_into_proposed, ensure_meta_remote, ensure_repo, fast_forward_applied_main,
|
||||
fetch_config_main_into_applied, meta_read_access, push_meta, shared_docs_access,
|
||||
fetch_config_main_into_applied, meta_read_access, push_meta,
|
||||
};
|
||||
pub use users::core_token;
|
||||
|
||||
|
|
@ -100,16 +100,6 @@ fn basic_auth_header(login: &str, token: &str) -> String {
|
|||
/// deploys through swarm-controller. The repos remain private, so an agent
|
||||
/// still can't reach *another* agent's config. hive-c0re only reads from it.
|
||||
pub(crate) const CONFIG_ORG: &str = "agent-configs";
|
||||
/// Forgejo org hosting the operator-curated shared docs/skills repo
|
||||
/// that every agent gets read-only access to. Agents use it as a
|
||||
/// common reference without the operator having to bake content into
|
||||
/// the system prompt or rely on `/shared`. Only the manager + operator
|
||||
/// (i.e. `core` user) can push. The swarm-controller creates the org
|
||||
/// and the repo; this hive only grants its agents read access.
|
||||
const SHARED_ORG: &str = "internal";
|
||||
/// The shared docs repo inside `SHARED_ORG`. Cloneable by every agent
|
||||
/// at `{forge_http_base()}/internal/docs.git`.
|
||||
const SHARED_DOCS_REPO: &str = "docs";
|
||||
|
||||
/// Leak `s` to get a `&'static str` warning `kind` for the small, bounded
|
||||
/// set of boot warnings in [`ensure_all`] keyed by a runtime name (at
|
||||
|
|
@ -219,15 +209,6 @@ pub async fn sync_agent(name: &str, core_token: Option<&str>) -> bool {
|
|||
tracing::warn!(%name, error = ?e, "forge: ensure_meta_remote failed");
|
||||
ok = false;
|
||||
}
|
||||
// Grant read-only access to internal/docs so the agent can clone
|
||||
// the operator-curated shared skills/runbook repo. Best-effort.
|
||||
if let Some(token) = core_token
|
||||
&& let Err(e) = shared_docs_access(name, token).await
|
||||
{
|
||||
tracing::warn!(%name, error = ?e, "forge: shared_docs_access failed");
|
||||
ok = false;
|
||||
}
|
||||
// internal/knowledge is public — no per-agent collaborator grant needed.
|
||||
ok
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! Repo + org plumbing on the local Forgejo: the meta + shared-docs +
|
||||
//! knowledge repos, meta mirroring (`push_meta`), collaborator grants,
|
||||
//! pull-mirrors, and branch-protection rules. The typed API-client
|
||||
//! constructor + org-name constants live in the module root (`super`).
|
||||
//! Repo + org plumbing on the local Forgejo: the meta + knowledge repos,
|
||||
//! meta mirroring (`push_meta`), collaborator grants, pull-mirrors, and
|
||||
//! branch-protection rules. The typed API-client constructor + org-name
|
||||
//! constants live in the module root (`super`).
|
||||
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
|
|
@ -16,8 +16,8 @@ use reqwest::StatusCode;
|
|||
use crate::coordinator::Coordinator;
|
||||
|
||||
use super::{
|
||||
CONFIG_ORG, SHARED_DOCS_REPO, SHARED_ORG, api, core_auth_header, core_token, forge_git_url,
|
||||
forge_http_base, is_present, reader_token,
|
||||
CONFIG_ORG, api, core_auth_header, core_token, forge_git_url, forge_http_base, is_present,
|
||||
reader_token,
|
||||
};
|
||||
|
||||
/// Creation options for an empty repo defaulting to `main`.
|
||||
|
|
@ -144,23 +144,6 @@ pub async fn push_meta(dir: &Path) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Grant agent `name` read-only collaborator access to `internal/docs`.
|
||||
/// Idempotent: re-adding an existing collaborator succeeds (Forgejo
|
||||
/// answers 204 either way). Mirrors `meta_read_access` so agents can
|
||||
/// clone the shared docs repo without authentication hassle.
|
||||
pub async fn shared_docs_access(name: &str, core_token: &str) -> Result<()> {
|
||||
add_collaborator(
|
||||
SHARED_ORG,
|
||||
SHARED_DOCS_REPO,
|
||||
name,
|
||||
AddCollaboratorOptionPermission::Read,
|
||||
core_token,
|
||||
)
|
||||
.await?;
|
||||
tracing::info!(%name, "forge: granted shared-docs read access");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Grant agent `name` read-only collaborator access to `core/meta` on
|
||||
/// the forge so the agent can clone/fetch the meta flake. Idempotent:
|
||||
/// re-adding an existing collaborator succeeds (Forgejo answers 204
|
||||
|
|
|
|||
Loading…
Reference in a new issue