From ae1d7275e65618424de86692a4166a0c9cbc0a17 Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Sun, 1 Nov 2026 11:24:01 +0700 Subject: [PATCH] fix: avoid false community-bot outage alerts --- AGENTS.md | 12 ++++++++++-- distribution/README.md | 6 +++--- .../android/en-US/changelogs/10773.txt | 1 + public/download/index.html | 6 +++--- scripts/ops-health.sh | 19 +++++++++++++++---- 5 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/10773.txt diff --git a/AGENTS.md b/AGENTS.md index bbdbf79..2e661b1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2237,7 +2237,7 @@ session with **no other memory of this project**. So: instead of showing the error boundary. - **Baselines** (verified 2026-10-29): `npm test` → **0 errors, 0 warnings**, **156 tests**, build ok. The gate also type-checks the CVM server - (`tsc -p cvm-server/tsconfig.json`). `package.json` version **1.7.72**. + (`tsc -p cvm-server/tsconfig.json`). `package.json` version **1.7.73**. - ✅ Lint is **clean**: `no-explicit-any` = 0 · `react-hooks/exhaustive-deps` = 0 · `no-unused-vars` = 0 · `react-refresh` = 0. Non-component exports were **split into their own modules** (`contexts/language.ts`, `lib/sortOptions.ts`, @@ -2464,7 +2464,7 @@ Rules: or `FORGEJO_PASSWORD`; `scripts/release.sh` calls it automatically when either is set). It uploads the APK and checksum, but does not push git history. - **Self-hosted F-Droid repo:** `https://fdroid.skate-spots.org/repo` - (`org.skatespots.app`; currently 1.7.72). It is a **third-party repo**, not + (`org.skatespots.app`; currently 1.7.73). It is a **third-party repo**, not F-Droid main. Repo signing fingerprint: `88:B1:71:1C:24:02:89:FB:B2:A7:FC:C1:B3:1F:BB:9D:60:F5:7F:19:18:E0:3D:62:2D:35:F2:3D:E1:84:46:75`. The developer APK signature is unchanged; the repo key only signs indexes. @@ -2522,6 +2522,10 @@ Rules: - Flags: `--probe-push` runs a bounded 45s **real** `git push` — signing only happens when there *is* something to push, so this is the only true signer probe (it publishes any unpushed commits; a timeout ⇒ signer down ⇒ open Amber in the foreground, or `ngit account login --interactive`). `--notify` = desktop notification (deduped by an actionable-problem signature). `--quiet` = silent when healthy. Test against a fake state dir with `SKATESPOTS_STATE_DIR=…`. - ⚠️ `git push --dry-run` does **NOT** exercise signing (prints "Everything up-to-date", never signs) — do not use it as a signer probe. - **Runs automatically every 15 min:** `skatespots-ops-health.timer` → `skatespots-ops-health.service` (`--quiet --notify`). Install/refresh with `scripts/install-ops-health-timer.sh`; logs `journalctl --user -u skatespots-ops-health`. + - **Community bot check is conservative:** a failed SSH probe now reports + “state unknown” and does **not** notify. Only an actual `inactive`/`failed` + systemd state is actionable. This stops transient SSH/DNS hiccups from + producing “community Cordn bot is unreachable” notifications. - **Web (manual)**: `npm run build` produces the web `dist/` (with `_headers`/`_redirects`); deploy by dragging `dist/` to the Netlify site's Deploys tab. - **Zapstore (Android)**, from the repo root: `SIGN_WITH='bunker://...' zsp publish zapstore.yaml` - `zsp publish --wizard` is **broken for this app** (the wizard can't parse a nostrhub web `repository` — it supports only GitHub/GitLab/Gitea/F-Droid/local). Always pass `zapstore.yaml`. @@ -2941,6 +2945,10 @@ Rules: shared merge path; image/avatar requests and the site referrer policy use no-referrer. APK sha256 `c2169cae…`, versionCode 10772. Web live at `78741f9`. + - **1.7.73 (2026-11-01):** login dialog now has two adaptive methods: + Amber on Android, NIP-46 QR on desktop, with bunker paste as a secondary + path and no duplicate NIP-46 card. APK sha256 `bcd51861…`, versionCode + 10773. Web live at `719a679`. ### Relay archive (dataset backup) - **Transfer content between keys (`scripts/transfer-content.mjs`, 2026-10-04):** diff --git a/distribution/README.md b/distribution/README.md index e8a3f02..34862d9 100644 --- a/distribution/README.md +++ b/distribution/README.md @@ -7,10 +7,10 @@ account is required. - Forge: - Latest release: -- Signed APK (1.7.72): - +- Signed APK (1.7.73): + - SHA-256: - `c2169caecab538ebff661a287d211f07c516a96ec05287f18baa2a75ef0a8169` + `bcd51861f8bba7b01d632d6f20f692f6f727f7ae31e9f5c6ee059565164b5bc4` The APK is signed with the same key as the Zapstore build. Installing an F-Droid-signed build over it would require uninstalling SkateSpots and losing diff --git a/fastlane/metadata/android/en-US/changelogs/10773.txt b/fastlane/metadata/android/en-US/changelogs/10773.txt new file mode 100644 index 0000000..ebdb73c --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/10773.txt @@ -0,0 +1 @@ +The login dialog now shows two adaptive methods: Amber on Android, or NIP-46 QR pairing on desktop. Bunker paste is a secondary path, and the duplicate NIP-46 card was removed. diff --git a/public/download/index.html b/public/download/index.html index 8281862..f6c2340 100644 --- a/public/download/index.html +++ b/public/download/index.html @@ -98,16 +98,16 @@ - Download SkateSpots-1.7.72.apk · 56 MB + Download SkateSpots-1.7.73.apk · 56 MB
Requires Android 7.0 or newer. - SHA-256: c2169caecab538ebff661a287d211f07c516a96ec05287f18baa2a75ef0a8169 + SHA-256: bcd51861f8bba7b01d632d6f20f692f6f727f7ae31e9f5c6ee059565164b5bc4 Only install APKs from a source you trust. Android will ask you to allow installs from your browser.
diff --git a/scripts/ops-health.sh b/scripts/ops-health.sh index 56e21fc..a5e820f 100755 --- a/scripts/ops-health.sh +++ b/scripts/ops-health.sh @@ -218,12 +218,23 @@ p "" p "${B}Community bot${N}" COMMUNITY_HOST="${SKATESPOTS_COMMUNITY_HOST:-skatespots-cvm}" if command -v ssh >/dev/null 2>&1 && grep -qsE "^Host[[:space:]]+${COMMUNITY_HOST}([[:space:]]|$)" "$HOME/.ssh/config"; then - community_state="$(timeout 8 ssh -o BatchMode=yes -o ConnectTimeout=5 "$COMMUNITY_HOST" 'systemctl is-active skatespots-community' 2>/dev/null || true)" - if [ "$community_state" = "active" ]; then + # A failed SSH connection is NOT evidence that the remote bot is down. The + # previous version turned an empty SSH result into "unreachable" and emitted + # an ops notification on every transient network/DNS hiccup. Retry once, then + # report an honest unknown state without alerting. + community_state="" + for attempt in 1 2; do + community_state="$(timeout 8 ssh -o BatchMode=yes -o ConnectTimeout=5 "$COMMUNITY_HOST" 'systemctl is-active skatespots-community' 2>/dev/null || true)" + [ -n "$community_state" ] && break + [ "$attempt" = "1" ] && sleep 1 + done + if [ -z "$community_state" ]; then + p " ${Y}⚠${N} skatespots-community: health check unreachable (SSH failed; state unknown)" + elif [ "$community_state" = "active" ]; then p " ${G}✓${N} skatespots-community active" else - p " ${R}✗${N} skatespots-community: ${community_state:-unreachable}" - problems+=("community Cordn bot is ${community_state:-unreachable}") + p " ${R}✗${N} skatespots-community: ${community_state}" + problems+=("community Cordn bot is ${community_state}") signature+="community-bot;" fi community_backup="$(systemctl --user is-active skatespots-community-backup.timer 2>/dev/null || echo unknown)"