[BOUNTY #5905] Health Dashboard#12
Conversation
Dynamically generates sitemaps for all UBQ.FI apps and plugins. - /sitemap.xml: Standard XML sitemap for search engines - /sitemap.json: Machine-readable JSON index for interop Apps (static): root, www, pay, work, dashboard, docs Plugins (dynamic): fetched from ubiquity-os-marketplace GitHub org Both endpoints cached for 1 hour (Cache-Control). Closes ubiquity#2 (linked from devpool-directory #5906)
Real-time status monitoring for all UBQ.FI services. Endpoints: - /health-dashboard — HTML dashboard (dark theme, auto-styled) - /health.json — JSON API Features: - Checks all app subdomains (pay, work, dashboard, docs) - Dynamically discovers plugins from ubiquity-os-marketplace org - 5s timeout per check - Status: healthy (2xx) / degraded (4xx) / unhealthy (5xx/timeout) - Summary cards: total, healthy, degraded, unhealthy - Response time and HTTP status per service - Interops with Plugin Health Monitor (ubiquity-os/.github#12) Closes ubiquity#3 (linked from devpool-directory #5905)
📝 WalkthroughWalkthroughThis pull request introduces a health monitoring system and sitemap generation for UBQ.FI services. A new 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
src/sitemap.ts (1)
51-51: Unused type field:pushed_atis declared but never used.Either use it for
lastmodentries or remove from type.src/health-dashboard.ts (1)
206-211: Minor XSS consideration: plugin/app names are inserted into HTML without escaping.If a malicious repo name contained
<script>, it would execute. Low risk since names come from GitHub API, but worth sanitizing.Add escapeHtml helper
function escapeHtml(str: string): string { return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); }Then use:
${escapeHtml(a.name)}and${escapeHtml(p.name)}in the template.Also applies to: 219-224
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2a00ddec-86dc-442a-adb6-b337ee290a4d
📒 Files selected for processing (3)
src/health-dashboard.tssrc/sitemap.tssrc/worker.ts
| * Checks availability of all apps and plugins. | ||
| */ | ||
|
|
||
| const APP_SUBDOMAINS = ["pay", "work", "dashboard", "docs"] as const; |
There was a problem hiding this comment.
APP_SUBDOMAINS differs from sitemap.ts:6-13.
Sitemap includes root ("") and "www", health dashboard doesn't. Consider unifying or intentionally documenting the difference.
| async function fetchPluginRepos(): Promise<string[]> { | ||
| try { | ||
| const res = await fetch(`${GITHUB_API}/orgs/ubiquity-os-marketplace/repos?per_page=100&sort=updated`, { | ||
| headers: { Accept: "application/vnd.github.v3+json", "User-Agent": "ubq-fi-health" }, | ||
| }); | ||
| if (!res.ok) return []; | ||
| const repos: Array<{ name: string }> = await res.json(); | ||
| return repos | ||
| .filter((r) => !r.name.startsWith(".") && !["command-config"].includes(r.name)) | ||
| .map((r) => r.name); | ||
| } catch { | ||
| return []; | ||
| } | ||
| } |
There was a problem hiding this comment.
Exclusion list mismatch with sitemap.ts:55.
This function only excludes "command-config", while sitemap.ts excludes 11 repos (command-, daemon-). Health dashboard will show plugins that sitemap.xml filters out.
Proposed fix: Extract shared exclusion list
Create a shared constant in a utils file:
// src/utils/plugin-config.ts
export const EXCLUDED_REPOS = [
"command-config",
"command-wallet",
"command-query",
"daemon-pricing",
"daemon-merging",
"daemon-disqualifier",
"daemon-task-matcher",
"daemon-planner",
"daemon-xp",
"daemon-spec-rewriter",
];Then import and use in both files.
| </table> | ||
| </section> | ||
|
|
||
| <p class="generated">Generated: ${data.generated} • <a href="/health.json">JSON API</a> • <a href="/health-history">History</a></p> |
There was a problem hiding this comment.
Dead link: /health-history endpoint doesn't exist.
Remove the link or implement the endpoint.
Quick fix: Remove unimplemented link
- <p class="generated">Generated: ${data.generated} • <a href="/health.json">JSON API</a> • <a href="/health-history">History</a></p>
+ <p class="generated">Generated: ${data.generated} • <a href="/health.json">JSON API</a></p>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <p class="generated">Generated: ${data.generated} • <a href="/health.json">JSON API</a> • <a href="/health-history">History</a></p> | |
| <p class="generated">Generated: ${data.generated} • <a href="/health.json">JSON API</a></p> |
| const APP_SUBDOMAINS = [ | ||
| "", | ||
| "www", | ||
| "pay", | ||
| "work", | ||
| "dashboard", | ||
| "docs", | ||
| ] as const; |
There was a problem hiding this comment.
APP_SUBDOMAINS includes root ("") and "www" here, but health-dashboard.ts uses a different set without these.
This mismatch means sitemap shows 6 apps while health dashboard shows 4.
Also applies to: 89-95
| async function fetchPluginRepos(): Promise<string[]> { | ||
| const res = await fetch(`${GITHUB_API}/orgs/ubiquity-os-marketplace/repos?per_page=100&sort=updated`, { | ||
| headers: { | ||
| "Accept": "application/vnd.github.v3+json", | ||
| "User-Agent": "ubq-fi-sitemap-generator", | ||
| }, | ||
| }); | ||
|
|
||
| if (!res.ok) { | ||
| console.error(`Failed to fetch plugin repos: ${res.status}`); | ||
| return []; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check how many repos exist in ubiquity-os-marketplace
curl -s "https://api.github.com/orgs/ubiquity-os-marketplace" | jq '.public_repos'Repository: ubiquity/ubq.fi-router
Length of output: 68
🏁 Script executed:
# Check the full sitemap.ts file to understand cache implementation
cat -n src/sitemap.tsRepository: ubiquity/ubq.fi-router
Length of output: 4319
🏁 Script executed:
# Search for all GitHub API calls in the codebase
rg "github\.com|GITHUB_API" -A 3 -B 3Repository: ubiquity/ubq.fi-router
Length of output: 1601
🏁 Script executed:
# Search for cache-related code
rg "cache|Cache" -t tsRepository: ubiquity/ubq.fi-router
Length of output: 512
Add optional GitHub token support to avoid rate limiting issues.
Unauthenticated GitHub API calls are rate-limited to 60 requests/hour per IP. The 1-hour cache helps, but this function is also called from src/health-dashboard.ts (duplicate implementation), doubling request frequency. With multiple workers, cache bypasses, or both calls active simultaneously, 60 requests/hour becomes tight. Accept an optional GITHUB_TOKEN environment variable.
The per_page=100 without pagination is fine—the org has only 15 public repos.
| return repos | ||
| .filter((r) => !r.name.startsWith(".") && !["command-config", "command-wallet", "command-query", "daemon-pricing", "daemon-merging", "daemon-disqualifier", "daemon-task-matcher", "daemon-planner", "daemon-xp", "daemon-spec-rewriter", "daemon-xp"].includes(r.name)) | ||
| .map((r) => r.name); |
There was a problem hiding this comment.
Duplicate entry in exclusion list: "daemon-xp" appears twice.
Also, this exclusion list differs from health-dashboard.ts:78 which only excludes "command-config". This inconsistency means sitemap and health dashboard will advertise different plugin sets.
Proposed fix
- .filter((r) => !r.name.startsWith(".") && !["command-config", "command-wallet", "command-query", "daemon-pricing", "daemon-merging", "daemon-disqualifier", "daemon-task-matcher", "daemon-planner", "daemon-xp", "daemon-spec-rewriter", "daemon-xp"].includes(r.name))
+ .filter((r) => !r.name.startsWith(".") && !["command-config", "command-wallet", "command-query", "daemon-pricing", "daemon-merging", "daemon-disqualifier", "daemon-task-matcher", "daemon-planner", "daemon-xp", "daemon-spec-rewriter"].includes(r.name))Consider extracting this list to a shared constant used by both sitemap.ts and health-dashboard.ts.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return repos | |
| .filter((r) => !r.name.startsWith(".") && !["command-config", "command-wallet", "command-query", "daemon-pricing", "daemon-merging", "daemon-disqualifier", "daemon-task-matcher", "daemon-planner", "daemon-xp", "daemon-spec-rewriter", "daemon-xp"].includes(r.name)) | |
| .map((r) => r.name); | |
| return repos | |
| .filter((r) => !r.name.startsWith(".") && !["command-config", "command-wallet", "command-query", "daemon-pricing", "daemon-merging", "daemon-disqualifier", "daemon-task-matcher", "daemon-planner", "daemon-xp", "daemon-spec-rewriter"].includes(r.name)) | |
| .map((r) => r.name); |
Summary
Real-time health dashboard for all UBQ.FI apps and plugins, built directly into the Cloudflare Worker router.
Endpoints
/health-dashboard/health.jsonFeatures
ubiquity-os-marketplaceGitHub orgInterop
Works with the Plugin Health Monitor cron job for alerting.
Closes #3 (linked from devpool-directory #5905)