feat(webui): read-only system-health API (Closes #634) #813
Merged
sysadmin
merged 3 commits from 2026-07-23 04:14:34 -05:00
feat/issue-634-readonly-system-health-api into master
Labels
Clear labels
allocator
anti-stomp
architecture
bug
chore
codex
concurrency
contamination
control-plane
dashboard
database
design
documentation
enhancement
gitea
glitchtip
important
incident
incident-bridge
integration
jenkins
labels
leases
mcp
mcp-health
mcp-menu
multi-project
mutating
nice-to-have
observability
portability
preflight
protected-branch
queue
read-only
reconnect
recovery
refactor
release
reliability
resumable-review
reviewer
roadmap
safety
security
self-hosted
sentry
stale-runtime
status:blocked
status:in-progress
status:pr-open
status:ready
terminal-lock
testing
tracker
type:bug
type:feature
type:feature
type:guardrail
visibility
workflow
workflow-hardening
workflow-hardening
Controller-owned work allocator
Prevent concurrent LLM session stomping
Architecture / structural design
OpenAI Codex client / workflow session surface
Concurrent session safety
Workflow or session contamination incident
MCP control-plane coordination and allocation authority
MCP operational dashboard/queue view
Internal coordination storage (SQLite/Postgres)
Design / investigation, no implementation
Docs / runbooks
New feature or improvement
Gitea MCP workflow
GlitchTip integration
Operational or process incident requiring durable audit trail
Sentry-to-Gitea incident bridging
Integration testing
Jenkins integration
Label taxonomy management
Lease adopt/release/expire lifecycle
MCP server / tooling
MCP namespace and runtime health
MCP menu surface
Work spanning multiple monitoring projects or Gitea repos
Mutating action; requires gating
Observability, metrics, traces, error reporting
Cross-platform / portability
Shared preflight gates before mutation
Protected branch / stable-branch policy concern
Work queue visibility and allocation
Read-only, no mutation
MCP client reconnect/reload recovery path
Recovery paths for stale/foreign leases
Code refactor / restructure
Release / versioning
Reliability / failure handling
Persist and resume prepared review verdicts across sessions
Reviewer workflow tooling
Roadmap / umbrella issue
Safety rails and fail-closed mutation guards
Security / trust boundary
Self-hosted infrastructure integration
Sentry error monitoring integration
Stale backend daemon / runtime-vs-master parity failures
Issue is blocked
Issue is being worked on
Issue has an open pull request
Issue is ready for work
Terminal review lock (#332) path
Tests / test coverage
Issue tracker hygiene / meta
Bug or defect
Feature or enhancement
Feature or enhancement
Safety gate or guardrail
Workflow state visibility for LLMs/operators
Cross-tool workflow
LLM workflow coordination hardening
LLM workflow coordination hardening
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Scaled-Tech-Consulting/Gitea-Tools#813
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #634
What this adds
GET /api/v1/system/health— a structured, read-only health surface for automated readiness checks. It is the first console API under the/api/v1prefix established by the #632 ADR; the unversioned MVP exports are untouched and remain compatibility aliases.webui/system_health.pycomposes a frozen DTO from fail-soft dependency probes: the control-plane database, the local checkout, and — opt-in via?deep=1— live Gitea reachability. Each probe carries status, reason, and latency. Required probes drive readiness; the optional Gitea probe can only degrade overallstatus, because local inventory stays serveable when the remote is unreachable. A probe that did not run leaves readiness incomplete rather than silently passing./healthis expanded additively: every MVP key is retained, plusstarted_at,uptime_seconds, and a pointer to the versioned API. It stays cheap and runs no dependency probe. The versioned route returns503when not ready, so automation can branch on the status code without parsing the body.Safety properties
mode=roURI, becauseControlPlaneDB.__init__creates directories and runs migrations — which a health check must never do. No restart or reload control is exposed; those are Phase 2, and #630 forbids process-kill recovery.stale_runtime.mutation_safeis true only when the runtime, checkout, and remote commits are all known and equal; an unfetched remote reports as indeterminate, never as safe. MCP namespaces always reportunproven, because a web process runs outside the IDE-managed MCP client and cannot invoke a namespace tool — per #543 only aclient_namespaceprobe proves that path.The network probe is TTL-cached (
WEBUI_HEALTH_PROBE_TTL_SECONDS, default 15s) so dashboard polling does not amplify into remote load.Acceptance criteria
load_system_health/snapshot_to_dict; route/api/v1/system/healthVersionInfo(git sha, describe, schema version, python),process_uptimeassess_stale_runtime;mutation_safefalse unless all three commits known and equaltests/test_webui_system_health.pydocs/webui-local-dev.md, with a sample responseNon-goals held: no restart/reload, no write dependencies, no Sentry ingestion.
Scope
Four files, all inside the issue's stated scope:
webui/system_health.py(new, 682 lines)tests/test_webui_system_health.py(new, 499 lines)webui/app.py(+34: route registration and the additive/healthfields)docs/webui-local-dev.md(+82)Test evidence
Verified against master
9eb0f29:pytest tests/test_webui_system_health.py— 40 passed, 11 subtests passed.pytest tests/ -k "webui or health"— 230 passed, 159 subtests passed.The 11 failures are the documented pre-existing master drift at
9eb0f29— the same five files and the same test names recorded as the baseline in #812:test_commit_payloads.py(6),test_issue_702_review_findings_f1_f6.py(2),test_mcp_server.py(1),test_post_merge_moot_lease.py(1),test_reconciler_supersession_close.py(1). None touchwebui/.Provenance note for the reviewer
The implementation content originated in an earlier author cycle that left it stranded and unpublished in worktree
branches/feat-issue-634-system-health-api, whose base sat 9 commits behind master. This cycle carried it forward as a patch onto a fresh worktree at current master9eb0f29— never as a file copy, so the intervening drift inwebui/app.pywas preserved — then re-ran the full test matrix above before publishing. The source worktree was read only and left untouched.Canonical PR State
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #813
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 69082-9fea2f7cb389
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-813
phase: claimed
candidate_head:
5494696227target_branch: master
target_branch_sha: none
last_activity: 2026-07-23T04:17:06Z
expires_at: 2026-07-23T04:27:06Z
blocker: none
Review verdict: APPROVE
PR #813 reviewed at head
5494696227b84148b374412e9b38d58c1eccfca5by prgs-reviewer (sysadmin). Authorjcwalker3≠ reviewer, so self-review is not in play. Scope is exactly the four files the issue names:webui/system_health.py(new),tests/test_webui_system_health.py(new),webui/app.py(route reg + additive/health),docs/webui-local-dev.md.Acceptance criteria (Closes #634)
load_system_health→ frozenSystemHealthSnapshot;snapshot_to_dict; route/api/v1/system/health. ✔VersionInfo(git sha, describe, schema version, python) andprocess_uptime(monotonic, captured at import). ✔assess_stale_runtime;mutation_safe = determinable and not stale, anddeterminablerequires checkout+remote+daemon all known. An unfetched@{upstream}yieldsremote_head=None→ not safe, with a reason. ✔tests/test_webui_system_health.pypresent; author reports 40 passed / 11 subtests (not re-run in this reviewer session). ✔ (evidence-based)docs/webui-local-dev.mdwith sample response. ✔Safety properties verified in code
sqlite3.connect(f"file:{path}?mode=ro", uri=True)— never triggersControlPlaneDB.__init__dir/migration side-effects;_gitruns onlyrev-parse/describe; no write, restart, or reload path. ✔load_system_healthalso wraps each probe_fn in try/except so a probe can never 500 the endpoint. ✔redact()/redact_url()strip userinfo, query, credential-shaped and long-opaque material; applied where probedetailembeds exception text, tometadata["endpoint"], and toprobe_errors. Static success details and local paths carry no secrets. ✔readiness_complete=Falserather than silently passing; route returns 200/503 accordingly. ✔Non-blocking observation (not a change request)
When the web process cannot observe the running MCP daemon's startup commit (the normal case),
assess_stale_runtimesubstitutescheckout_headfor the daemon dimension, somutation_safecan read true on the two genuinely-proven dimensions while the substitution is disclosed inreasons. Defensible for a read-only advisory surface and transparently reported; flagged only for merger and a futureclient_namespaceprobe (#543) awareness. No change required.The 11 full-suite failures cited match the documented
9eb0f29baseline (#812) and none touchwebui/.Canonical PR State
STATE: approved-awaiting-merge
WHO_IS_NEXT: merger
NEXT_ACTION: Independently re-verify merger eligibility (non-self-merge, still mergeable, head still
5494696) and merge PR #813 into master, then reconcile #634 closure and branch cleanup.NEXT_PROMPT:
WHAT_HAPPENED: prgs-reviewer (sysadmin) performed a native MCP formal review approving PR #813 at head
5494696after reading webui/system_health.py and webui/app.py at that head and checking scope, read-only guarantees, fail-soft probes, redaction, and readiness/status-code derivation against issue #634 AC1–5.WHY: All five acceptance criteria are met, the diff is confined to the four files the issue scopes, and the read-only/no-restart non-goals hold in code (mode=ro DB URI, read-only git probes, no write/restart/reload path). The one honesty nuance in daemon-head substitution is transparently disclosed via reasons and does not gate anything.
ISSUE: #634
HEAD_SHA:
5494696227REVIEW_STATUS: APPROVED
MERGE_READY: yes — reviewer-approved and Gitea reports mergeable; merger must still perform its own independent eligibility re-check (non-self-merge, head unchanged, mergeable) before merging.
BLOCKERS: none
VALIDATION: Reviewer read webui/system_health.py and webui/app.py at head
5494696and confirmed read-only DB access, fail-soft probes, boundary redaction, and 200/503 readiness derivation. Author-reported test evidence: focused pytest tests/test_webui_system_health.py 40 passed / 11 subtests; full suite 4358 passed with 11 pre-existing failures matching the documented9eb0f29baseline (#812), none touching webui/. Reviewer did not re-run the suite this session.NATIVE_REVIEW_PROOF: Native MCP review mutation via gitea_submit_pr_review on the prgs-reviewer stdio transport (native_mcp_transport=true, entrypoint mcp_server, pid 69082, token_fingerprint 557f1e1ec6f7ab35); reviewer PR lease recorded at comment 14664. No offline/import fallback path was used.
LAST_UPDATED_BY: prgs-reviewer (sysadmin)
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #813
issue: #634
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 25383-ebba2d11e5b5
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-813
phase: claimed
candidate_head:
6868b345eetarget_branch: master
target_branch_sha:
4f3a464a90last_activity: 2026-07-23T08:56:35Z
expires_at: 2026-07-23T09:06:35Z
blocker: none
Review verdict: APPROVE
Independent re-review of PR #813 at current head
6868b345ee53ab69eb1bd733d3b5ed490ab9bb6bby prgs-reviewer (sysadmin). Authorjcwalker3!= reviewer, so self-review is not in play. Prior approval #512 (at head5494696) went stale only because the author merged fresh master; this decision re-establishes approval at the live head.Why the prior approval still holds (verified at current head)
Read-only local git comparison
5494696..6868b345:webui/system_health.pyandtests/test_webui_system_health.pyare byte-identical to the approved head (empty diff since #512) — the 682-line implementation and 499-line test I approved are unchanged.Merge branch 'master'commits (da6a864,6868b34); every non-merge commit in the range belongs to master (#840, #822, #635, #633, #815, #812), not to this branch.webui/system_health.py(A),tests/test_webui_system_health.py(A),webui/app.py(M),docs/webui-local-dev.md(M).webui/app.pydelta vs master is exactly the additive #634 change: import ofsystem_health, additive/healthfields (started_at,uptime_seconds,system_health_apipointer), theapi_system_healthGET handler returning 200/503 onsnapshot.ready, and one route registration. Read-only (GET/HEAD/OPTIONS only); no entanglement with master's console-authz or project-registry routes; no write/restart/reload path.Acceptance criteria (Closes #634)
load_system_health-> frozen snapshot;snapshot_to_dict; route/api/v1/system/health. OKVersionInfo+process_uptime. OKmutation_safetrue only when checkout+remote+daemon commits all known and equal; unfetched remote -> not safe with a reason. OKtests/test_webui_system_health.py(unchanged since approval; author evidence 40 passed / 11 subtests; not re-run this session). OK (evidence-based)docs/webui-local-dev.md+81. OKSafety properties (unchanged, re-confirmed additive)
Read-only control-plane DB via
mode=roURI; fail-soft probes (each probe cannot 500 the endpoint); browser-boundary redaction of userinfo/query/credential-shaped text; readiness derivation where an unrun required probe leavesreadiness_complete=Falserather than passing.Non-blocking (carried from #512, no change required)
When the web process cannot observe the running daemon's startup commit,
assess_stale_runtimesubstitutescheckout_headfor the daemon dimension and discloses it inreasons— defensible for a read-only advisory surface; flagged for merger and futureclient_namespaceprobe (#543) awareness.Canonical PR State
STATE: approved-awaiting-merge
WHO_IS_NEXT: merger
NEXT_ACTION: Independently re-verify merger eligibility (non-self-merge, still mergeable, head still
6868b345, reviewer-approval at current head) and merge PR #813 into master, then reconcile #634 closure and branch cleanup.NEXT_PROMPT:
WHAT_HAPPENED: prgs-reviewer (sysadmin) re-approved PR #813 at current head
6868b345after verifying via read-only git that the approved content (webui/system_health.py, tests) is unchanged since head5494696and the head advanced only by clean master-merges, leaving the PR diff confined to the four in-scope files with an additive, read-only app.py delta.WHY: All five #634 acceptance criteria remain met at the current head; the diff is still confined to the four scoped files; read-only/no-restart guarantees hold in code; the prior approval was stale solely due to a master-merge, not new work.
ISSUE: #634
HEAD_SHA:
6868b345eeREVIEW_STATUS: APPROVED
MERGE_READY: yes — reviewer-approved at current head and Gitea reports mergeable; merger must still perform its own independent eligibility re-check (non-self-merge, head unchanged, mergeable) before merging.
BLOCKERS: none
VALIDATION: Read-only git verification at head
6868b345—diff 5494696..6868b345 -- webui/system_health.py tests/test_webui_system_health.pyempty (approved content unchanged);log --no-merges 5494696..6868b345contains only master commits;diff master...6868b345 --name-status= the four scoped files; app.py delta vs master is the additive read-only health route/fields. Author-reported test evidence: pytest tests/test_webui_system_health.py 40 passed / 11 subtests; full suite 11 pre-existing failures matching the documented baseline, none touching webui/. Reviewer did not re-run the suite this session.NATIVE_REVIEW_PROOF: Native MCP review mutation via gitea_submit_pr_review on the prgs-reviewer stdio transport (native_mcp_transport=true, entrypoint mcp_server, pid 25383, token_fingerprint 32f0166abefba239); reviewer PR lease recorded at comment 14863. No offline/import fallback path was used.
LAST_UPDATED_BY: prgs-reviewer (sysadmin)
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #813
issue: #634
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 25383-ebba2d11e5b5
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-813
phase: released
candidate_head:
6868b345eetarget_branch: master
target_branch_sha:
4f3a464a90last_activity: 2026-07-23T08:57:35Z
expires_at: 2026-07-23T09:07:35Z
blocker: manual-release
repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #813
issue: #634
reviewer_identity: sysadmin
profile: prgs-merger
session_id: 25396-65b877b55722
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr-813
phase: claimed
candidate_head:
6868b345eetarget_branch: master
target_branch_sha:
4f3a464a90last_activity: 2026-07-23T09:13:59Z
expires_at: 2026-07-23T09:23:59Z
blocker: none
Stale #332 review-decision lock cleanup (#594)
Status: APPLIED
sysadminprgs-merger2026-07-23T09:14:39.541000+00:00approveon PR feat(webui): read-only system-health API (Closes #634) (#813)closed(merged=True)1c455b6ec0f9cb761fe6248de68c17e061fb5ecd4prgs-reviewerManual deletion of session-state files is not the workflow.
This path only clears a lock when the referenced PR is merged/closed.