This repository was archived by the owner on Jul 16, 2026. It is now read-only.
Repository navigation
feat(slack-bridge): recover orphan .sending files on startup (Phase 5.12) - #80
Merged
Merged
Conversation
….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>
6 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends the proactive-delivery recovery sweep from Phase 5.11 to slack-bridge so the same orphan-
.sendingbug 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.sendingfile sits orphaned inresults/— no poll iteration looks at.sendingsuffixes, so the owner notification is silently dropped until manual intervention.OSS
sutandoalready had this guard in slack-bridge; we now match.Changes
src/slack-bridge.py:_recover_orphan_sending_files()(byte-identical to the telegram/discord versions modulo the docstring's cross-reference; renames eachproactive-*.sendingback to*.txt, collision-aware, fail-open on per-file errors).main()immediately after_single_instance_acquire, before the result-watcher thread and Socket-Mode handler start.tests/bridge-orphan-sending-recovery.test.py:slack_bolt+SLACK_BOT_TOKEN/SLACK_APP_TOKENenv so the module imports under test without the real lib.test_slack_recovers_orphan_sending_files,test_slack_recovery_is_selective,test_slack_recovery_collision_safe.test_all_bridges_define_recovery_functionandtest_all_bridges_call_recovery_at_startupnow cover all three bridges. A future PR that drops the function or the call from any bridge breaks the build.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:
_update_access_cache+_restore_access_from_cachedefend slack'saccess.jsonagainst external deletion (Settings UI can wipe it, causing re-TOFU that destroys tierMap)send_allowlistextractTest plan
python3 tests/bridge-orphan-sending-recovery.test.py→ all 12 tests pass (4 net-new for slack)pnpm -s typecheckcleanpython3 -m py_compile src/slack-bridge.pycleanMade with Cursor