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:
parent
633139069f
commit
bd54372fcc
9 changed files with 35 additions and 25 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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<()> {
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue