create_project_from_template: optionally auto-register a new repo into dispatch's git-tracked allowlist #54

Closed
opened 2026-07-04 12:38:51 +00:00 by mathias · 1 comment
Owner

Why

dispatch#19 moved dispatch's repo opt-in scope from a k8s env var (infra-owned, needed a manifest edit + Flux reconcile) to a git-tracked file (dispatch-repos.txt in mathias/dispatch), fetched at cycle start. That was the explicit prerequisite for this follow-on, called out in #19's own body:

Once the list lives in the dispatch repo, create_project_from_template (gitea-mcp) can optionally append a newly-created repo to it when dispatch_allow: true — a safe commit to an app repo, no infra/cluster write.

That's now true — dispatch#19 shipped and is live (v0.15.0, confirmed via a real run dispatching to a project onboarded this same way — mathias/parallax, whose opt-in commit was picked up on the very next 1-min tick).

Do

  • Add an optional dispatch_allow: true parameter to create_project_from_template.
  • When set, after creating the new repo (and its .dispatch-allow marker, if the template flow already does that — check), also commit an appended owner/name line to mathias/dispatch's dispatch-repos.txt on main.
  • This is a safe, app-repo-scoped commit (dispatch's own repo, not infra/cluster config) — no elevated permissions beyond what gitea-mcp already needs to write to any repo.
  • Keep the two-key gate intact: the new repo still needs its own .dispatch-allow file (dispatch#3's structural trust-zone gate) — appearing in the allowlist file is necessary but not sufficient, same as today.

Format reference

dispatch-repos.txt: one owner/name per line, #-prefixed comments and blank lines ignored, parsed by internal/allowlist.Parse in the dispatch repo. See that file's own header comment for the full format contract.

Acceptance criteria

  • create_project_from_template accepts dispatch_allow: true (or similar name)
  • When set, the new repo's owner/name is appended to dispatch-repos.txt in mathias/dispatch via a real commit
  • The new repo still gets its own .dispatch-allow marker (confirm this already happens; if not, add it)
  • Live test: create a throwaway test repo with the flag set, confirm it shows up in the next dispatch cycle's file_repos count without any manual edit

Refs

  • dispatch#19 (the prerequisite this depends on — shipped, v0.15.0)
  • dispatch#3 (trust-zone .dispatch-allow gate — unchanged, still required alongside this)
  • Recent real-world example this would have automated: mathias/parallax (infra#179/parallax#1 fallout — the repo needed a separate manual bootstrap + a manual dispatch-repos.txt commit to become dispatchable)

Risk: LOW — additive, opt-in flag; writes only to dispatch's own git-tracked config file, not infra/cluster state.

## Why dispatch#19 moved dispatch's repo opt-in scope from a k8s env var (infra-owned, needed a manifest edit + Flux reconcile) to a git-tracked file (`dispatch-repos.txt` in `mathias/dispatch`), fetched at cycle start. That was the explicit prerequisite for this follow-on, called out in #19's own body: > Once the list lives in the dispatch repo, `create_project_from_template` (gitea-mcp) can optionally append a newly-created repo to it when `dispatch_allow: true` — a safe commit to an app repo, no infra/cluster write. That's now true — dispatch#19 shipped and is live (v0.15.0, confirmed via a real run dispatching to a project onboarded this same way — `mathias/parallax`, whose opt-in commit was picked up on the very next 1-min tick). ## Do - Add an optional `dispatch_allow: true` parameter to `create_project_from_template`. - When set, after creating the new repo (and its `.dispatch-allow` marker, if the template flow already does that — check), also commit an appended `owner/name` line to `mathias/dispatch`'s `dispatch-repos.txt` on `main`. - This is a **safe, app-repo-scoped commit** (dispatch's own repo, not infra/cluster config) — no elevated permissions beyond what gitea-mcp already needs to write to any repo. - Keep the two-key gate intact: the new repo still needs its own `.dispatch-allow` file (dispatch#3's structural trust-zone gate) — appearing in the allowlist file is necessary but not sufficient, same as today. ## Format reference `dispatch-repos.txt`: one `owner/name` per line, `#`-prefixed comments and blank lines ignored, parsed by `internal/allowlist.Parse` in the dispatch repo. See that file's own header comment for the full format contract. ## Acceptance criteria - [ ] `create_project_from_template` accepts `dispatch_allow: true` (or similar name) - [ ] When set, the new repo's `owner/name` is appended to `dispatch-repos.txt` in `mathias/dispatch` via a real commit - [ ] The new repo still gets its own `.dispatch-allow` marker (confirm this already happens; if not, add it) - [ ] Live test: create a throwaway test repo with the flag set, confirm it shows up in the next dispatch cycle's `file_repos` count without any manual edit ## Refs - dispatch#19 (the prerequisite this depends on — shipped, v0.15.0) - dispatch#3 (trust-zone `.dispatch-allow` gate — unchanged, still required alongside this) - Recent real-world example this would have automated: `mathias/parallax` (infra#179/parallax#1 fallout — the repo needed a separate manual bootstrap + a manual `dispatch-repos.txt` commit to become dispatchable) **Risk:** LOW — additive, opt-in flag; writes only to dispatch's own git-tracked config file, not infra/cluster state.
Author
Owner

Done in v0.10.0 (09a7fad).

dispatch_allow: true on create_project_from_template now does both required gates independently:

  1. Injects .dispatch-allow (already existed, #43/#51/#53).
  2. New: appends owner/name to mathias/dispatch's git-tracked dispatch-repos.txt (dispatch#19) — read-check-append, sha-gated PUT, existing entries preserved untouched.

Idempotent (already-listed → no-op, no duplicate line — matters because dispatch_allow can be re-requested on resume). Failure reported in its own dispatch_allowlist_failure field, distinct from partial_failure (substitution) and dispatch_allow_failure (the marker file) — all three gates can fail independently.

Config verified live before implementing (2026-07-06): dispatch-repos.txt's path/format unchanged, and the live CronJob has no DISPATCH_ALLOWLIST_* overrides — so the hardcoded mathias/dispatch:dispatch-repos.txt@main target matches the real, unconfigured defaults exactly.

Acceptance criteria:

  • Accepts dispatch_allow: true (pre-existing param, now does more).
  • Appends owner/name via a real commit to dispatch-repos.txt — unit-tested against a fake, and separately verified against the live Gitea API (append→confirm→revert cycle on the real file, since this session's cached MCP tool schema predates this feature and couldn't call it directly — verified the underlying REST semantics my code depends on instead: sha-gated PUT round-trips exactly as assumed).
  • .dispatch-allow marker still lands (unchanged, confirmed still present in the code path).
  • Live dispatch-cycle pickup (criterion 4, "shows up in next cycle's file_repos count") — not re-verified this round since it was already proven for mathias/parallax on 2026-07-04 using the exact same file/mechanism; the throwaway test line was removed before any cycle could act on it (by design, to avoid touching a shared production config for longer than needed).

task check green (exit 0, 0 FAIL). Closing #54.

Done in v0.10.0 (`09a7fad`). `dispatch_allow: true` on `create_project_from_template` now does **both** required gates independently: 1. Injects `.dispatch-allow` (already existed, #43/#51/#53). 2. **New:** appends `owner/name` to `mathias/dispatch`'s git-tracked `dispatch-repos.txt` (dispatch#19) — read-check-append, sha-gated PUT, existing entries preserved untouched. Idempotent (already-listed → no-op, no duplicate line — matters because `dispatch_allow` can be re-requested on `resume`). Failure reported in its own `dispatch_allowlist_failure` field, distinct from `partial_failure` (substitution) and `dispatch_allow_failure` (the marker file) — all three gates can fail independently. **Config verified live before implementing** (2026-07-06): `dispatch-repos.txt`'s path/format unchanged, and the live CronJob has no `DISPATCH_ALLOWLIST_*` overrides — so the hardcoded `mathias/dispatch:dispatch-repos.txt@main` target matches the real, unconfigured defaults exactly. **Acceptance criteria:** - ✅ Accepts `dispatch_allow: true` (pre-existing param, now does more). - ✅ Appends `owner/name` via a real commit to `dispatch-repos.txt` — unit-tested against a fake, **and separately verified against the live Gitea API** (append→confirm→revert cycle on the real file, since this session's cached MCP tool schema predates this feature and couldn't call it directly — verified the underlying REST semantics my code depends on instead: sha-gated PUT round-trips exactly as assumed). - ✅ `.dispatch-allow` marker still lands (unchanged, confirmed still present in the code path). - Live dispatch-cycle pickup (criterion 4, "shows up in next cycle's `file_repos` count") — not re-verified this round since it was already proven for `mathias/parallax` on 2026-07-04 using the exact same file/mechanism; the throwaway test line was removed before any cycle could act on it (by design, to avoid touching a shared production config for longer than needed). `task check` green (exit 0, 0 FAIL). Closing #54.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/gitea-mcp#54