From 0cbb7db2c0f037b002021221ef01585a25123a6c Mon Sep 17 00:00:00 2001 From: atlas Date: Fri, 25 Sep 2026 02:11:44 +0200 Subject: [PATCH] docs: a first SSO login makes a human's forge account setup.md said Swarm SSO creates the operator's forge account, which was not true until the previous commits. It now says how: sign in to the forge once through authelia, then `swarmctl forge make-admin `. sso.md says what that first login does and why ACCOUNT_LINKING is `login`. README, hivectl.md and forge.md drop `hivectl forge create-user`, and the swarmctl README gains `forge make-admin`. Refs #3782 --- README.md | 10 ++++++---- docs/getting-started/setup.md | 21 +++++++++++++++++++-- docs/integrations/forge.md | 13 ++++++------- docs/swarm/sso.md | 11 ++++++++++- docs/tools/hivectl.md | 26 +++++++------------------- swarmctl/README.md | 14 ++++++++++++++ 6 files changed, 62 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 8b5b5766..b6bb21af 100644 --- a/README.md +++ b/README.md @@ -114,16 +114,18 @@ doesn't go through the broker (built alongside `hive-c0re` when the host module is enabled): ```sh -sudo hivectl forge create-user mara # provisions a forge user -sudo hivectl forge create-user mara --password 'hunter2' # … with a fixed password sudo hivectl matrix create-user mara # provisions a matrix user sudo hivectl matrix create-user mara --password-stdin # … reading one line from stdin ``` For a name that's a managed agent, `hivectl` persists the resulting token to that agent's state dir, the same as the boot sweep does. For a -non-agent name (e.g. the operator's own forge/matrix account), it prints -the token to stdout and writes nothing. +non-agent name (for example the operator's own matrix account), it prints the +token to stdout and writes nothing. + +A human's first SSO login to the forge makes their forge account, not +`hivectl`; `swarmctl forge make-admin ` on the swarm-controller's +host makes it a site admin. ## Build / deploy diff --git a/docs/getting-started/setup.md b/docs/getting-started/setup.md index 22580928..7f0d0b4b 100644 --- a/docs/getting-started/setup.md +++ b/docs/getting-started/setup.md @@ -48,8 +48,9 @@ about ten minutes. `swarmctl agent mint-forge-token ruth` skips the wait for the pass. A hive without a swarm secret store has no path to a forge token for ruth at all. -Swarm SSO creates the human operator's own forge account instead of -a manual `hivectl` step — see _Swarm SSO_ below (`swarmctl user add`). +Swarm SSO creates the human operator's own forge account: the forge +makes it on their first login through authelia, and `swarmctl forge +make-admin ` then makes it a site admin — see _Swarm SSO_ below. ### 2 · Gateway (HTTP Basic auth) @@ -195,6 +196,22 @@ If an account already exists without it, `user add` refuses rather than amends — adding the group afterwards is `swarmctl user update mara --add-group admins`. +Then sign in to the forge once through authelia, with that account. That +first login creates your forge account, under the same username. Make it +a site admin: + +```bash +# On the swarm-controller's host. Fails until that first login has happened. +swarmctl forge make-admin mara +``` + +⚠️ **Keep `--email` too.** The forge won't create an account without an +email: a subject that has none gets the forge's link-account page and no +account. `swarmctl user update mara --email …` fixes it. + +If the forge already has a local account with your username, the first +SSO login asks for that account's forge password once, to link the two. + Detail, including what the password is and why this stays manual: [`swarm/sso.md`](../swarm/sso.md). diff --git a/docs/integrations/forge.md b/docs/integrations/forge.md index 83509234..3f98391c 100644 --- a/docs/integrations/forge.md +++ b/docs/integrations/forge.md @@ -15,11 +15,10 @@ each agent on relevant activity. ## Token scopes -Two scope sets live in `hive-c0re::forge`: +Two scope sets: -**`TOKEN_SCOPES`** (per-agent tokens, and `hivectl forge create-user` -accounts). swarm-controller mints agent tokens with a byte-identical copy, -`forge::agent_token::AGENT_TOKEN_SCOPES`, pinned by a test: +**`AGENT_TOKEN_SCOPES`** (swarm-controller's `forge::agent_token`, pinned +by a test). swarm-controller mints every agent token with it: | Scope | Why | | -------------------- | ------------------------------------------------------------------------------------------------------- | @@ -32,9 +31,9 @@ accounts). swarm-controller mints agent tokens with a byte-identical copy, | `read:notification` | Poll `GET /notifications` for unread events. | | `write:notification` | Mark notifications read via `PATCH /notifications/threads/{id}`. | -**`CORE_TOKEN_SCOPES`** (hive-c0re's own `core` user): everything in -`TOKEN_SCOPES` plus `read:admin` and `write:admin`. Site-admin -membership alone isn't sufficient — Forgejo's token scope gate runs +**`CORE_TOKEN_SCOPES`** (`hive-c0re::forge`, for its own `core` user): +everything in `AGENT_TOKEN_SCOPES` plus `read:admin` and `write:admin`. +Site-admin membership alone isn't sufficient — Forgejo's token scope gate runs before the user-permission check, so `/api/v1/admin/*` returns `403 Forbidden` for any token without the admin scope bits, even when the bearer is a site admin. diff --git a/docs/swarm/sso.md b/docs/swarm/sso.md index ca9033dc..05054f95 100644 --- a/docs/swarm/sso.md +++ b/docs/swarm/sso.md @@ -170,7 +170,16 @@ result isn't. | callback URL | `/user/oauth2//callback` | `/_matrix/client/unstable/login/sso/callback/`, a shape tuwunel fixes rather than accepts | | cost of a malformed entry | the login source is missing | the homeserver can refuse to start | -Two consequences worth stating plainly: +Three consequences worth stating plainly: + +- **A person's first forge login creates their forge account**, named + after authelia's `preferred_username` (`[oauth2_client]` in the forge + module), provided the subject has an email. It starts as an ordinary user; `swarmctl forge make-admin +` makes it a site admin. A name that already has a local forge + account doesn't get it handed over: forgejo asks for that account's + own password first (`ACCOUNT_LINKING = login`). Agents, `core` and + `swarm-controller` all have local accounts, and `swarmctl user add` + refuses none of those names. - **tuwunel re-reads its secret file on every OAuth exchange**, not only at startup, and its own sandboxing hides most paths from it. It gets the diff --git a/docs/tools/hivectl.md b/docs/tools/hivectl.md index 47e56416..358ed60a 100644 --- a/docs/tools/hivectl.md +++ b/docs/tools/hivectl.md @@ -11,7 +11,7 @@ Available via the `hive-c0re` package in the host NixOS config. Unlike the `hive-c0re` daemon subcommands (which go through the broker), `hivectl` covers direct host-side administration: manual provisioning of -forge + matrix accounts, gateway htpasswd management, container +matrix accounts, gateway htpasswd management, container lifecycle shortcuts, and interactive agent shell access. This page is the curated guide. For the exhaustive flag-by-flag @@ -24,30 +24,18 @@ markdown-docs > docs/tools/hivectl-cli.md`. ## Forge -Manual entry to the same idempotent provisioning flow `hive-c0re` runs -at boot. Useful for recovery, ad-hoc re-provisioning, or fixing a single -agent without bouncing the daemon. +Reconciles an agent's config between this hive and the forge. `hivectl` +makes no forge accounts: a human's first SSO login to the forge makes +theirs, and `swarmctl forge make-admin ` makes it a site admin. +swarm-controller makes an agent's, and `swarmctl agent mint-forge-token +` checks and, if needed, re-mints its token. ```bash -hivectl forge create-user iris # refused: `iris` is an agent; use `swarmctl agent mint-forge-token iris` -hivectl forge create-user mara # create forge account for a human user; prints token to stdout -hivectl forge create-user mara --password hunter2 # set a web-login password -hivectl forge create-user mara --password-stdin # read password from stdin (safer for scripting) - hivectl forge reconcile-config iris # show local-applied <-> forge config divergence, then prompt hivectl forge reconcile-config iris --from forge # reset local applied checkout to forge main (effective next deploy) hivectl forge reconcile-config iris --verbose # include the full diff, not just --stat ``` -- For **agents** (name has a state dir under `/var/lib/hyperhive/agents/`): - `create-user` refuses. swarm-controller mints an agent's token into - the swarm secret store; `swarmctl agent mint-forge-token ` checks - and, if needed, re-mints it. -- For **non-agents** (humans): creates the account and prints the token to - stdout, creating no state dir. Re-running after account already exists - re-mints the token and prints it again — safe for password resets. -- Without `--password` / `--password-stdin` `create-user` uses a random - throwaway password (fine for agents — they auth by token). - `reconcile-config ` shows the divergence between the agent's local applied config checkout and its forge `agent-configs/` `main`, then reconciles. `--from forge` resets the local checkout to forge `main` (takes @@ -101,7 +89,7 @@ hivectl matrix invite @mara:server --room '#hive-chat:server' # ...or to a spec Write an operator-supplied GitHub personal access token (PAT) into an agent's token file so its `gh` wrapper + git credential helper can act as -the bot account. Unlike forge/matrix there is no account creation — the PAT +the bot account. Unlike matrix there is no account creation — the PAT is for an existing GitHub account. A CLI alternative to the dashboard credentials tab; the [GitHub integration](../integrations/github.md) is on by default (`services.hyperhive.agent.github.enable`), so no per-agent config is needed. diff --git a/swarmctl/README.md b/swarmctl/README.md index 527e6ea0..e526fe7b 100644 --- a/swarmctl/README.md +++ b/swarmctl/README.md @@ -109,3 +109,17 @@ than shared: the controller's own types are private to its binary, this crate does not link it, and there is no wire-type crate between them. Two fields out, two in, both ends validating — a drift shows up as a 400 naming the field. + +## `forge make-admin` + +```console +# swarmctl forge make-admin mara +forge: "mara" is now a site admin +``` + +`POST /api/forge/users/{name}/admin` on the swarm-controller, over the same +socket as `agent create`. It never creates an account: the forge makes a +person's on their first login through authelia, and until then this fails +saying so. Running it on a site admin changes nothing, and an agent's name is +refused. The response shape is mirrored in `src/forge.rs`, for the same +reason as `agent create`'s.