molecule-ai-uptime-probe
Gitea-native uptime monitor for Molecules AI services. Replaces upptime/uptime-monitor, which died post-2026-05-06 because every code path hits api.github.com and our org tokens no longer authenticate there.
Why
upptime/uptime-monitor is structurally GitHub-coupled:
- Calls
api.github.com/repos/upptime/uptime-monitor/releasesto look up its own version - Posts probe results as commits to the host repo via the GitHub API
- Manages incidents as GitHub Issues
- Generates a static site assuming GitHub Pages
After the 2026-05-06 GitHub org suspension, none of those calls authenticate. Per feedback_no_single_source_of_truth: vendor-neutral by design, runs on our own infra.
Responsibility boundary
┌─────────────────────────────────────────────────┐
│ This binary │
.upptimerc.yml ──▶ │ 1. parse config (upptime-compatible) │ ──▶ stdout: JSON
│ 2. probe each URL in parallel │
│ 3. emit Result{timestamp,name,url,latency, │ ──▶ history/<slug>.jsonl
│ status_code,success,error} │ (one line per check)
└─────────────────────────────────────────────────┘
The binary owns only probing and result encoding. Scheduling, result publication, and public-site deployment belong to separate consumers. A green build of this repository does not prove any of those downstream boundaries.
Live status integration and proposed hardening
At the 2026-07-15 audit, Live status main
(ff9dcbd71f84092539edc6c9eefab643bbab7967) had this integration:
- scheduled the probe every five minutes but checked out mutable
mainfrom this repository rather than an exact commit; - swallowed the probe's non-zero exit and did not validate a complete current result plus history append for every configured site before publishing;
- seeded and committed history to
uptime-probe-results; and - carried status-page configuration whose same-origin
/data/*source resolved themainbranch. The public configuration matched that source.
molecule-ai-status#45 proposes to pin an exact probe commit, validate the
complete run, publish only validated results, and point the checked-in static UI
at uptime-probe-results. Those guarantees were proposed, not current at the
audit. Treat them as current only after that change is merged and a subsequent
scheduled run verifies the new path.
The results commit and the public-site publisher are distinct boundaries. The public-site publication is not proven by a successful probe run; the publisher, cache behavior, and response-header ownership remain unresolved until a deployment owner separately publishes and verifies the root UI, data route, and headers. This repository makes no hosting-provider or rebuild-owner claim.
Usage
# Build
go build -o uptime-probe ./cmd/probe
# Run with default config
./uptime-probe -config .upptimerc.yml
# Run + append per-site history files
./uptime-probe -config .upptimerc.yml -history-dir ./history
# Custom probe timeout / concurrency
./uptime-probe -config .upptimerc.yml -timeout 10s -concurrency 16
Exit codes:
0— every probe succeeded1— one or more sites returned a non-success status (status-code mismatch, latency cap, or connection failure)2— flag/configuration failure, no configured sites, or failure to encode the result array to stdout
History append failures are reported but remain non-fatal: the complete result
array has already been written to stdout. An orchestrator that publishes
history must validate every append before committing. At the audit, live status
main did not provide that complete-run guarantee; the
molecule-ai-status#45 hardening proposed it.
Config compatibility
The probe consumes the existing .upptimerc.yml shape so no migration is needed:
sites:
- name: Customer app
url: https://app.moleculesai.app
# optional fields:
expectedStatusCodes: [200, 201] # default: 200..208, 226
method: GET # default: GET
maxResponseTime: 3000 # ms, default: no cap
headers:
- "Origin: https://moleculesai.app"
Or use a map for ergonomics:
sites:
- name: Customer app
url: https://app.moleculesai.app
headers:
Origin: https://moleculesai.app
X-Custom-Auth: token
The binary ignores unrelated top-level Upptime keys (owner, repo,
status-website, theme, and similar). That compatibility applies to this
binary only: the status hardening's proposed validator accepts only name and
url in its deliberately narrower publication contract. Add other probe
options there only after that validator is expanded in the same change.
What this binary deliberately doesn't do
- Talk to
api.github.com. The whole point. - Manage issues / commits / status badges. Out-of-band orchestration concerns.
- Render or publish the status page. Those are separate status-repository and deployment-owner concerns.
Build provenance
Local development builds from a checked-out revision with the commands above.
At the audit, live status main built mutable main; exact-commit provenance
was a proposed status hardening and must not be inferred from this repository
alone.
go.mod retains go.moleculesai.app/uptime-probe as the module identifier, but
this README does not treat it as an installation endpoint. No live vanity
resolver is claimed; do not publish a go install ...@latest instruction until
that resolver and version path are verified end to end.
Tracking
- Replacement plan:
molecule-ai/molecule-ai-status#2 - Status publication hardening:
molecule-ai/molecule-ai-status#45 - Original vanity import plan:
molecule-ai/internal#71