Files
brain-of-reese/.agent/user_stories/git-sources-admin.md
T

2.7 KiB
Raw Blame History

Story: Admin Page to Add / Remove Git Sources

Phase: 35_git_sources_admin · E2E: tests/e2e/test_git_sources_admin.py

Narrative

As the admin (owner), today I manage the git repos that feed the knowledge base by editing BOR_GIT_SOURCES in .env and restarting. I want a page only I can access where I can add and remove git sources — no env file, no restart — and have the Sync button (phase 32) and import_docs (phase 28) use that stored list.

  • Given I am signed in as admin
  • When I open the Git sources page and add a repo URL (or remove one)
  • Then the change is stored in Postgres (git_sources table) and the next sync / import uses the stored list — the BOR_GIT_SOURCES env var remains only a fallback while the table is empty, and phase 32's fail-loud "no git sources configured" is preserved when both are empty.

Acceptance criteria

  1. Migration 0006: git_sources (id UUID PK, url TEXT UNIQUE NOT NULL, added_at TIMESTAMPTZ) — reversible, integration-tested up/down (existing migration-test pattern).
  2. Admin-only API (phase 16 pattern — 403 admin only anonymous): GET /api/git-sources (DB rows in added order; while the table is empty, the env list with from_env: true), POST /api/git-sources {url} (trimmed, 1–500 chars, https?:// / ssh:// / git@ shape, 409 on duplicate with a detail that never echoes the URL), DELETE /api/git-sources/{id} (204 / 404).
  3. effective_git_sources() shared by app/api/sync.py::_run_sync and scripts/import_docs.py: DB rows win, env fallback only while the table is empty, fail-loud unchanged when both are empty; the sync log line records the list origin (origin=db|env).
  4. /git-sources.html — soft-gated like the Sources page (anonymous: sign-in gate) with the standard header (phase 34) and an admin-only "Git sources" nav link on all five pages (phase 29 pattern): sources list (mono URL + added date + per-row Remove), an add form (labeled input + Add, inline error, never-stale button per §7.4), an env-fallback note while the table is empty, and a hint that the KB itself updates via the Sync button.
  5. .env.example + README: BOR_GIT_SOURCES documented as the empty-table fallback; the admin page is the primary management UI.
  6. Unit + integration green, app/ coverage >90%, story E2E green in isolation, ruff + pyright clean, one --no-gpg-sign commit.

Playwright Mapping Rule

tests/e2e/test_git_sources_admin.py — one story, one file, run in isolation: anonymous gets the sign-in gate (and 403s on the API); the admin adds/removes sources on the page (the list updates live, invalid input gets an inline error) and reaches the page via the "Git sources" nav link on every page.