From 6531bcc0f1b77b561bf80bf5d5a40306d5d34b88 Mon Sep 17 00:00:00 2001 From: "m2 (AI Agent)" Date: Thu, 2 Jul 2026 05:52:20 +0200 Subject: [PATCH] web: Forgejo basic auth (token-scheme headers 401 on this instance) Co-Authored-By: Claude Fable 5 --- web/backend/src/m2_market_web/ledger.py | 10 +++++++++- web/backend/src/m2_market_web/registry.py | 7 ++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/web/backend/src/m2_market_web/ledger.py b/web/backend/src/m2_market_web/ledger.py index 652e635..d0ca314 100644 --- a/web/backend/src/m2_market_web/ledger.py +++ b/web/backend/src/m2_market_web/ledger.py @@ -35,12 +35,20 @@ def _registry_raw_url(path: str) -> str: return f"{forgejo}/{repo}/raw/branch/main/{path}" +def _b64(raw: str) -> str: + import base64 + + return base64.b64encode(raw.encode()).decode() + + async def _latest_audit_date() -> str: today = date.today().isoformat() forgejo = os.environ["FORGEJO_URL"].rstrip("/") repo = os.environ["REGISTRY_REPO"].strip("/") token = os.environ.get("FORGEJO_TOKEN", "") - headers = {"Authorization": f"token {token}"} if token else {} + user = os.environ.get("FORGEJO_USER", "m2") + # this Forgejo instance rejects token-scheme headers; HTTP basic only (forgejo skill) + headers = {"Authorization": "Basic " + _b64(f"{user}:{token}")} if token else {} async with client(forgejo, headers) as http: response = await http.get(f"/api/v1/repos/{repo}/contents/audit", params={"ref": "main"}) response.raise_for_status() diff --git a/web/backend/src/m2_market_web/registry.py b/web/backend/src/m2_market_web/registry.py index e24c882..3117e68 100644 --- a/web/backend/src/m2_market_web/registry.py +++ b/web/backend/src/m2_market_web/registry.py @@ -21,8 +21,13 @@ def _repo() -> str: def _headers() -> dict[str, str]: + import base64 + token = os.environ["FORGEJO_TOKEN"] - return {"Authorization": f"token {token}"} + user = os.environ.get("FORGEJO_USER", "m2") + # this Forgejo instance rejects token-scheme headers; HTTP basic only (forgejo skill) + basic = base64.b64encode(f"{user}:{token}".encode()).decode() + return {"Authorization": f"Basic {basic}"} def _age_days(created_at: str | None) -> int: