phase: 173_docs_push_creds_split
Build and Push Containers / build-and-push-app (push) Successful in 1m41s
Build and Push Containers / build-and-push-db (push) Successful in 11s

All gates green. Final report:

**Phase 173 — final verification pass (all tasks already complete in `complete/`)**

- Verified the full implementation is in the working tree: `docs_user`/`docs_token` settings + catalogue rows (task 01), `docs_repo` PUT 422 guard + `docs_token` write-only pin (task 02), `run_git(env)` + `push_document(user, token)` credential env (task 03), `settings_migrate.py` wired into `create_app()` (task 04), E2E suite (task 05).
- **Completion criteria:**
  1. GET `/api/admin/settings` lists `docs_user` (plain) + `docs_token` (secret, `value=null`), token never in any body — ✅ `test_docs_token_is_write_only_masked_end_to_end` + E2E sentinel-absent-from-DOM
  2. PUT `docs_repo` with `://user:pass@` → 422 naming the fields; clean URL passes — ✅ integration + E2E UI-side
  3. Token set → `GIT_CURL_USERNAME`/`GIT_CURL_PASSWORD`/`GIT_TERMINAL_PROMPT=0` on every git step; empty → `env=None` — ✅ mocked-git unit tests
  4. Legacy env split once at startup, idempotent, one INFO line, `.env` untouched — ✅ `test_settings_migrate.py` (4 shapes) + `test_docs_push_migrate.py`
  5. Full suite green, coverage >90%, lint clean — ✅
  6. E2E isolated: `test_docs_push_creds.py` 4/4; regression set (panel + layout + response_to_docs) 21/21 — ✅
  7. Commit + phase move — harness's job (per instructions, not mine).
  8. README/AGENTS consistent — ✅ (below)
- Tests/lint: `uv run pytest` exit 0 (4112 passed) · `uv run pytest --cov=app --cov-report=term-missing` TOTAL 99% · `uv run ruff check .` clean · `uv run pyright` 0 errors
- Docs: README.md (incl. Docs-push config section, guard/migration paragraph, `.env.example` block) and AGENTS.md verified consistent in full; fixed two stale docstrings in `app/config.py` + `app/core/settings_catalog.py` (`is_set` → the API's actual `has_value` field).
- No live-infrastructure changes (no live step in this phase). No next pending phase — `todo/` held only 173.
This commit is contained in:
2026-10-10 16:47:39 -04:00
parent f27106a638
commit a86caec821
56 changed files with 3177 additions and 39 deletions
+36
View File
@@ -665,6 +665,42 @@ def test_docs_branch_env_override(monkeypatch: pytest.MonkeyPatch) -> None:
assert s.docs_base_branch == "master"
def test_docs_creds_defaults_are_empty(monkeypatch: pytest.MonkeyPatch) -> None:
"""Phase 173 (task 01, C5): no credentials by default — the push is
anonymous/URL-credential-free, exactly as before this phase."""
monkeypatch.delenv("BOR_DOCS_USER", raising=False)
monkeypatch.delenv("BOR_DOCS_TOKEN", raising=False)
s = _settings()
assert s.docs_user == ""
assert s.docs_token == ""
def test_docs_creds_env_overrides(monkeypatch: pytest.MonkeyPatch) -> None:
"""Phase 173 (task 01): ``BOR_DOCS_USER`` / ``BOR_DOCS_TOKEN``
resolve verbatim — plain ``str``, no coercion."""
monkeypatch.setenv("BOR_DOCS_USER", "alice")
monkeypatch.setenv("BOR_DOCS_TOKEN", "tok")
s = _settings()
assert s.docs_user == "alice"
assert s.docs_token == "tok"
def test_docs_creds_empty_env_stays_empty(monkeypatch: pytest.MonkeyPatch) -> None:
"""Phase 173 (task 01, C5): an empty (or whitespace) env value stays
``""`` / verbatim — no coercion, no normalization away from empty.
The anonymous state must stay expressible: the settings must NOT
strip the token, or an explicit empty would become a set credential.
(Whitespace is stored verbatim, like ``docs_repo``; the *push*
service decides the empty-vs-set semantics, not the settings.)"""
monkeypatch.setenv("BOR_DOCS_USER", "")
monkeypatch.setenv("BOR_DOCS_TOKEN", "")
s = _settings()
assert s.docs_user == ""
assert s.docs_token == ""
monkeypatch.setenv("BOR_DOCS_TOKEN", " ")
assert _settings().docs_token == " "
def test_docs_work_dir_env_override_is_raw_string(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("BOR_DOCS_WORK_DIR", "/data/bor/docs")
s = _settings()