prj-forgejo-org-refactor/decisions/forge-visibility-policy.md
tegwick 218df303e8 ORGREF-WP-0002-T01 done: visibility policy fully decided
Packages private; the founder holds T01 and T08, an agent drives the rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5457@bnt-lap001
Assistant-Session: 792bf84a-3783-4f5d-a811-cded61dd2012
2026-10-08 18:59:02 +02:00

127 lines
6.4 KiB
Markdown

# Forge visibility policy (ORGREF-WP-0002-T01)
Status: **decided** (founder, 2026-10-08). All six points and the plan's owner.
## 1. The forge is private, with no anonymous access — decided
Every org, repository and package on `forgejo.coulomb.social` is private, and
the final wave sets `REQUIRE_SIGNIN_VIEW=true`. The forge is internal
infrastructure. Public codebases, when there are any, are published to a
separate location with its own publicity, probably not one we build
(GitHub or similar).
## 2. Publication is a per-repo `public/` convention, not a visibility setting — decided
Licensing is experimental and is **not** an input to access decisions.
What to publish, where and for whom is a series of decisions per repository.
They are made through a shared publication-flow mechanism, not reinvented per
repository. The baseline is the Unix home directory's public folder:
- **`public/` holds only symlinks**, never original content. Each link points to
a file inside the same repository.
- **Everything reachable through `public/` may be made readable from outside**,
by a publisher that projects it to the public location. Nothing outside
`public/` is published.
- **Emergency removal:** renaming the folder (for example to `public.withdrawn/`)
withdraws everything at once.
- **Transparency:** `INTENT.md`, `README.md` and `LICENSE.md` are candidates to
link from `public/` where showing what a repository is about is wanted.
- **Sanitization:** published content passes a check before it leaves (secrets,
internal hostnames and addresses, personal data, links into private
repositories).
- **Hall of Helix** content is published: it is a PR edge. This connects to
coulomb.social, where a coulomb.social space corresponds to a repository and
its content is a projection of information in that repository.
### Consequences to carry into the design
- **Withdrawal must propagate.** Renaming `public/` stops new publication. It only
removes content from the outside if the projection mirrors absence: the
publisher deletes what is no longer in `public/` on its next run, and a
withdrawal can trigger that run immediately. What has already been fetched
outside stays fetched.
- **The publisher is the only reader that crosses the boundary.** It reads
private repositories with its own read identity, resolves the symlinks,
sanitizes, and writes to the public target. The forge itself never serves
`public/` anonymously, which is consistent with point 1.
- **The convention is checkable.** A repository check can enforce that `public/`
contains only relative symlinks resolving inside the repository, with no
absolute paths, no `..` escapes and no links to other symlinks.
- **This is ecosystem convention.** The `public/` rule belongs in canon (a
the-custodian standard, review-gated). The publisher and the coulomb.social
projection belong to their own owners (coulomb-social, plus a publishing
component). This plan only needs the forge to be closable without breaking
the Hall's PR edge.
## 3. Packages follow their repository: private — decided
One node-level registry login (k3s `registries.yaml`, read-only package
identity) for all 43 workloads; one ArgoCD credential template for the
`coulomb/` repositories; job tokens in CI; package-read tokens for PyPI and npm.
## 4. Telegram post images — decided
The fluid-telegram adapter fetches each image with a read identity and uploads
it to Telegram, so no image URL needs to be public (fluid-telegram
FT-WP-0001-T14).
A public assets location will come later, deliberately: a specific asset
repository and store with creator and trust management. It is **not** improvised
now, and Telegram images do not wait for it.
## 5. Interim lockdown — decided, with guardrails
The interim set is approved: the sensitive repositories with no anonymous reader
(inventory 2026-10-08): `disaster-control`, `railiance-hosts`, `secrets-engine`,
`rapp-secrets-engine`, `rapp-openbao`, `rapp-policy-nexus`, `fin-hub`,
`qonto-assistant`, `rapp-tenant-engine`, `executor-sandbox`, `ops-mason`,
`rein-aharness`, `rein-openweights`. `hall-of-helix` stays readable until its
publication path exists.
Founder guardrail, and the rule for every later wave as well: **tighten
gradually. Never lock ourselves out, never risk losing assets, never end up in a
state that is hard to repair.** Concretely:
1. **Before anything closes:** confirm that a current local clone of each
repository exists (SSH, `forgejo-remote`) and is up to date with the server.
Confirm that the founder account and the local administrator can sign in, and
that administrator recovery is documented. Visibility changes delete nothing,
but the clone is the recovery path if anything goes wrong.
2. **One repository first,** the least connected one. Close it, then verify:
founder web view, SSH fetch and push, agent clone over SSH, and that an
anonymous request gets 404. Reopen it once to prove the rollback, then close
it again.
3. **Then the rest in small batches,** with the same checks after each batch.
Stop at the first surprise and reopen what that batch changed.
4. **Only visibility changes.** No deletion, archiving, transfer, renaming, team
or permission edits, and no instance settings (`REQUIRE_SIGNIN_VIEW` stays for
the final wave).
5. **Record every change** (repository, time, before and after, check results)
under `inventory/`, so that any step can be undone exactly.
### Step 1 pre-check, 2026-10-08
Local clones exist for all 13 and were fetched. 11 are clean and level with
`origin/main`. Two need their owners first and stay out of the first batch:
- **`executor-sandbox`:** local `master` and server `main` have diverged: 3 local
commits were never pushed, and the server has 5 that the local branch lacks.
Both histories are now held locally (`origin/main` fetched), so closing loses
nothing. The unpushed work belongs to the owner to reconcile; it is not changed
here.
- **`ops-mason`:** 3 uncommitted local changes. Server state is fetched; the
changes are the owner's.
Suggested first repository for step 2: `rapp-openbao` or `railiance-hosts`
(single branch, clean, no anonymous reader).
## 6. Exposed history — decided
T03 scans public history and drives rotations in parallel. It does not block
the waves.
## Owner — decided
The founder holds T01 (this policy) and T08 (approval of each production wave).
An agent drives the rest of ORGREF-WP-0002.