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:

  1. Calls api.github.com/repos/upptime/uptime-monitor/releases to look up its own version
  2. Posts probe results as commits to the host repo via the GitHub API
  3. Manages incidents as GitHub Issues
  4. 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 main from 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 the main branch. 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 succeeded
  • 1 — 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
S
Description
Gitea-native uptime probe — reads .upptimerc.yml-compatible config, emits JSON results. Replaces upptime/uptime-monitor (api.github.com-coupled, dead post-2026-05-06). Closes molecule-ai-status#2.
Readme
69 KiB
Languages
Go 100%