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

feat(discord-bridge): record outbox audit on every delivery (Phase 5.16) - #84

Merged
jgluck96 merged 1 commit into
dev-clientfrom
josh/phase-5.16-discord-outbox-records
Jun 2, 2026
Merged

jgluck96 merged 1 commit into
dev-clientfrom
josh/phase-5.16-discord-outbox-records

Conversation

@jgluck96

@jgluck96 jgluck96 commented Jun 2, 2026

Copy link
Copy Markdown

Summary

Phase 5.15 added the dashboard reader + Outbox card. Slack writes were already populating outbox_log, so slack deliveries became visible right away. Discord deliveries still didn't, because discord-bridge.py had no outbox_log.append(...) calls. Ported the three OSS sites that cover Discord's main delivery paths.

Sites ported

Each wrapped in try / import outbox_log / append(...) / except Exception: pass so the audit log can NEVER block a Discord delivery (telemetry must not be load-bearing).

Site Path channel_type recipient
1 poll_results reply (DM or guild channel) discord_dm | discord_channel (from isinstance(channel, discord.DMChannel)) str(channel.id)
2 Proactive owner DM discord_dm str(owner_id)
3 dm-fallback channel-redirect (when [channel: <id>] marker routes a result elsewhere) discord_channel str(target_channel_id) (not owner_id — reflects where the message actually landed)

recipient_label set everywhere for human readability in the dashboard card (otherwise it falls back to the bare channel id which is useless for review).

Out of scope

Two stando-specific send sites were NOT ported and don't have OSS equivalents:

  • L2225 welcome message to new guild user — stando-only feature.
  • L2705 cap-hit reply for cloud-cap accounting — stando-only.

Adding outbox writes for those would be a feature addition, not a port — out of scope for the minimal-divergence sync rule.

Tests

New tests/discord-bridge-outbox.test.py (5 cases)

  • Structural: exactly 3 append sites, each wrapped in try / import outbox_log / append / except Exception: pass. Future PR that adds an unwrapped 4th site fails this.
  • Variable binding: each append carries channel_type, recipient, recipient_label, body, task_id.
  • Channel-type vocabulary: stays in dashboard._channel_icon's known set (catches typos that would silently render the default → arrow).
  • Round-trip: writes via outbox_log are read back via the dashboard reader added in Phase 5.15.
  • Drift guard: every append is preceded by a _chunk_for_discord send loop within 30 lines (prevents future PR from recording empty-body audit rows when the bridge only sent files).

Test plan

  • python3 tests/discord-bridge-outbox.test.py → 5/5
  • Full Python regression sweep → 58/58 pass (was 57; +1 net-new file)
  • pnpm -s typecheck → clean
  • python3 -m py_compile src/discord-bridge.py → clean

Result

After this merges, Discord DM replies, channel replies, proactive notifications, and channel-redirected results all show up in the dashboard's Outbox card alongside slack — symmetric audit visibility across both major bridges.

Roadmap

The bridge → outbox → dashboard pipeline is now feature-complete across slack + discord. Possible next phases (none currently flagged high-confidence):

  • Phase 5.17 candidate: telegram-bridge outbox writes (smaller surface than discord, but would close the bridge-family symmetry).
  • Phase 5.18 candidate: scan OSS dm-result.py for outbox writes (REST fallback path; would complete coverage when the live bridge is offline).

Made with Cursor

Phase 5.15 added the dashboard reader + Outbox card. Slack writes were
already populating outbox_log, so slack deliveries became visible right
away. Discord deliveries still didn't, because discord-bridge.py had
no `outbox_log.append(...)` calls. Ported the three OSS sites that
cover discord's main delivery paths.

Sites ported (each `try/import outbox_log/append/except Exception: pass`
to keep telemetry fail-open and non-load-bearing):

1. `poll_results` reply path — every channel.send() reply (DM or guild
   channel). channel_type derived from `discord.DMChannel` check;
   recipient_label = "<recipient> DM" or "#<channel-name>".
2. Proactive owner-DM path — every dm.send() proactive notification.
   channel_type="discord_dm"; recipient = owner_id; recipient_label
   from fetched user.name.
3. dm-fallback channel-redirect path — every target_channel.send()
   when a [channel: <id>] marker routes a result to a non-originating
   channel. channel_type="discord_channel"; recipient = the resolved
   target_channel_id (NOT the owner_id), so the dashboard reflects
   where the message actually landed.

Two stando-specific send sites were NOT ported and don't have OSS
equivalents:
- L2225 welcome message to new guild user (stando-only feature)
- L2705 cap-hit reply for cloud-cap accounting (stando-only)

Adding outbox writes for those would be a feature addition, not a
port — out of scope for the minimal-divergence sync.

Tests (new tests/discord-bridge-outbox.test.py, 5 cases):
- Structural: exactly 3 append sites, each wrapped in
  `try/import outbox_log/append/except Exception: pass`.
- Variable binding: each append carries channel_type, recipient,
  recipient_label, body, task_id.
- Channel-type vocabulary stays in dashboard._channel_icon's known set
  (catches typos that would silently render the default → arrow).
- Round-trip: writes via outbox_log are read back via the dashboard
  reader added in Phase 5.15.
- Drift guard: every append is preceded by a _chunk_for_discord send
  loop within 30 lines (prevents future PR from recording empty-body
  audit rows when the bridge only sent files).

Verification:
- 58/58 Python tests pass (was 57; +1 net-new file).
- TypeScript typecheck clean.
- `python3 -m py_compile src/discord-bridge.py` clean.

Phase 5.16 of the OSS → private sync. Discord deliveries now show up
alongside slack in the dashboard Outbox card.

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