From 79f4ce3f1eb3c8ce77fbc03f742b77ab1d67fff4 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 8 Oct 2026 15:26:51 +0200 Subject: [PATCH] Add ORGREF-WP-0002: close the forge after NetKingdom access integration Founder-approved 2026-10-08. Independent of the ORGREF-WP-0001 entry gate: changes who may read, not where repositories live. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 5457@bnt-lap001 Assistant-Session: 792bf84a-3783-4f5d-a811-cded61dd2012 --- ...WP-0002-forge-closure-netkingdom-access.md | 300 ++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 workplans/ORGREF-WP-0002-forge-closure-netkingdom-access.md diff --git a/workplans/ORGREF-WP-0002-forge-closure-netkingdom-access.md b/workplans/ORGREF-WP-0002-forge-closure-netkingdom-access.md new file mode 100644 index 0000000..25d3744 --- /dev/null +++ b/workplans/ORGREF-WP-0002-forge-closure-netkingdom-access.md @@ -0,0 +1,300 @@ +--- +id: ORGREF-WP-0002 +type: workplan +title: "Close the forge: NetKingdom access control first, then private by default" +domain: infotech +repo: prj-forgejo-org-refactor +status: ready +flavor: implementation +owner: worsch +topic_slug: railiance +created: "2026-10-08" +updated: "2026-10-08" +depends_on: [] +related_repos: + - key-cape + - railiance-forge + - railiance-platform + - railiance-apps + - ops-warden + - fluid-telegram + - pr-hall-of-helix + - the-custodian +--- + +# ORGREF-WP-0002 - Close the forge: NetKingdom access control first, then private by default + +## Why + +`forgejo.coulomb.social` does not distinguish public-facing repositories from +private ones. The 2026-09-28 anonymous inventory listed **141 server +repositories, all public**. That includes `hall-of-helix` draft seats, agent +session accounts, operational docs and workplans. Anyone can read them, and +their raw files can be fetched anonymously. + +The founder's decision (2026-10-08): switch repositories to private, but only +**after** Forgejo access control is integrated with NetKingdom (key-cape). Every +human, agent and service reader then has a governed identity before anonymous +access ends. A flip without that would push every consumer to ad-hoc local +accounts and tokens that would later have to be unwound. + +## Relation to ORGREF-WP-0001 + +This plan is **independent of the ORGREF-WP-0001 entry gate**. It moves no +repository between orgs, renames nothing and changes no repository content, so +the org-migration gate (validator, deployable coverage, G1, transfer rollback) +does not apply. It changes **who may read**, not where things live. + +It reuses ORGREF-WP-0001's preparation: the `inventory/` collectors, the +stewardship assignments in `taxonomy/` (as owners for each consumer) and the +reference scan. It also gives back to ORGREF-WP-0001: once the forge is closed, +the anonymous collector can no longer see private repositories, so T09 moves it +to an authenticated read identity. That resolves the access half of decision +`5f3680fc` (authenticated metadata). + +## Target state + +- Forgejo signs humans in through NetKingdom OIDC (key-cape). Agents and services + use NetKingdom-issued identities or scoped Forgejo tokens with an owner and a + rotation path. A local administrator account remains only as sealed + break-glass, with its credentials in OpenBao. +- Organisations and repositories are **private by default**. Public visibility + is an explicit, recorded allowlist entry with a reason. +- Every consumer that read the forge anonymously reads it with its own + credential, with least privilege, before its repositories close. +- Campaign images that must stay world-readable (Telegram posts fetch them by + URL) come from a deliberate public asset location, not from a forge repo that + happens to be public. +- Anonymous probes show only the allowlist; the evidence is recorded. + +## Boundaries + +This project may: + +- decide sequencing, run read-only inventories and anonymous/authenticated probes +- rehearse on throwaway repositories and packages it creates for that purpose +- open and track child work records in owner repos, linked by ID, not copied + +It must not: + +- configure key-cape, Forgejo, OpenBao or any consumer itself. Each change lands + through the owner repo's own workplan. +- flip a production repository's visibility before T07's rehearsal passes and + the founder approves that wave +- read or print secret values (credential routing: `warden route`) +- move, rename or restructure repositories (that is ORGREF-WP-0001) + +Visibility changes are reversible; exposure is not. Content that has been public +stays public in clones, caches and archives. T03 treats that history as a +separate review, not something the flip repairs. + +## Tasks + +```task +id: ORGREF-WP-0002-T01 +status: wait +needs_human: true +blocking_reason: "The founder decides the visibility policy, the public allowlist and whether an interim lockdown runs before the integration." +priority: high +``` + +### T01 — Decide the visibility policy + +Record a founder decision covering: + +1. **Default:** private for organisations and repositories, plus whether + instance-level `REQUIRE_SIGNIN_VIEW` is set so that nothing is anonymous + except the allowlist. +2. **Public allowlist:** which repositories stay public and why (for example, + intentionally open-source repos or a published campaign repo). Each entry + names an owner. +3. **Packages:** container images and charts follow repository visibility or + are private independently (28 running workload images come from + `forgejo.coulomb.social`; see `inventory/runtime-2026-09-28.json`). +4. **Public assets:** where world-readable campaign images live once + `hall-of-helix` and `pr-hall-of-helix` close (a public asset repo, object + storage, or attaching the image as an upload instead of a URL). +5. **Interim lockdown:** whether to close a short list of sensitive repositories + now with existing local accounts. If yes: which ones, accepting that their + consumers move to local tokens temporarily and are re-homed in T06. + +```task +id: ORGREF-WP-0002-T02 +status: todo +priority: high +``` + +### T02 — Inventory every anonymous reader + +Read-only. Extend `inventory/` with an access-consumer inventory: every party +that reads the forge today without credentials, the repositories or packages it +reads, and the owner (from `taxonomy/assignments.csv`) who will give it an +identity. Known classes to cover: + +- cluster pulls: ArgoCD/Flux `repoURL`s, Helm chart repositories, and image pulls + by k3s nodes from the Forgejo registry (namespaces lacking `imagePullSecrets`) +- Forgejo Actions runners: checkouts and cross-repo `uses:` of reusable actions +- agent and workstation clones, `go`/`pip`/`npm` fetches of forge-hosted modules +- State Hub, repo-manager and forge-projection reads; ORGREF's own collector +- fluid-telegram: Telegram fetching post images from raw URLs +- external links: READMEs, badges, docs, published sites and canon links + +Output a machine-readable `inventory/access-consumers-.json` plus a +summary listing, per consumer class, the owner and the proposed credential +kind. Uncertain entries are flagged, not dropped. + +```task +id: ORGREF-WP-0002-T03 +status: todo +priority: high +``` + +### T03 — Review what has already been public + +Before closing, and independent of it: run a secret and sensitive-content scan +over the public repositories' history (credentials, tokens, private keys, +internal hostnames or IPs, personal data). Findings go to their owners for +rotation through `warden route`. Closing a repository does not un-publish +history, so a leaked credential needs rotating either way. Record the scan scope +and results without reproducing any value. + +```task +id: ORGREF-WP-0002-T04 +status: wait +depends_on: [ORGREF-WP-0002-T01] +blocking_reason: "The NetKingdom side follows the visibility and identity decisions; open the key-cape child workplan once T01 is resolved." +priority: high +``` + +### T04 — NetKingdom: Forgejo as an OIDC client (child workplan in key-cape) + +Open a key-cape workplan, linked here by ID, to: + +- register Forgejo as a confidential OIDC client (redirect URI, scopes, PKCE) + with its client secret in OpenBao, through the railiance-platform custody path +- define the claims Forgejo consumes: subject, email, `groups` mapped to Forgejo + organisations and teams, and `principal_type`, so that human, agent and service + identities are distinguishable +- apply the MFA policy for forge administrators, and decide which agent and + service identities get forge access as NetKingdom service identities, not as + user accounts + +Acceptance: a test login against a staging client returns the expected claims +for one human, one agent and one service identity. + +```task +id: ORGREF-WP-0002-T05 +status: wait +depends_on: [ORGREF-WP-0002-T04] +blocking_reason: "Forgejo can only add the authentication source once the NetKingdom client and claims exist." +priority: high +``` + +### T05 — Forgejo: NetKingdom login and team mapping (child workplan in railiance-forge) + +Open a railiance-forge workplan, linked here by ID, to: + +- add the NetKingdom OIDC authentication source and claim-to-team mapping; + disable open registration; link existing local accounts (founder, agent + accounts) to their NetKingdom identities +- seal the local administrator as break-glass, with its credentials in OpenBao + and recovery documented +- create the organisation teams with least-privilege read/write that T06's + consumers will use +- change **no** repository visibility yet + +Acceptance: the founder and one agent sign in through NetKingdom and see what +their team grants. Break-glass login is verified once and recorded. + +```task +id: ORGREF-WP-0002-T06 +status: wait +depends_on: [ORGREF-WP-0002-T02, ORGREF-WP-0002-T05] +blocking_reason: "Each consumer gets its credential from the T02 inventory, using the identities T05 makes available." +priority: high +``` + +### T06 — Give every consumer its own read identity + +For each consumer class in T02, its owner provisions a scoped credential and +proves it works **against a private canary repository and package** created by +this project, while anonymous access to that canary fails: + +- cluster: deploy tokens for ArgoCD/Flux repo credentials, `imagePullSecrets` + for registry pulls (railiance-apps, railiance-platform) +- runners: tokens or OIDC for checkout and reusable actions (railiance-forge) +- agents and workstations: NetKingdom identities or scoped tokens routed through + ops-warden; nothing pasted into repositories +- State Hub, repo-manager and the ORGREF collector: authenticated read identity +- fluid-telegram and pr-hall-of-helix: images moved to the T01 public asset + location, with the `compose visual` raw-URL bases updated + +Each owner records its proof in its own workplan. This plan tracks the list. + +```task +id: ORGREF-WP-0002-T07 +status: wait +depends_on: [ORGREF-WP-0002-T06] +blocking_reason: "Rehearsal needs every consumer class migrated onto the canary." +priority: high +``` + +### T07 — Rehearse the flip and the rollback + +On throwaway repositories and packages: switch public → private → public, and +verify consumer reads, anonymous denial, web links, Actions runs and image pulls +at each step. Record the exact commands or API calls, the time each step takes, +and what a rollback restores (visibility) and what it does not (anything already +fetched). This rehearsal is the gate for T08. + +```task +id: ORGREF-WP-0002-T08 +status: wait +depends_on: [ORGREF-WP-0002-T07] +needs_human: true +blocking_reason: "Each production visibility wave needs founder approval after a green rehearsal." +priority: high +``` + +### T08 — Close the forge in waves + +Change production visibility in founder-approved waves. Each wave lists its +repositories and packages and the consumers that read them. Proposed order: + +1. repositories with no consumers outside their owner (fastest proof of the path) +2. sensitive repositories (operational docs, workplans, agent sessions) +3. repositories read by the cluster and runners +4. instance-level `REQUIRE_SIGNIN_VIEW`, if T01 chose it + +After each wave: consumer health checks, anonymous probe, and a recorded +rollback point. A failing consumer rolls its repositories back to public and +stops the wave. The fix lands with the consumer's owner. + +```task +id: ORGREF-WP-0002-T09 +status: wait +depends_on: [ORGREF-WP-0002-T08] +blocking_reason: "Verification and handback follow the final wave." +priority: medium +``` + +### T09 — Verify, hand back and record + +- Anonymous probe of the server: only the T01 allowlist is visible. Record the + evidence under `inventory/`. +- Move ORGREF-WP-0001's collector to the authenticated identity from T06 and + note the effect on decision `5f3680fc`. +- Add a row to the-custodian `docs/security-close-down-checklist.md` + recording that the forge is closed by default, plus anything relaxed along the + way that must be re-armed. +- Record any consumer still on a temporary credential as live owner work, not as + prose in this file. + +## Open questions for review + +- Owner: is the founder the right owner, or should an agent own the driver with + the founder holding T01/T08? +- Should T03 (history review) block T08, or run in parallel and only gate + rotations? +- Is an interim lockdown (T01 point 5) worth the temporary-token churn, given how + long T04–T07 will take?