diff --git a/docs/research/deployment-walk.md b/docs/research/deployment-walk.md index 9a5b3c0..7c4ffa1 100644 --- a/docs/research/deployment-walk.md +++ b/docs/research/deployment-walk.md @@ -175,16 +175,41 @@ upstream `sinclair` history inside the two imports. Usage patterns this census establishes: -- **Single-branch development.** Almost every active repo develops - exclusively on `main`. The non-`main` branches are leftovers: one - stale feature branch (`reverse-proxy`), `alknet`'s `develop` - (dormant since June), and single-window experiment clusters - (`flowgraph`, `wraith`, `pubsub`, `alktype`'s two POC branches). - Branches are not a load-bearing workflow; `main` + push is. +- **Single-branch is what persists, not the workflow; branches are + load-bearing.** This bullet is corrected: see the correction lenses + in sect 11 and `docs/sdd_process.md` phase 3. The coordinator's + branch-per-worktree pattern pushes, merges, and cleans up branches + as transient scaffolding, so the tree only records its residue. + Branches go stale exactly when a coordination session becomes + overloaded (merge hell) and skips the minor cleanup steps: the + `flowgraph`/`wraith`/`pubsub`/`alktype` clusters and + `reverse-proxy`'s stale branch are cleanup-failure debris. `alknet`'s + `develop` was an out-of-hand rewrite that got decomposed into the + alk\* crates instead of merged. Requirements fallout for alkforge: + accept arbitrary branch pushes with no gating, tolerate high branch + churn, list and delete branches easily (cleanup must not be a + specialist chore), but build no PR/review machinery since review is + in-session. - **Direct push to main, no PR flow.** Confirmed by 0 PRs org-wide plus per-agent commit authorship on `main`. Review happens outside forge-side workflow (in opencode sessions); the forge is the landing zone, not the review surface. +- **Outbound push-mirrors (uncovered by the walk; owner-stated).** + Gitea holds a GitHub personal access token (plaintext in its DB) + and push-mirrors some repos to GitHub; the owner stopped setting up + mirrors for newer repos, and the stated ideal is **all public OSS + repos mirrored to GitHub**, with `alkfamily` internal-only. So + outbound mirroring is load-bearing (currently half-implemented by + inertia), invisible to walk probes (it is config in gitea's DB, + not logged traffic), and its credential storage on gitea is exactly + the anti-pattern the family posture forbids. Under alkforge this + becomes an assembly capability: an alkvault reference for the PAT + with outbound credential injection at the assembly layer (alkhttp + precedent: the OpenAPI/MCP adapters inject `HttpAuthScheme::Bearer` + from `OperationContext.capabilities` at request build, so decrypted + material exists only at the outbound request, never on the wire or + at rest). Migration work: enumerate which repos mirror today and + rotate those tokens into alkvault. - **Tags are the release surface.** 87 semver tags across 15 repos, matching published crate versions; multi-crate repos prefix tags per crate (`alkgit-v0.1.0`). No gitea release objects, no release @@ -214,10 +239,14 @@ inertia, or deferred. 1. Anonymous HTTP smart-clone of all org repos (whole-org public read; the de-facto grant is org-level, not per-repo). -2. Authenticated SSH git, read and write, with direct push to `main` - by per-agent identities (no PR flow, no branch hygiene to enforce). -3. Single-branch (`main`) model with an `alknet/develop` branch to - preserve through migration. +2. Authenticated SSH git, read and write, with direct push by + per-agent identities (no PR flow, no branch hygiene to enforce). +3. **Branch support as a core workflow capability**: arbitrary branch + push/pull with no gating, high churn tolerance, easy listing and + deletion (the coordinator's branch-per-worktree SDD pattern, + `docs/sdd_process.md` phase 3, plus `alknet`'s `develop` and the + stale-branch cleanup decisions at migration; corrected from the + first pass, see sect 11 lens 2). 4. Tags as the release surface (87 tags; per-crate prefixing; migration must carry them; version-tag browsing is the natural minimal web surface). @@ -236,31 +265,54 @@ inertia, or deferred. per-identity write to private repos (17 of 52; `alkfamily` and friends), where "everything else private" is already the daily operative model (new-repo default private on the deployment). +10. **Outbound push-mirrors to GitHub for the public OSS repos** + (owner-stated ideal; currently half-implemented on gitea, sect 4). + In 0.1 this can be as small as: vault-referenced credential, + assembly-injected bearer, periodic push to the mirror remote. If + 0.1 ships without it, the interim migration posture is documented + hand-push until the capability lands (it must not silently ride + gitea's plaintext DB). **Inertia (dropped in 0.1, with a migration note):** - Issues, pull requests, wiki, gitea projects, gitea releases UI, stars/forks/watchers: flags may be on, usage is zero and always - was. Migration note: document that these features were unused, so - the cutover does not silently strand workflows. + was. **Why unused (correction-lenses clarity, sect 11 lens 1)**: + review/coordination lives in opencode sessions, and gitea's + forge-side features were never trusted enough to adopt. Zero usage + here means "not needed *in gitea* in this period", not "never + wanted": the eventual replacement/replication of some of these is + explicitly on the family's long-term roadmap. Migration note: + document that these features were unused, so the cutover does not + silently strand workflows. - Empty repo (`alkdev/ade`): create or drop as the owner chooses. -- Experiment/stale branches outside `main` (except `alknet`'s - `develop`): branch-delete on cutover or preserve for archaeology, - but spec-irrelevant either way. - The JSON API as a user-facing surface (no known API consumers; the family's tooling operates over git + local session state, not the forge API). Confirmed-unknown: any external anonymous API consumer would be indistinguishable from web browsing here. + Shape note (sect 11 lens 3): alkforge should NOT inherit gitea's + all-or-nothing anonymous OpenAPI; under alkcall's model any future + forge surface is an ACL-checked op where an entity sees only what + it has access to, and the anonymous peer class is just another + grantable class. **Deferred (real-but-not-yet or later-version):** +- Stale non-`main` branches (`reverse-proxy`'s, `alknet/develop`, + the POC clusters): they are workflow residue, not capability gaps. + Migration-time decision per branch: delete, or preserve for + archaeology. The *capability* (branches) is load-bearing and + listed above; only these specific branches are disposable. - LFS: unused today (heaviest blob 3.2 MB). The alkblobs/alkgit ADR-022 LFS door can be deferred with confidence; keep a watch for future large design media, which would be the trigger to turn it back on. -- Forge-side CI: never operated; not a 0.1 concern. +- Forge-side CI: verification is in-session by design (and gitea's + Actions runner was never trusted/adopted); not a 0.1 concern. - Everything else in gitea's broad feature set (packages, actions, - mirror sync webhooks, ...): zero evidence of use. + webhooks, ...): zero evidence of use; candidates for later + replication by the long-term roadmap after consideration, not + defaults. ## 6. Sizing implications (what the walk changes) @@ -297,6 +349,11 @@ inertia, or deferred. exact server version. The 0.1 web view plus nameless git serving (no roster page, no version endpoint) is a large standing-exposure cut, consistent with ADR-002's motivation. +- **Outbound mirrors add one credential surface to the migration.** + Whatever ships in 0.1 (push-mirror capability or documented interim + hand-push, sect 5 item 10), the gitea-side PAT must be enumerated + and rotated at cutover, never copied: new secret home is alkvault, + injection at the assembly layer. ## 7. What the walk confirms about the upstream asks (sect 6 of phase-0) @@ -446,3 +503,56 @@ column is stale post-migration and disagrees with on-disk reality the system runbooks instead): the sect 8.6 verification of the off-host "three locations" stays open until the cutover plan verifies a restore point. + +## 11. Correction lenses (reading this walk without gitea's biases) + +The walk measures what the incumbent *served and traversed*. That is +reliable for door and data-volume sizing, but it must not be read as +a requirements list, for reasons the first reading got right only +after owner input (2026-11-07). Five lenses, recorded so future +roadmap work re-applies them: + +1. **Zero usage has three meanings and the walk collapsed them.** + "No need" (issues, PRs: genuinely unused workflows), "done + elsewhere" (CI, wiki: verification and coordination live in the + opencode sessions by design), and "distrust avoidance" (forge-side + features the owner deliberately never adopted in gitea). A zero in + gitea's history means "not needed *in gitea*", never "not wanted". + Any feature with zero usage deserves a "why" question before it + gets deferred; the 0.1 freeze stands as-is, but the long-term + roadmap may re-add considered replacements. +2. **Residue is not the workflow.** The git tree only records what + persisted. Branches are core to this family's process + (`docs/sdd_process.md` phase 3: branch-per-worktree coordination), + but they are transient scaffolding, so the deployment shows them + mostly as debris left by overloaded coordination sessions. Read + "stale branch" as "cleanup gap", not "unused feature". +3. **Do not inherit the incumbent's surface shape.** Gitea's anonymous + OpenAPI (roster, version, full endpoint catalog) is gitea's shape. + alkforge's shape is alkcall's: visible-surface = authorized-surface, + every surface an ACL-checked op, entities see only what their + grants cover, and the anonymous peer class is a granted class, not + an unauthenticated service. The only 0.1 surfaces are the two git + doors and the web pages; any future API surface goes through + alkcall's capability model, not an all-or-nothing spec. +4. **Incumbent workarounds are unmet-need signals.** A plaintext PAT + stored in gitea's DB to power push-mirrors is not "gitea feature + parity"; it is the *capability* (outbound mirroring) that matters, + re-homed per the family posture (alkvault references, injected + credentials, sect 5 item 10). Same method for any future "we only + use this tool because it is in the middle" finding. +5. **The primary user is invisible to deployment telemetry.** The + walk enumerated the outside (OSS consumers, scanners) because that + is what is observable; the dominant real user is the family's own + SDD workflow (coordinators, agents, the human), which leaves only + commit traces. Requirements should be re-derived from + `docs/sdd_process.md` workflows first, with this walk then used + to size the doors those workflows traverse and the crawl/bot + pressure the public half must survive. + +Standing framing for the version sequence (owner-stated): 0.1.0 +replicates the important day-to-day surface (git doors, minimal web +view, migration without breaking what external watchers depend on), +and gitea's broader feature catalog is a long-term backlog to be +replicated selectively after consideration, guided by the roadmap to +be built in subsequent sessions, not a checklist to port. diff --git a/docs/research/phase-0.md b/docs/research/phase-0.md index b5d9ddb..41a7bae 100644 --- a/docs/research/phase-0.md +++ b/docs/research/phase-0.md @@ -135,7 +135,16 @@ method, per-repo census, and three-bucket classification are in bounded) feeds OQ-FG-09's limits. - Migration (OQ-FG-07) is easy: ~158 MB on disk across all 52 repos, mirror-fetch + push suffices; account/key regeneration is the only - non-git work (about ten accounts, twelve ed25519 keys). + non-git work (about ten accounts, twelve ed25519 keys), plus + enumerating gitea's push-mirrors and rotating their GitHub PAT into + alkvault (never copied; assembly-layer injection, the alkhttp + bearer precedent). +- De-bias guard: the walk reads gitea's *history*, not the family's + *requirements*. Branching is load-bearing (SDD phase-3 + branch-per-worktree) despite the tree showing mostly `main`, and + zero-usage features need a "why" before deferral (see the walk + doc's sect 11 correction lenses). 0.1 replicates the important + day-to-day surface; gitea's wider catalog is a selective long-term backlog. - Residue: mostly closed. A host-access pass (read-only: logs, Postgres, on-disk sizes) resolved the visit-pattern, host-config, key-inventory, and non-git-SSH questions (walk doc's sect 8, sect @@ -349,7 +358,12 @@ config lives in alkstore rows vs a static file per deployment. Sequence the cutover: git data (alkgit import path exists? gitea's bare repos are ordinary git repos, so a clone-push migration through protocol halves is likely), account/key data regeneration into -alkvault/alkstore, and the reverse-proxy endpoint swap. Sized by +alkvault/alkstore, the reverse-proxy endpoint swap, and the push +-mirror disposition: enumerate which repos mirror to GitHub today, +rotate the stored PAT into alkvault (never copy), and decide whether +mirroring goes live in 0.1 or runs as documented hand-push until the +assembly capability lands (see walk doc sect 5 item 10). Verify a +restore point (off-host backup locations) before cutover. Sized by OQ-FG-01's findings. ### OQ-FG-08: Where does TLS terminate? @@ -375,6 +389,17 @@ with ACL at the HTTP layer, while transport-critical state changes (repo create/delete, permission grants) go through alkcall ops so the ACL model covers them uniformly. +### OQ-FG-11: Is outbound push-mirroring in 0.1, and in what shape? + +Owner-stated ideal: all public OSS repos mirrored to GitHub +(`alkfamily` internal-only; see walk doc sect 5 item 10). The +capability is required at some point (gitea relies on it), the +credential pattern is settled (alkvault reference, assembly-layer +bearer injection), but 0.1 scope is open: a built-in periodic +push-mirror capability, an operator-run job, or a documented +hand-push interim. Also sizes the migration's token-rotation step. +Disposition ties to the 0.1 feature-freeze list this phase produces. + ## 8. POC candidates None committed yet. The candidates the seeded OQs imply, in rough