the-custodian/docs/changes/netkingdom-target-2026-10-18/forgejo-postgres-source-r1/owner-integration/workplan-preimage.md

284 lines
13 KiB
Markdown
Raw Normal View History

---
id: RAPPS-WP-0016
type: workplan
title: "Forgejo sign-in through NetKingdom, before the forge closes"
domain: infotech
repo: railiance-apps
status: active
flavor: implementation
owner: claude-code
topic_slug: railiance
created: "2026-10-08"
updated: "2026-10-18"
depends_on:
- KEY-WP-0038
related_repos:
- prj-forgejo-org-refactor
- key-cape
- railiance-platform
state_hub_workstream_id: "f6b1d6f6-0abb-5774-87b9-bf3cfb640a3b"
---
# RAPPS-WP-0016 - Forgejo sign-in through NetKingdom, before the forge closes
## Why
`forgejo.coulomb.social` is closing: private by default, no anonymous access
(prj-forgejo-org-refactor ORGREF-WP-0002, decision
`decisions/forge-visibility-policy.md`). The founder's condition is that sign-in
runs through NetKingdom first. railiance-apps owns the Forgejo Helm release
(`docs/forgejo-on-railiance01.md`: S5 Helm release, ingress, operator Makefile),
so the Forgejo side lands here. This plan is ORGREF-WP-0002-T05. The NetKingdom
side is key-cape `KEY-WP-0038`.
## Boundaries
- **Founder guardrail:** tighten gradually; never lock anyone out; never risk
assets; never reach a state that is hard to repair. Every step keeps the
current sign-in path working until the new one is proven.
- **No visibility change** in this plan. Repositories, packages and
`REQUIRE_SIGNIN_VIEW` are ORGREF-WP-0002-T08.
- **Configuration in git.** The authentication source is declared in
`helm/forgejo-values.yaml` (`gitea.oauth`), with its secret drawn from an
ExternalSecret over OpenBao. No click-ops, and no secret value in git.
- Open registration is already disabled (`service.DISABLE_REGISTRATION: true`).
This plan keeps it that way.
## Tasks
```task
id: RAPPS-WP-0016-T01
status: done
priority: high
state_hub_task_id: "98004ed0-83e6-5f6e-9b18-15b8b2aec2e7"
```
### T01 — Make the local administrator a sealed break-glass
Before anything about sign-in changes: confirm the local administrator account
works, keep its credential only in OpenBao, and document recovery (who, how,
where it is logged) in `docs/forgejo-on-railiance01.md`. Verify one break-glass
sign-in and record it without the credential.
Acceptance: a recorded break-glass sign-in, with the recovery path written down.
This is the "never lock ourselves out" floor for every later step.
Done 2026-10-17: founder sealed `forgejo_admin` into OpenBao
`platform/workloads/forgejo/break-glass-admin` (version 1) and verified a local
sign-in (HTTP 200, site admin): `docs/evidence/2026-10-17-forgejo-breakglass-signin.json`.
Recovery path: `docs/forgejo-on-railiance01.md` § Break-glass administrator.
```task
id: RAPPS-WP-0016-T02
status: wait
depends_on: [RAPPS-WP-0016-T01, KEY-WP-0038-T02]
blocking_reason: "Break-glass done (T01); needs the NetKingdom client registered with its secret in custody (KEY-WP-0038-T02)."
priority: high
state_hub_task_id: "13cd3aec-c87d-5d3f-a421-39d8ff131edd"
```
### T02 — Add the NetKingdom authentication source
- an ExternalSecret delivering the `forgejo` client secret from OpenBao to a
Secret in the `forgejo` namespace. Custody path is
`platform/workloads/keycape/forgejo`, field `CLIENT_SECRET`, read by ESO through
Kubernetes-auth role `external-secrets-keycape-forgejo-forgejo`, which carries
only policy `workload-kv-read-keycape-forgejo-forgejo` (net-kingdom 074b3a0;
replaces the earlier `platform/workloads/forgejo/netkingdom-oidc-client` proposal). The
SA/SecretStore/ExternalSecret shape follows the NK-WP-0048
`deliver-consumer-secret` receipt contract
(`docs/evidence/nk48-t16-owner-review/owner-review-railiance-apps.json`)
- `gitea.oauth`: name `netkingdom` (must match the redirect URI registered in
key-cape), provider `openidConnect`, auto-discovery from
`https://kc.coulomb.social/.well-known/openid-configuration`, scopes
`openid profile email groups`, group-claim name `groups`
- `oauth2_client` settings: no automatic account creation for unknown subjects;
account linking to existing local accounts by username after a successful
local sign-in (so the founder and agent accounts keep their history)
- Helm upgrade with the previous revision noted for rollback
Local password sign-in stays enabled.
Acceptance: the "Sign in with netkingdom" option appears. Local sign-in still
works. Rollback is one `helm rollback` to the noted revision.
```task
id: RAPPS-WP-0016-T03
status: wait
depends_on: [RAPPS-WP-0016-T02]
blocking_reason: "Linking and team mapping follow a working authentication source."
priority: high
state_hub_task_id: "81f072aa-c316-511e-a2cd-21dd1b1d0a00"
```
### T03 — Link accounts and map groups to teams
- The founder links their account through NetKingdom (MFA), then signs in again
through NetKingdom only and sees the same repositories, organisations and
admin rights.
- Map NetKingdom groups (names agreed in KEY-WP-0038-T01) to organisation teams:
owners and readers at least. Create the read-only teams that
ORGREF-WP-0002-T06 consumers will use.
- Apply KEY-WP-0038-T03's decision on agents and services: NetKingdom sign-in, or
scoped tokens bound to service identities.
Acceptance: founder and one agent work through NetKingdom; group-to-team mapping
verified by adding and removing one test membership; break-glass still works.
```task
id: RAPPS-WP-0016-T04
status: wait
depends_on: [RAPPS-WP-0016-T03]
needs_human: true
blocking_reason: "Restricting local password sign-in is a founder decision once NetKingdom sign-in is proven."
priority: medium
state_hub_task_id: "32c54737-c40f-5fde-9b91-163f8dcb0068"
```
### T04 — Decide on local password sign-in
Once NetKingdom sign-in has been used for a while without problems, the founder
decides whether local password sign-in is turned off for everyone except
break-glass. This is not required to close the forge; it is the next tightening
step, taken separately.
```task
id: RAPPS-WP-0016-T05
status: wait
depends_on: [RAPPS-WP-0016-T02]
blocking_reason: "Waits for net-kingdom's answer to the Apps 1.3 needs-change record (the-custodian docs/changes/netkingdom-target-2026-10-17/nk48-1.3-owner-review/owner-review-railiance-apps.json: RAPPS-1.3-C1..C3) and the re-frozen 1.3 candidate."
priority: medium
state_hub_task_id: "728786c9-f1f9-5983-a6a4-dea21faf67f5"
```
### T05 — Apps owner seams for NK-WP-0048 consumer steps
Implement the real Apps capabilities behind the `deliver-consumer-secret` and
`hand-over` adapters, as owner-run paths (option C): `owner_apply` /
`owner_remove` emitting `netkingdom.consumer-secret-delivery.v1` receipts from the
T02 objects; a consumer verifier that observes Forgejo sign-in and the T03
positive/negative group probes; and a committed-evidence hand-over receipt store.
See the owner-review record for the contract.
Acceptance: receipts produced from the live T02/T03 run validate against the
adapters' checks with no value-bearing keys.
## Also in scope: stale node credential
The k3s `registries.yaml` on railiance01 still holds a login for the frozen Gitea
host `92.205.130.254` (ORGREF-WP-0002-T02). Coordinate its removal with the node
owner when ORGREF-WP-0002-T06 adds the forge registry login, in the same change.
## T06 — Package the reviewed consumer source through the Apps build path
```task
id: RAPPS-WP-0016-T06
status: done
priority: high
state_hub_task_id: "08ab8921-7801-5309-b84b-bc2a3ceea1e4"
```
Completed 2026-10-18, source build tooling only. The existing Apps Makefile now
has explicit prepare, public-dependency acquisition, offline build, artifact
verification and local OCI export targets for the pinned official Forgejo11.0.3
source plus reviewed multi-value claim patch. Source/toolchains/locks/compiler
inputs/base image are fixed. Third-party application source stays in a new /tmp
workspace; Apps holds the release input lock, patch and build recipe.
The original build profile produced identical frontend assets, bindata sources
and complete static executable in two workspaces, and identical local OCI
archives in two no-cache exports. Independent review then found host process
argv visibility through /proc (APPSBUILD-R1-F01). The revised recipe adds a
private PID namespace; exact source and synthetic canary regression are separately
reviewed. The original full builds are historical r1-profile evidence; no full
r2 build is claimed. Original packet/review and failure history remain in
Custodian apps-forgejo-release-build-r1 and apps-release-independent-review-r1;
the correction is apps-forgejo-release-build-r2. This is coordinator source
integration after independent technical review, not formal owner assent or image
admission. Helm values, deployed image, local sign-in and visibility are unchanged.
NK-WP-0048-T39 remains progress for the full release acceptance scope.
## T07 — Keep the client secret out of process arguments
```task
id: RAPPS-WP-0016-T07
status: progress
priority: high
state_hub_task_id: "786d6584-6db1-5a10-9324-d7b94db0df94"
```
Implement and independently review a real Forgejo add/update --secret-file path
and the actual chart helper/mount adaptation. Preserve the existing CLIENT_SECRET
key and custody route; use no agent-value argument or environment fallback. Test
bounded stable nofollow file reads, exact existing minted-secret encoding,
mutual exclusion/update preservation, fixed errors and actual Helm rendering.
Private mount identity/reader set and new package/type revisions need explicit
owner/runtime admission. The in-progress isolated candidate is Custodian
forgejo-private-input-r1; source completion is distinct from T02 native delivery.
## T08 — Provide a transactional application-source inverse and durable recovery
```task
id: RAPPS-WP-0016-T08
status: progress
priority: high
state_hub_task_id: "4ab8a5e7-ab32-5ee2-aaf2-6da246d1b0c8"
```
Implement actual owner database primitives that record operation intent/outcome
in the same durable database, compare complete raw persisted before/post/current
source state privately, and serialize conflicting application writers at the DB
boundary. Never emit stored credential/config bytes or delete/detach linked users
or a preexisting/shared source. SQLite and PostgreSQL transaction semantics must
be tested against the real app packages; unsupported backends refuse.
T05 and NK-WP-0048-T34 additionally require actual authenticated execution and
fresh inverse sessions, admitted evidence/recovery and exclusion of every release
writer, including Helm/runtime writers. The candidate DB primitive alone does
not establish those facilities. Helm rollback/omission does not remove persisted
OAuth sources: verify the exact app-state inverse before any image downgrade.
If links prevent removal, retain the extended image and reconcile. The earlier
T02 single-Helm-rollback statement is not sufficient recovery for this extension;
its historical text is retained and corrected here.
## T09 — Enforce authenticated Access Engine decisions in the application path
```task
id: RAPPS-WP-0016-T09
status: progress
priority: high
state_hub_task_id: "d3804638-c73d-5b9f-a456-4262f62f9e6b"
```
Use the producer-owned decision format/canonical bytes and independently admitted
signer/policy/request pins. Forgejo must verify the caller's issuer/tenant and
assurance facts, obtain and authenticate the exact Access Engine resource/action
decision, and refuse missing, stale, wrong-pin, unavailable or malformed replies.
Keep the original three-group any-of access set as policy input; its local
compatibility gate is not a substitute PDP or an architecture exception. An
issuer allowed/denied claim cannot manufacture authorization. Source integration
needs real provider/callback/session wiring and meaningful producer-consumer
positive/adverse tests before re-freezing the case and package. Existing break-
glass/local account and linking behavior remain within the declared owner scope.
2026-10-18 source continuation for T07/T08/T09: the digest-bound build
candidate now composes all 37 paths, including private secret-file input, actual
source-state transactions/private SQL hooks, the producer-owned Access Engine
Check client from ca0cb757 and guarded OIDC callback enforcement. The parser uses
the actual KeyCape typed assurance/authentication-time/provenance contract; its
actual issuer fixture/callback suite passes 71 test/subtest results, and selected
composed packages pass 93 with no skips. The previous incompatible-string-claim
rejection is retained. All patch postimages independently replay from the pinned
official archive. Complete release build/verification is tracked in Custodian
forgejo-keycape-claims-r1; earlier release outputs do not prove this revision.
This is coordinator source integration of a tested build candidate; independent
owner review and formal operational admission remain open. T07's chart/private
mount admission, T08's fresh authenticated operation/inverse and release-wide
writer exclusion, T09's ongoing HTTP/API/Git/SSH paths, private evidence/retention,
PostgreSQL/native proof and actual issuer/factor/custody acceptance remain open.
No trust, deployed image, Helm values, source DB, user/link state or local sign-in
is changed by this build-source update. The preserved legacy patch is historical;
the input lock now explicitly selects forgejo-security-extension.patch.