Skip to content

uptime: partner API for fleet monitors (w3bs.org, threatcrush.com) - #404

Merged
sh1pt-actions-fleet[bot] merged 1 commit into
masterfrom
feat/uptime-partner-api
Oct 29, 2026
Merged

sh1pt-actions-fleet[bot] merged 1 commit into
masterfrom
feat/uptime-partner-api

Conversation

@sh1pt-actions-fleet

Copy link
Copy Markdown
Contributor

Piece 2 of the fleetbar feature: first-party apps manage a crawlproof user's monitors server to server.

Endpoints (/api/uptime/v1, JSON, errors { error, message })

  • GET|PUT /settings { keys_url, alert_email, alert_phone } (keys_url must be https://app.logicsrc.com/k/lks_….json)
  • GET /keys (keyring fetched server-side, 10 min cache)
  • GET|POST /monitors, GET|PATCH|DELETE /monitors/:id, GET /monitors/:id/incidents

Auth: Authorization: Bearer cpu_… (table uptime_partners, sha256 stored, scripts/mint-uptime-partner.ts <name>) + X-Fleet-User-Email, mapped to the crawlproof user with that confirmed email (uptime_user_id_by_email, service_role only). Unknown email: 404 no_crawlproof_account + signup_url.

Scope: the user's one Fleet project (projects.kind = 'fleet', unique per owner, made on first use). Monitors are always filtered by that project id; another user's monitor id is a 404.

Keyring SSH checks: ssh: { username, fingerprint } resolves the key from the user's logicsrc share link and stores { username, fingerprint, keys_url, key_comment, public_key (snapshot) }. The worker resolves by fingerprint each check (HTTPS app.logicsrc.com only, no redirects, 5s, 64 KB, 10 min cache): removed key = DOWN key <fp> removed from keyring; unreachable keyring = snapshot.

Validation: moved out of createMonitor into lib/uptime-monitor-input.ts, used by both the dashboard action and the API (private keys still refused).

Migration 20261029160000_uptime_partner_api.sql (additive) is already applied to prod.

Tests: tests/uptime-partner-api.test.ts (auth: bad/revoked token, unknown email; scoping; keyring resolution; removed-key DOWN; 64 KB cap; cache). Full suite + typecheck green locally.

🤖 Generated with Claude Code

/api/uptime/v1/{settings,keys,monitors[/:id[/incidents]]} for first-party
apps: Bearer cpu_ partner token (uptime_partners, sha256 stored, minted by
scripts/mint-uptime-partner.ts) + X-Fleet-User-Email mapped to the crawlproof
user with that confirmed email. Everything is scoped to the user's one Fleet
project (projects.kind = 'fleet', made on first use), so the partners and the
dashboard show the same checks.

SSH checks can name a key in the user's logicsrc keyring by fingerprint; the
worker resolves it from the share link each check (10 min cache, HTTPS
app.logicsrc.com only, 5s, 64 KB), goes DOWN with "key <fp> removed from
keyring" once it is gone, and falls back to the snapshot if the keyring is
unreachable. Monitor validation moved to lib/uptime-monitor-input.ts and is
shared by the dashboard's createMonitor and the API.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

47 finding(s)

HIGH/CRITICAL: 2 | MEDIUM: 29 | LOW: 16

Severity Rule Location
HIGH tls-verification-disabled lib/onion.ts:48
HIGH secret-generic-credential lib/sp/platforms/facebook.ts:32
MEDIUM js-unescaped-html-sink app/(app)/dashboard/admin/email-broadcast/EmailBroadcastForm.tsx:125
MEDIUM js-unescaped-html-sink app/(app)/dashboard/projects/[id]/autoblog/articles/[articleId]/page.tsx:214
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:71
MEDIUM js-unescaped-html-sink app/(marketing)/blog/[slug]/page.tsx:99
MEDIUM js-unescaped-html-sink app/(marketing)/recent/page.tsx:186
MEDIUM js-unescaped-html-sink app/(marketing)/recent/page.tsx:190
MEDIUM js-unescaped-html-sink app/c/[project]/[slug]/page.tsx:77
MEDIUM js-unescaped-html-sink app/c/[project]/page.tsx:57
MEDIUM js-unescaped-html-sink app/careers.js/route.ts:228
MEDIUM js-unescaped-html-sink app/careers.js/route.ts:285
MEDIUM js-unescaped-html-sink app/layout.tsx:129
MEDIUM js-open-redirect app/login/form.tsx:39
MEDIUM js-unescaped-html-sink app/r/[token]/page.tsx:176
MEDIUM js-open-redirect app/signup/form.tsx:63
MEDIUM js-unescaped-html-sink components/json-ld.tsx:8
MEDIUM js-unescaped-html-sink components/pit-footer.tsx:17
MEDIUM js-unescaped-html-sink components/report/markdown-view.tsx:16
MEDIUM js-unescaped-html-sink lib/careers/page-templates.ts:198
MEDIUM js-dynamic-code-execution lib/crawl-limits.ts:67
MEDIUM redos-nested-quantifier lib/emailMarkdown.ts:41
MEDIUM redos-nested-quantifier lib/emailMarkdown.ts:324
MEDIUM redos-nested-quantifier lib/lx/articleGen.ts:100
MEDIUM redos-nested-quantifier lib/tracker/agent-gate.ts:61
MEDIUM sh-predictable-temp-path ops/selfhost/server/setup-supabase.sh:218
MEDIUM sql-template-interpolation scripts/detect-slot-themes.ts:31
MEDIUM sql-template-interpolation scripts/purge-constructed-keywords.ts:163
MEDIUM sql-template-interpolation scripts/purge-offniche-keywords.ts:124
MEDIUM js-dynamic-code-execution scripts/test-crawl-limits.mjs:14
MEDIUM js-dynamic-code-execution scripts/test-crawl-limits.mjs:24
LOW secret-generic-credential app/(marketing)/docs/autoblog-webhook/page.tsx:156
LOW secret-generic-credential lib/sealed/migrate.ts:38
LOW secret-generic-credential lib/sp/platforms/linkedin.ts:25
LOW js-dynamic-code-execution tests/careers-page-templates.test.ts:21
LOW js-dynamic-code-execution tests/careers-widget-script.test.ts:19
LOW js-dynamic-code-execution tests/careers-widget-script.test.ts:69
LOW js-dynamic-code-execution tests/contract/ad-visitor-id.test.ts:51
LOW js-dynamic-code-execution tests/contract/ad-visitor-id.test.ts:52
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:20
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:24
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:25
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:26
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:31
LOW js-dynamic-code-execution tests/contract/ads-click-cooldown-redis.test.ts:35
LOW secret-generic-credential tests/contract/posthog-integration.test.ts:13
LOW secret-generic-credential tests/lead-campaign.test.ts:16

Snippets are redacted; ThreatCrush never prints matched credential material.

@sh1pt-actions-fleet
sh1pt-actions-fleet Bot merged commit d5b5416 into master Oct 29, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant