Skip to content
This repository was archived by the owner on Jul 16, 2026. It is now read-only.

feat(slack-bridge): recover orphan .sending files on startup (Phase 5.12) - #80

Merged
jgluck96 merged 1 commit into
dev-clientfrom
josh/phase-5.12-slack-bridge
Jun 2, 2026
Merged

jgluck96 merged 1 commit into
dev-clientfrom
josh/phase-5.12-slack-bridge

Conversation

@jgluck96

@jgluck96 jgluck96 commented Jun 2, 2026

Copy link
Copy Markdown

Summary

Extends the proactive-delivery recovery sweep from Phase 5.11 to slack-bridge so the same orphan-.sending bug class is closed on every surface (telegram + discord + slack). When the bridge crashes between the atomic claim-rename (proactive-*.txt → .sending) and the actual send, the .sending file sits orphaned in results/ — no poll iteration looks at .sending suffixes, so the owner notification is silently dropped until manual intervention.

OSS sutando already had this guard in slack-bridge; we now match.

Changes

  • src/slack-bridge.py:
    • Add _recover_orphan_sending_files() (byte-identical to the telegram/discord versions modulo the docstring's cross-reference; renames each proactive-*.sending back to *.txt, collision-aware, fail-open on per-file errors).
    • Call it from main() immediately after _single_instance_acquire, before the result-watcher thread and Socket-Mode handler start.
  • tests/bridge-orphan-sending-recovery.test.py:
    • Stub slack_bolt + SLACK_BOT_TOKEN / SLACK_APP_TOKEN env so the module imports under test without the real lib.
    • Net-new test functions for slack: test_slack_recovers_orphan_sending_files, test_slack_recovery_is_selective, test_slack_recovery_collision_safe.
    • Rename + broaden drift guards: test_all_bridges_define_recovery_function and test_all_bridges_call_recovery_at_startup now cover all three bridges. A future PR that drops the function or the call from any bridge breaks the build.
    • Extend the idempotency / missing-dir test to also exercise sbridge.

Minimal-divergence rationale

Per the directive, this PR is the strictly-additive port. Two other portable hardenings surfaced during the audit and are not included — they're queued as follow-up phases so each PR stays focused:

Win What Queued as
Access-cache (sonichi#899) _update_access_cache + _restore_access_from_cache defend slack's access.json against external deletion (Settings UI can wipe it, causing re-TOFU that destroys tierMap) Phase 5.13 candidate
send_allowlist extract Replace slack-bridge's inline 25-line allowlist with the shared helper introduced in Phase 5.9 Phase 5.14 candidate

Test plan

  • python3 tests/bridge-orphan-sending-recovery.test.py → all 12 tests pass (4 net-new for slack)
  • Full Python regression sweep → 55/55 tests pass
  • pnpm -s typecheck clean
  • python3 -m py_compile src/slack-bridge.py clean

Made with Cursor

….12)

Extends the recovery sweep from Phase 5.11 to slack-bridge.py, closing
the same orphan-`.sending` bug class on every proactive-delivery surface
(telegram, discord, slack). When the bridge crashes between the atomic
claim-rename (`proactive-*.txt` → `.sending`) and the actual send, the
.sending file sits orphaned in `results/` because no poll iteration ever
looks at .sending suffixes — the owner notification is silently dropped.

Changes:
- `src/slack-bridge.py`: add `_recover_orphan_sending_files()` (byte-
  identical to telegram/discord versions modulo the docstring's
  cross-reference) and call it from `main()` immediately after the
  single-instance lock, before any threads spin up.
- `tests/bridge-orphan-sending-recovery.test.py`: extend coverage to
  slack — add basic recovery, selectivity, collision-safety, and
  idempotent/missing-dir variants; rename the drift-guard tests to
  cover all three bridges; stub `slack_bolt` + dummy SLACK_*_TOKEN
  env so the module imports under test without the real library.

Per the minimal-divergence directive, only the additive recovery
function is ported in this PR. Two other portable hardenings surfaced
during the audit are queued as follow-ups:
- access-cache for sonichi#899 (slack-bridge access.json external-deletion fix)
- `send_allowlist` helper extract (parallel to Phase 5.9 for discord)

Tests: 55/55 Python tests pass (12/12 in the orphan-recovery file,
4 of which are net-new for slack). TypeScript typecheck clean.

Phase 5.12 of the OSS → private sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant