gitea-saas-core/gitea_saas
Claude 08febd56ca fix(dashboard): require X-API-Key on /dashboard (fail-closed, #25)
The HTML operator page served the same clients/ledger/queue/review data as
the authenticated JSON summary, but with no auth at all. The loopback
requirement it relied on existed only as prose (page note + docstring); it
was never enforced by mount_dashboard, which does not own the app and
cannot constrain the bind address.

Put /dashboard behind the same _guard as /api/dashboard/summary:
- no X-API-Key -> 401, no billing data
- no configured key -> 503 (fail-closed)
- valid key -> 200 HTML (unchanged rendering)

Also drop the now-false 'loopback-only' security claims from the page note
and the mount_dashboard docstring, and update the tests:
- test_dashboard_page_open_and_html now sends a valid key
- new test_dashboard_page_guard_blocks_anonymous_access: no key -> 401,
  body contains no client data (mutation check: fails if guard removed)
- new test_dashboard_wrong_key_same_length_rejected: wrong same-length
  key -> 401 on HTML page too
- test_summary_fail_closed_without_configured_key now asserts the HTML
  page also fails closed (503), not open
- test_dashboard_mounts_onto_existing_app sends a valid key

/api/dashboard/summary behaviour unchanged. Suite: 160 passed, 1 skipped
(before: 158 passed, 1 skipped).
2026-08-26 02:54:37 -05:00
..
billing_core.py gitea-saas-core#16: billing core client API consistency (id, flat records, list_clients) 2026-08-25 06:09:46 -05:00
config.py Merge origin/issue-2 into issue-6 (bounce fix: mount review routes on #2's app, drop duplicate gitea_client.py, adopt #16 id rename) 2026-08-25 11:08:50 -05:00
dashboard.py fix(dashboard): require X-API-Key on /dashboard (fail-closed, #25) 2026-08-26 02:54:37 -05:00
db.py gitea-saas-core#1: billing ledger core (clients/ledger/holds, idempotent, fail-closed) 2026-08-25 04:16:35 -05:00
delivery.py gitea-saas-core#7: adopt #16 core shape (create_client id key, flat get_client) 2026-08-25 11:20:55 -05:00
gitea_client.py gitea-saas-core#8: drop gitea_client.py per bounce — issue #4 owns it (via !21/!23); keep real-client skip-guard 2026-08-25 16:18:38 -05:00
intake_eval.py gitea-saas-core#8: canonical gitea_client + list_issue_comments, #16 id rename, real-request test 2026-08-25 11:32:18 -05:00
intake_factory.py gitea-saas-core#4: constant-time API-key check via API_KEY_HEADER 2026-08-25 11:36:52 -05:00
review_policy.py gitea-saas-core#6: review policy + merge loop (tier auto-merge, bounce routing, delivery debit) 2026-08-25 05:29:55 -05:00
reviewer.py gitea-saas-core#5: review gate — automated PR reviewer (acceptance parse, tests, verdicts) 2026-08-25 04:31:08 -05:00
schema.sql gitea-saas-core#1: billing ledger core (clients/ledger/holds, idempotent, fail-closed) 2026-08-25 04:16:35 -05:00
server.py fix(#9): bounce — #16 id-key API + mount dashboard onto app factory 2026-08-25 11:38:54 -05:00
stripe_client.py gitea-saas-core#3: fail-closed Stripe credential resolution (bounce fix) 2026-08-25 06:00:36 -05:00