Watch
0
0
Fork
You've already forked hyperhive
0

describe core/meta as the legacy permission repo; drop stale meta-flake prose

Comments, docs and the hive-c0re README no longer say the hive renders, locks or pushes a meta flake. core/meta is the legacy permission-seed repo that meta::remove_permission_files still commits to; builds come from internal/meta (meta_rev.rs). Docs note that a start of a stale stopped agent can fail until the swarm's update pins the config.
This commit is contained in:
atlas 2026-10-25 15:08:50 +01:00
commit bd54372fcc
9 changed files with 35 additions and 25 deletions

View file

@ -444,7 +444,10 @@ nothing; a rebuild would have no flake to build from either. A hive deploy
alone doesn't rebuild agents. alone doesn't rebuild agents.
A stopped agent gets its rebuild at its next start: the start path upgrades A stopped agent gets its rebuild at its next start: the start path upgrades
the start of a stale, stopped agent to a rebuild followed by the start. the start of a stale, stopped agent to a rebuild followed by the start. In
the window after a config merge, before the swarm's update has pinned the new
config, that rebuild fails with the error that names the agent, and the
agent stays stopped until the update lands and you ask for the start again.
The dashboard surfaces pending config changes per agent: a clickable The dashboard surfaces pending config changes per agent: a clickable
"needs update ↻" badge appears whenever the agent's applied repo has a "needs update ↻" badge appears whenever the agent's applied repo has a

View file

