docs: close Phase 5D security hardening
CI / verify (pull_request) Successful in 27s
CI / infrastructure-smoke (pull_request) Successful in 12s
CI / migration-smoke (pull_request) Successful in 42s

The documentation still described Phase 5D as in progress, Phase 6 as
blocked, and a disposable-runner isolation proof as a prerequisite for
opening the real pull request. All five passes and the independent
whole-repository re-audit have landed, so those statements no longer
match the accepted operating model.

The README's current status now records Phase 5D as complete under the
current trusted-contributor, not-yet-deployed threat model, with Phase 6
unblocked, and gains a pass 5 closure paragraph covering the re-audit,
the repository-local supply-chain and dependency fixes, the accepted
trusted-code-only CI boundary, and what remains required before
untrusted CI or a public launch. The pass 1-4 paragraphs keep their
technical content unchanged; only their tense changes, so each reads as
what was outstanding at the close of that pass rather than as a current
claim.

`platform-architecture.md` no longer stops at pass 1 or says passes 2-5
are unfinished; it summarizes all five passes and defers the remaining
operational limitations to the security document.

`security.md` states the trusted-code-only operating rule explicitly and
replaces "CI blockers before the real pull request is opened" with
"Requirements before executing untrusted contributions", framing the five
hardening items as prerequisites for relaxing that rule rather than as
Phase 6 blockers, and naming an isolated hosted-runner service as an
accepted alternative. The Gitea 1.24.2 warnings, the scope of
`persist-credentials: false`, and the unverified runner topology and
job-token authority are preserved verbatim; no external Gitea setting is
claimed. The launch checklist is marked as gating a public launch, not
development.

Both Doctor examples are corrected to the real three-migration output,
adding `core:0002_authorization_integrity · 634294731180`. The stale
sentence calling Core authorization the next architectural phase is
refreshed.

ADRs 0017-0020 are untouched: their statements that later passes were
outstanding are historical records made when each was accepted.

Documentation only — no production code, test, workflow, dependency,
migration, or schema change.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
ekklesia
2026-07-29 21:59:26 -05:00
co-authored by Claude Opus 5
parent 27088fc054
commit 288c088377
4 changed files with 117 additions and 41 deletions
+7 -6
View File
@@ -108,9 +108,10 @@ Data definitions
✓ Schemas validated
0 modules · 0 tables
✓ Migrations validated
2 migrations · checksums valid
3 migrations · checksums valid
core:0000_identity_core_tables · f8f2086ef06f
core:0001_authorization_core_tables · 830e1fbc26d0
core:0002_authorization_integrity · 634294731180
PostgreSQL
○ Connection check skipped
@@ -133,11 +134,11 @@ Result: READY WITH WARNINGS
Doctor is a local, human-readable summary. `pnpm verify`, `pnpm ci:verify`, infrastructure smoke,
and migration smoke remain the authoritative automated evidence because they exercise formatting,
boundaries, types, tests, builds, containers, and live mutation/rollback behavior that Doctor does
not repeat. Core authorization and an explicit platform-owner bootstrap command are the next
architectural phase; Doctor does not diagnose authorization, the `apps/api` HTTP transport, runtime
module health, or production storage yet, and it never constructs an operational Better Auth
instance, starts the API, or claims sign-in works. See [API](api.md) for `pnpm api:start` and the
identity HTTP transport this repository now has.
not repeat. Core authorization and the explicit platform-owner bootstrap command have since shipped,
and Doctor reports the composed permission registry; it still does not diagnose grant evaluation, the
`apps/api` HTTP transport, runtime module health, or production storage, and it never constructs an
operational Better Auth instance, starts the API, or claims sign-in works. See [API](api.md) for
`pnpm api:start` and the identity HTTP transport this repository now has.
Migration planning and application require `DATABASE_URL`. Keep it in the uncommitted `.env`
created from `.env.example`:
+30 -2
View File
@@ -111,6 +111,10 @@ A loopback default is not a firewall, and a config default is not a verified bou
Until every one of these is verified on the actual hosts, the deployment is not launch-ready. None
of them can be satisfied by reading this repository.
This checklist gates a **public launch**. It does not gate development: Surfaces, modules, and Core
work all proceed against the local development infrastructure while every item below is still
outstanding.
1. The reverse-proxy path serves the API successfully.
2. The origin port is unreachable from the public Internet.
3. The origin port is also unreachable from any untrusted network/VLAN — only the intended private
@@ -143,6 +147,17 @@ Ekklesia does not ship one. Do not describe the current limiter as distributed t
CI runs on self-hosted Gitea Actions runners. The inventoried server is **Gitea 1.24.2**, and that
version determines which parts of the workflow are real guarantees and which are not.
### The current operating rule: trusted code only
**This CI installation is a trusted-code-only boundary.** Only code controlled and reviewed by
trusted repository collaborators may execute on the self-hosted runner. An unknown or untrusted pull
request must **not** execute on it automatically — a maintainer reviews the diff, including any
change to the workflow itself, before it runs.
This is an operating rule, not an enforced technical control, and it is the reason the rest of this
section is safe today. Everything below describes what the repository can and cannot prove about
that runner; none of it is a substitute for the rule.
### What is true of the repository today
These are properties of files in this repository, enforced by the action or the package manager,
@@ -192,7 +207,15 @@ Docker socket, must be established against the actual Gitea instance and runner
evidence exists, treat pull-request CI as executing with whatever authority the runner host actually
grants.
### CI blockers before the real pull request is opened
### Requirements before executing untrusted contributions
These five items are the prerequisites for **relaxing the trusted-code-only rule above** — that is,
for letting code this project has not reviewed execute on this Gitea installation. They are backlog
requirements for that specific future capability. **They do not block Phase 6 Surface work**, and
they are not conditions on merging trusted, reviewed work.
None of them can be satisfied by editing this repository; each requires access to the Gitea server
and runner hosts, and each must be proven there.
1. Upgrade Gitea to a reviewed supported release with job-token permission controls — at least the
1.26 feature line. Select the actual release during infrastructure work, after backup and
@@ -204,4 +227,9 @@ grants.
private repository.
4. Enforce job timeout, cancellation, concurrency, and teardown in the trusted
provisioner/reaper rather than relying on the ignored workflow keys above.
5. Complete the disposable-guest runner isolation proof before opening the real pull request.
5. Complete a disposable-guest runner isolation proof: one throwaway guest per job, torn down by a
trusted reaper outside workflow YAML, holding no deployment credential, registration token, or
reusable key.
Moving future public contribution workflows to a service that provides isolated hosted runners — for
example GitHub — is an accepted alternative to satisfying items 1–5 on this installation.