docs: add token scopes section to forge.md, trim forge.rs module doc + scope comments
This commit is contained in:
parent
88cdab411e
commit
5522d65074
2 changed files with 43 additions and 46 deletions
|
|
@ -8,6 +8,37 @@ handling live in [`docs/gateway.md`](gateway.md); this file owns the
|
|||
per-agent integration story and the notification pump that wakes
|
||||
each agent on relevant activity.
|
||||
|
||||
## Token scopes
|
||||
|
||||
Two scope sets live in `hive-c0re::forge`:
|
||||
|
||||
**`TOKEN_SCOPES`** (per-agent tokens):
|
||||
|
||||
| Scope | Why |
|
||||
|-------|-----|
|
||||
| `write:repository` | Create, clone, push, delete repos; merge PRs. |
|
||||
| `write:issue` | Open / comment / review issues **and** pull requests (Forgejo namespaces PR conversation under issues). |
|
||||
| `write:user` | Edit own profile, create repos under own user. |
|
||||
| `write:organization` | Create + manage orgs (lets agents share a forge namespace). |
|
||||
| `read:user` | Token-owner endpoint used for self-identification at harness startup. |
|
||||
| `write:misc` | Hooks, attachments, the rest of the long tail. |
|
||||
| `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
|
||||
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.
|
||||
|
||||
**Migration note**: if `PATCH /api/v1/admin/users/{name}` returns 403
|
||||
on an existing deploy, the core token predates the admin-scope
|
||||
addition. Delete `/var/lib/hyperhive/forge-core-token` and restart
|
||||
hive-c0re to re-mint with the new scopes.
|
||||
|
||||
---
|
||||
|
||||
## Per-agent forge accounts
|
||||
|
||||
Each agent gets its own Forgejo user + access token, provisioned at
|
||||
|
|
|
|||
|
|
@ -1,21 +1,6 @@
|
|||
//! Optional Forgejo wiring. When the `hive-forge` nixos-container is
|
||||
//! present and running, hive-c0re ensures every agent (and the
|
||||
//! manager) has a corresponding forgejo user with an API token
|
||||
//! written to `<agent-state>/forge-token` — visible inside the
|
||||
//! container as `/state/forge-token`. Idempotent: skips creation
|
||||
//! when the user already exists, skips token issuance when the file
|
||||
//! is already there.
|
||||
//!
|
||||
//! It also mirrors each agent's hive-c0re-owned *applied* config repo
|
||||
//! into the private `agent-configs` org (`push_config`), so every
|
||||
//! deploy / approval tag core plants is visible on the forge. Each
|
||||
//! agent is a read-only collaborator on `core/meta` (the meta flake)
|
||||
//! so they can fetch their deployment context; the `agent-configs`
|
||||
//! repos remain core-only.
|
||||
//!
|
||||
//! No-op when `hive-forge` isn't enabled (detected via
|
||||
//! `nixos-container list`), so operators who don't run the bundled
|
||||
//! forge pay nothing.
|
||||
//! Optional Forgejo wiring — per-agent user + token provisioning,
|
||||
//! config-repo mirroring, meta read-access grants. No-op when
|
||||
//! `hive-forge` isn't running. Full design: `docs/forge.md`.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
|
@ -56,32 +41,15 @@ const CONFIG_ORG: &str = "agent-configs";
|
|||
/// Forgejo orgs hive-c0re ensures on startup. The meta repo lives at
|
||||
/// `core/meta` (the `core` user's own namespace — no org needed).
|
||||
const SEEDED_ORGS: &[&str] = &[CONFIG_ORG];
|
||||
/// Forgejo scopes the agent's token gets. Broad-but-not-admin: every
|
||||
/// repo / PR / issue thing an agent needs day-to-day, no admin
|
||||
/// surface.
|
||||
/// - `write:repository` — create, clone, push, delete repos in the
|
||||
/// user's own namespace; merge PRs.
|
||||
/// - `write:issue` — open / comment / review issues *and* pull
|
||||
/// requests (forgejo namespaces PR conversation under issues).
|
||||
/// - `write:user` — edit own profile, create repos under own user.
|
||||
/// - `write:organization` — create + manage orgs (lets agents share
|
||||
/// a forge namespace).
|
||||
/// - `read:user` — token-owner endpoint clients call to introspect.
|
||||
/// - `write:misc` — hooks, attachments, the rest of the long tail.
|
||||
/// - `read:notification` — required by `forge_notify` to poll
|
||||
/// `GET /notifications` for unread PR/review events.
|
||||
/// - `write:notification` — required by `forge_notify` to mark
|
||||
/// notifications as read via `PATCH /notifications/threads/{id}`.
|
||||
/// Per-agent token scopes (broad-but-not-admin). See
|
||||
/// `docs/forge.md::Token scopes` for the per-scope rationale.
|
||||
const TOKEN_SCOPES: &str = "read:user,write:user,read:notification,write:notification,write:repository,write:issue,write:organization,write:misc";
|
||||
|
||||
/// Scopes for the bootstrap `core` token used by hive-c0re itself.
|
||||
/// Adds `read:admin,write:admin` on top of `TOKEN_SCOPES` so the host
|
||||
/// daemon can drive `/api/v1/admin/*` endpoints (PATCH user email on
|
||||
/// agent provision, future webhook + org admin work). Site-admin
|
||||
/// membership alone isn't enough — the token's own scope gate runs
|
||||
/// before the user-permission check, so `403 Forbidden` comes back
|
||||
/// for any `/admin/users/*` call from a non-admin-scoped token
|
||||
/// even if the bearer is an admin user.
|
||||
/// Bootstrap `core` token scopes — adds `read:admin,write:admin` on
|
||||
/// top of `TOKEN_SCOPES` so the host daemon can drive
|
||||
/// `/api/v1/admin/*`. Site-admin membership alone isn't enough: the
|
||||
/// token's own scope gate runs before the user-permission check.
|
||||
/// See `docs/forge.md::Token scopes`.
|
||||
const CORE_TOKEN_SCOPES: &str = "read:admin,write:admin,read:user,write:user,read:notification,write:notification,write:repository,write:issue,write:organization,write:misc";
|
||||
|
||||
/// Token file inside the agent's bind-mounted state dir (visible as
|
||||
|
|
@ -271,10 +239,8 @@ async fn ensure_user_email(name: &str) {
|
|||
tracing::debug!(%name, %email, "forge: user email aligned");
|
||||
}
|
||||
Ok(status) if status == reqwest::StatusCode::FORBIDDEN => {
|
||||
// Almost certainly an existing-deployment migration case:
|
||||
// an older core token may have been minted without admin
|
||||
// scope, so /admin/users/* now returns 403 even though
|
||||
// `core` is a site admin. Tell the operator how to fix it.
|
||||
// Core token missing admin scope — see
|
||||
// `docs/forge.md::Token scopes` migration note.
|
||||
tracing::warn!(
|
||||
%name, %email, %status,
|
||||
"forge: PATCH user email forbidden — core token likely missing admin scope. \
|
||||
|
|
|
|||
Loading…
Reference in a new issue