phase: 121_git_source_tokens
**Phase 121 final verification pass — all green** (all 4 tasks already in `complete/`; verified, no defects found, no changes needed) - Verified implementation vs phase design: migration `0021` (reversible, round-tripped via `alembic downgrade base` + `upgrade head` → head `0021`), `GitSource.token` column, `normalize_credential`/`clone_url_for`/`sanitize_url`, clone callers switched (`sync.py`, `import_docs.py`), masked token fields in add form + editor, `extra="forbid"` output shapes - Tests: `uv run pytest` → 2662 passed, 0 failed (exit 0); `uv run pytest --cov=app --cov-report=term-missing` → TOTAL **99%** (≥90% gate) - Lint/types: `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors, 0 warnings - E2E in isolation: `uv run pytest tests/e2e/test_git_source_tokens.py -v --no-cov` → **4 passed** Completion criteria: 1. Private repo (UI add or pasted embedded-token URL) clones with injected token; token absent from every API response, page text, title attr, and full HTML — **PASS** (integration raw-JSON assertions + E2E `_assert_token_nowhere`) 2. Legacy embedded-token rows still clone from stored URL; output sanitized — **PASS** (`test_sync_legacy_row_clones_with_original_stored_url`, `test_get_masks_legacy_embedded_token_row`, env-fallback masking) 3. Public/local sources byte-identical — **PASS** (verbatim-URL + no-userinfo-unchanged tests) 4. pytest / coverage / ruff / pyright — **PASS** (see above) 5. Commit + phase move — harness responsibility; task files already in `complete/`, changes left in working tree (no commit made, per protocol) Notable: no deviations; DB left at head, functional. Next pending phase: **122_image_documents** (then 123_chat_image_questions).
This commit is contained in:
+15
-6
@@ -19,10 +19,15 @@ precedence order:
|
||||
(first run, full history — no ``--depth``; an existing shallow
|
||||
checkout is unshallowed first, phase 107) or fast-forwarded
|
||||
(``git pull --ff-only``) into ``BOR_SOURCES_DIR/<repo-name>/``
|
||||
(default ``~/bor-sources``); local rows are the existing directories
|
||||
themselves, walked directly. A failing clone/pull — or a local
|
||||
directory that is missing at run time — aborts the whole run
|
||||
*before* anything is imported.
|
||||
(default ``~/bor-sources``) — with the phase-121 clone URL
|
||||
(:func:`app.rag.git_sources.clone_url_for`): the row's ``token``
|
||||
column injected as ``https://x-access-token:<token>@…`` only for
|
||||
https? rows, NULL token → the bare stored URL verbatim (public
|
||||
repos and legacy embedded-token rows clone exactly as before);
|
||||
the checkout name stays on the bare URL (credential-free); local
|
||||
rows are the existing directories themselves, walked directly. A
|
||||
failing clone/pull — or a local directory that is missing at run
|
||||
time — aborts the whole run *before* anything is imported.
|
||||
3. Fallback — the legacy ``DEFAULT_SOURCES`` (``~/Homelab`` +
|
||||
``~/Deployments``), kept for backwards compatibility (reached only
|
||||
while both the table and ``BOR_GIT_SOURCES`` are empty).
|
||||
@@ -113,7 +118,7 @@ from app.core.logging import configure_logging
|
||||
from app.db import SessionLocal
|
||||
from app.models import KbOverview
|
||||
from app.rag.folder_summaries import generate_folder_summaries, missing_folder_summaries
|
||||
from app.rag.git_sources import effective_sources
|
||||
from app.rag.git_sources import clone_url_for, effective_sources
|
||||
from app.rag.importer import ImportSummary, import_sources
|
||||
from app.rag.llm import LLMClient
|
||||
from app.rag.overview import regenerate_overview
|
||||
@@ -236,7 +241,11 @@ def _resolve_sources(
|
||||
doc_dates_by_root: dict[str, dict[str, datetime]] = {}
|
||||
for row in rows:
|
||||
if row.kind == "git":
|
||||
root = clone_or_pull(row.url, sources_root / repo_name(row.url))
|
||||
# Phase 121: the token column is injected into the clone
|
||||
# URL ONLY here (clone_url_for — NULL token → the bare
|
||||
# stored URL verbatim); repo_name stays on the bare URL
|
||||
# so the checkout directory name is credential-free.
|
||||
root = clone_or_pull(clone_url_for(row), sources_root / repo_name(row.url))
|
||||
# Phase 106 (D2): the checkout's per-file last-commit
|
||||
# dates, keyed by the SAME root string the importer
|
||||
# sees; local rows contribute nothing (mtime fallback).
|
||||
|
||||
Reference in New Issue
Block a user