@ -122,10 +122,11 @@ Two things live in the `agent-configs` Forgejo organization:
[config-changes.md § Config changes](../agent-lifecycle/config-changes.md#config-changes)). [config-changes.md § Config changes](../agent-lifecycle/config-changes.md#config-changes)).
hive-c0re pushes nothing to this org; it only reads from it. hive-c0re pushes nothing to this org; it only reads from it.
Repos stay private, so an agent can't read another Repos stay private, so an agent can't read another
agent's config. (Agents remain read-only collaborators on `core/meta`.) agent's config. (Agents remain read-only collaborators on the legacy
`core/meta`, the hive's old permission-seed repo.)
The agent's **persistent meta flake input** is this repo's `main` head, The agent's **persistent meta flake input** is this repo's `main` head,
pinned by sha (`agent-<n>.url = git+<forge>/agent-configs/<n>.git?rev=<sha>`; pinned by sha in `internal/meta` (`agent-<n>.url =
see git+<forge>/agent-configs/<n>.git?rev=<sha>`; see
[config-changes.md § Meta flake](../agent-lifecycle/config-changes.md#meta-flake)). [config-changes.md § Meta flake](../agent-lifecycle/config-changes.md#meta-flake)).
hive-c0re's own git reads of this repo, which resolve the sha, authenticate with the hive's read hive-c0re's own git reads of this repo, which resolve the sha, authenticate with the hive's read
token through `forge::reader_token()` (see token through `forge::reader_token()` (see

View file

@ -41,8 +41,11 @@ to track it:
per-agent sockets. per-agent sockets.
- **`forge/`** — optional Forgejo wiring (`docs/integrations/forge.md`). - **`forge/`** — optional Forgejo wiring (`docs/integrations/forge.md`).
- **`coordinator.rs`** — top-level wiring for `serve`. - **`coordinator.rs`** — top-level wiring for `serve`.
- **`meta.rs`**, **`migrate.rs`** — the meta flake + schema/state - **`meta_rev.rs`** — which `internal/meta` commit an agent builds from, and
migrations. the markers a successful build writes. **`agent_set.rs`** — the files that
follow the agent set (topology, gateway map). **`meta.rs`** — the commit
that removes the legacy permission seed files. **`migrate.rs`** —
schema/state migrations.
- **`matrix.rs`**, **`gateway_nginx.rs`**, **`priv_client.rs`** — - **`matrix.rs`**, **`gateway_nginx.rs`**, **`priv_client.rs`** —
matrix provisioning, gateway vhosts, and the `hive-priv` client matrix provisioning, gateway vhosts, and the `hive-priv` client
respectively. respectively.

View file

@ -1,5 +1,6 @@
//! Optional Forgejo wiring — the `core/meta` repo and meta read-access //! Optional Forgejo wiring — the legacy `core/meta` repo (the hive's old
//! grants. Those writes, as `core`, run only beside a local `hive-forge` //! permission-seed repo, which `meta::remove_permission_files` still commits
//! to) and its 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. //! 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 //! The swarm-wide orgs, teams and repos, and each agent's read grant on
//! `internal/docs`, are swarm-controller's. Full design: //! `internal/docs`, are swarm-controller's. Full design:
@ -215,8 +216,8 @@ where
.map_err(|_| anyhow::anyhow!("{op}: no answer from the forge within {API_TIMEOUT:?}")) .map_err(|_| anyhow::anyhow!("{op}: no answer from the forge within {API_TIMEOUT:?}"))
} }
/// Per-agent forge sync: grant read access to `core/meta`, and wire the /// Per-agent forge sync: grant read access to the legacy `core/meta`, and wire
/// `meta` remote in its proposed repo. All operations are idempotent; /// the `meta` remote in its proposed repo. All operations are idempotent;
/// failures are logged as warnings but don't abort the caller. /// failures are logged as warnings but don't abort the caller.
/// ///
/// `core_token` is `core_token()` — passed in so callers that already /// `core_token` is `core_token()` — passed in so callers that already
@ -234,8 +235,9 @@ pub async fn sync_agent(name: &str, core_token: Option<&str>) -> bool {
// swarm-controller's; this hive creates none of them and pushes nothing // swarm-controller's; this hive creates none of them and pushes nothing
// to the repo. // to the repo.
let mut ok = true; let mut ok = true;
// Grant read-only access to core/meta and wire the `meta` remote // Grant read-only access to the legacy core/meta and wire the `meta`
// into the proposed repo so agents can fetch their deployment context. // remote into the proposed repo. Agents build from `internal/meta`, not
// from this repo.
if let Some(token) = core_token if let Some(token) = core_token
&& let Err(e) = meta_read_access(name, token).await && let Err(e) = meta_read_access(name, token).await
{ {
@ -249,7 +251,7 @@ pub async fn sync_agent(name: &str, core_token: Option<&str>) -> bool {
ok ok
} }
/// The `core_token.is_some()` half of [`ensure_all`]: the meta repo, the /// The `core_token.is_some()` half of [`ensure_all`]: the legacy meta repo, the
/// core avatar, and removing this hive's own config-PR hook — /// core avatar, and removing this hive's own config-PR hook —
/// every step that needs an authenticated forge client. The swarm-wide /// every step that needs an authenticated forge client. The swarm-wide
/// objects (orgs, the `operators` team, mirrors, `internal/docs`, /// objects (orgs, the `operators` team, mirrors, `internal/docs`,
@ -258,9 +260,9 @@ pub async fn sync_agent(name: &str, core_token: Option<&str>) -> bool {
/// `ensure_all` under clippy's function-length limit; not meant to be called /// `ensure_all` under clippy's function-length limit; not meant to be called
/// from anywhere else. /// from anywhere else.
async fn ensure_all_orgs_and_repos(token: &str) { async fn ensure_all_orgs_and_repos(token: &str) {
// Meta repo lives at core/meta — pushed from git_commit in // The legacy meta repo lives at core/meta. The only push to it is
// meta.rs on every deploy/lock-update. Make sure it exists // `meta::remove_permission_files`' commit; make sure the repo exists
// before the first push hits a 404. // before that push hits a 404.
if let Err(e) = ensure_repo("meta", token).await { if let Err(e) = ensure_repo("meta", token).await {
tracing::warn!(error = ?e, "forge: ensure_repo core/meta failed"); tracing::warn!(error = ?e, "forge: ensure_repo core/meta failed");
crate::warnings::set_boot_warning( crate::warnings::set_boot_warning(
@ -380,7 +382,7 @@ async fn wait_until_ready() -> bool {
} }
/// Sweep the forge at startup: seed the `core` admin user (hive-c0re's own /// Sweep the forge at startup: seed the `core` admin user (hive-c0re's own
/// identity for pushing the meta repo + driving the API) and its token, the /// identity for pushing the legacy meta repo + driving the API) and its token, the
/// `core/meta` repo and the local knowledge clone, then run [`sync_agent`] /// `core/meta` repo and the local knowledge clone, then run [`sync_agent`]
/// over every existing container (manager + sub-agents). Agent accounts, /// over every existing container (manager + sub-agents). Agent accounts,
/// tokens and `agent-configs/<name>` repos are the swarm-controller's, as is /// tokens and `agent-configs/<name>` repos are the swarm-controller's, as is

View file

@ -6,7 +6,7 @@
//! //!
//! `Status` is read-only (fetches forge `main` into a scratch ref, reports //! `Status` is read-only (fetches forge `main` into a scratch ref, reports
//! the divergence). `Apply(Forge)` resets the local applied checkout to //! the divergence). `Apply(Forge)` resets the local applied checkout to
//! forge `main`; the meta flake pins forge `main` itself, not this tree. It //! forge `main`; `internal/meta` pins forge `main` itself, not this tree. It
//! does NOT auto-deploy. `Apply(Local)` is not supported: forge `main` is //! does NOT auto-deploy. `Apply(Local)` is not supported: forge `main` is
//! branch-protected, so it only advances through a config-PR merge. //! branch-protected, so it only advances through a config-PR merge.

View file

@ -89,11 +89,12 @@ pub async fn ensure_repo(name: &str, token: &str) -> Result<()> {
} }
/// Dashboard-warning guard for the meta non-fast-forward condition. /// Dashboard-warning guard for the meta non-fast-forward condition.
/// Held while `core/meta` remote is ahead of our local mirror; cleared /// Held while the `core/meta` remote is ahead of our local mirror; cleared
/// automatically when the next push succeeds. /// automatically when the next push succeeds.
static META_NON_FF_GUARD: Mutex<Option<crate::warnings::WarningGuard>> = Mutex::new(None); static META_NON_FF_GUARD: Mutex<Option<crate::warnings::WarningGuard>> = Mutex::new(None);
/// Push `dir` (the meta repo) to `core/meta` on the local forge. /// Push `dir` (the legacy hive meta repo) to `core/meta` on the local forge.
/// Its one caller is `meta::remove_permission_files`' commit.
/// Best-effort: returns Err which callers log + ignore. No-op when /// Best-effort: returns Err which callers log + ignore. No-op when
/// the core token isn't present yet (forge container not provisioned). /// the core token isn't present yet (forge container not provisioned).
pub async fn push_meta(dir: &Path) -> Result<()> { pub async fn push_meta(dir: &Path) -> Result<()> {
@ -150,7 +151,7 @@ pub async fn push_meta(dir: &Path) -> Result<()> {
} }
/// Grant agent `name` read-only collaborator access to `core/meta` on /// Grant agent `name` read-only collaborator access to `core/meta` on
/// the forge so the agent can clone/fetch the meta flake. Idempotent: /// the forge so the agent can clone/fetch that legacy repo. Idempotent:
/// re-adding an existing collaborator succeeds (Forgejo answers 204 /// re-adding an existing collaborator succeeds (Forgejo answers 204
/// either way). /// either way).
pub async fn meta_read_access(name: &str, core_token: &str) -> Result<()> { pub async fn meta_read_access(name: &str, core_token: &str) -> Result<()> {
@ -168,7 +169,7 @@ pub async fn meta_read_access(name: &str, core_token: &str) -> Result<()> {
/// Add the forge `core/meta.git` URL as the `meta` remote in the /// Add the forge `core/meta.git` URL as the `meta` remote in the
/// agent's proposed config repo so the agent (and the manager) can /// agent's proposed config repo so the agent (and the manager) can
/// fetch the meta flake from the forge. Idempotent: no-op when the /// fetch that legacy repo from the forge. Idempotent: no-op when the
/// remote already points at the right URL, or when the proposed repo /// remote already points at the right URL, or when the proposed repo
/// does not exist yet. No-op when the forge is not running. /// does not exist yet. No-op when the forge is not running.
pub async fn ensure_meta_remote(name: &str) -> Result<()> { pub async fn ensure_meta_remote(name: &str) -> Result<()> {

View file

@ -65,7 +65,7 @@ fn matrix_base() -> Result<&'static str> {
/// ///
/// # Errors /// # Errors
/// When `HYPERHIVE_HIVE_NAME` is unset or empty. That is the same variable /// When `HYPERHIVE_HIVE_NAME` is unset or empty. That is the same variable
/// [`stored_sender_token`] logs in with and `hive-c0re`'s meta flake asserts /// [`stored_sender_token`] logs in with and the swarm meta flake asserts
/// for every hive, so its absence is a broken deployment rather than a /// for every hive, so its absence is a broken deployment rather than a
/// supported one — and there is no safe default to fall back to: the only one /// supported one — and there is no safe default to fall back to: the only one
/// available is the shared account this replaced. /// available is the shared account this replaced.

View file

@ -11,7 +11,7 @@
//! queued node: operator/intent actions update the row synchronously //! queued node: operator/intent actions update the row synchronously
//! at request time, then submit the DAG whose terminal `Reconcile` //! at request time, then submit the DAG whose terminal `Reconcile`
//! reads the fresh value — rapid toggles are last-writer-wins and the //! reads the fresh value — rapid toggles are last-writer-wins and the
//! reconciles converge. Power toggles never commit to the meta repo. //! reconciles converge.
use std::path::Path; use std::path::Path;
use std::sync::Mutex; use std::sync::Mutex;

View file

@ -110,7 +110,7 @@
defaultText = lib.literalMD "`\"path:\${pkgs.path}\"`"; defaultText = lib.literalMD "`\"path:\${pkgs.path}\"`";
description = '' description = ''
Store-path URL of the nixpkgs the swarm builder's check flake Store-path URL of the nixpkgs the swarm builder's check flake
builds on. The generated meta flake does not use it: its `nixpkgs` builds on. The swarm meta flake does not use it: its `nixpkgs`
follows `hyperhive/nixpkgs`. follows `hyperhive/nixpkgs`.
Defaults to `"path:''${pkgs.path}"`, the nixpkgs the host NixOS Defaults to `"path:''${pkgs.path}"`, the nixpkgs the host NixOS