Skip to content

adr: the minimum Discord fallback for upstream notifications #52

Description

@tucktuck101

Context and problem statement

Ruling 6 gives Discord a specific and narrow job: "awareness of Buzz releases or failures does not depend entirely on the class Buzz deployment being healthy". It is an out-of-band path, and the PRD's non-goals state "No requirement for Discord to become a second full user interface."

The question is what the smallest thing is that actually discharges that job. The two options the PRD offers — release alerts only, or the same digest — differ on more than volume: they differ on whether Discord carries a pointer or carries the content. A pointer into a Buzz channel is worthless in exactly the scenario the fallback exists for, because the relay being unreachable is the scenario. A full mirror discharges it completely but is the thing the non-goal forbids.

There is also a case Ruling 6 names that the question's two options both miss: failures. If the scheduled job errors, or synthesis fails, or publication to Buzz is rejected, nothing appears in Buzz — and a Discord path that only fires on successful releases is silent in precisely that case too. A fallback that shares the primary path's failure mode is not a fallback.

Nothing Discord-related exists in the cohort's tree yet: launchpad/ on launchpad-issue-pr-scaffold contains only AGENTS.md, AGENT_PR_TEMPLATE.md, README.md, labels.yml and sync-labels.sh.

Decision drivers

  • Ruling 6: Buzz is the primary interface, Discord is the independent fallback — independence is the whole point, so the fallback must not depend on the relay
  • Non-goal: Discord must not become a second full user interface
  • Ruling 6 names two things worth falling back for — releases and failures — and the open question only asks about the first
  • A link-only alert is useless when the relay is the thing that is down
  • A Discord webhook is an additional credential in a public repository, governed by launchpad/AGENTS.md section 8
  • Discord is a third party outside the cohort's boundary; Buzz publication is membership-gated, Discord posting is not the same trust context
  • Relay releases are roughly monthly (29 days between relay-v0.2.0 and relay-v0.2.1), so a release-only Discord path is nearly silent — and a channel nobody sees traffic in is one nobody checks

Considered options

  • Release alert only: stream, version, one-line headline, links to the upstream sources and to the Buzz post
  • Health-and-failure alerts only: Discord fires when the job fails or when publication to Buzz is rejected, and stays silent otherwise
  • Tiered: a headline plus links normally, escalating to the full report text when publication to Buzz failed — so the fallback carries content exactly when the primary path did not
  • The full digest mirrored to Discord every time
  • No Discord path in Phase 1, deferring Ruling 6 entirely
  • Expected rejection: mirroring the full digest. It contradicts the PRD's own non-goal and erodes Ruling 6 in practice rather than in principle — once the complete content is in Discord, Discord becomes where people read it, and Buzz stops being the primary interface by usage even while remaining primary on paper.
  • Expected rejection: no Discord path at all in Phase 1. It leaves Ruling 6's stated failure mode uncovered: the cohort would learn that Buzz is broken only by noticing the absence of something, which is not a detection mechanism.
  • Expected rejection: a link-only alert as the sole fallback. In the outage this exists for, the link does not resolve, so the fallback delivers nothing.

Decision outcome

Left blank deliberately. launchpad/AGENTS.md rule 1 for agents: draft everything, approve nothing.

Consequences

Good: naming the minimum keeps a secondary channel from quietly growing into a product surface, and gives the implementation a testable statement — "when publication to Buzz fails, this specific thing appears in Discord" is something a task can prove by breaking the relay connection on purpose.

Bad: any Discord path is a second delivery target to build, configure and keep working, and a fallback that only fires on failure is itself untested most of the time — silent-and-broken and silent-and-fine look identical. Deciding the minimum also does not settle who administers the Discord channel or what happens when that person leaves the cohort, and that is real operational surface for a teaching cohort with a fixed lifespan.

Security implications

A Discord webhook URL is a bearer credential: anyone holding it can post into the channel as the integration. launchpad/AGENTS.md section 8 governs it — Actions secrets or an Environment, never a tracked file, and never a private hostname alongside it. Because this repository is public, a webhook leaked through a workflow log or a fork-reachable workflow is a channel anyone can post into, which matters more than it sounds: cohort members would be reading upstream security assessments from a channel that a stranger can write to.

The trust contexts also differ from Buzz's. Buzz publication is membership-gated (BUZZ_REQUIRE_AUTH_TOKEN=true, BUZZ_REQUIRE_RELAY_MEMBERSHIP=true in upstream's deploy/compose/.env.example); Discord's audience is whoever is in that Discord. For Phase 1 the content is public upstream information, so the delta is small. Under Ruling 7 it is not — fork-aware content would state our deployed version and divergence, and sending that to a third-party service on a failure path is a decision that should be made deliberately here rather than inherited later by default.

Supersedes

none


Filed by an AI agent (Claude Opus 5) on behalf of @tucktuck101, drafted from #3's open questions and intended to be parented to #3 per launchpad/AGENTS.md section 4. Verified by reading the repos: Ruling 6 and the Discord non-goal in #3; launchpad/AGENTS.md section 8 on public-repository secret handling; the five-file contents of launchpad/ on launchpad-issue-pr-scaffold; the relay tag dates giving the ~29-day gap; and BUZZ_REQUIRE_AUTH_TOKEN / BUZZ_REQUIRE_RELAY_MEMBERSHIP in block/buzz deploy/compose/.env.example. NOT verified: whether a cohort Discord server or channel exists today, who administers it, and whether any Discord configuration exists elsewhere in the repository — only launchpad/ on that branch was surveyed, so this claims absence there and nowhere else.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:upstream-intelTracking and reporting on block/buzz upstreamby:agentFiled or authored by an AI agent, not a humanneeds-decisionBlocked on a decision. Applied automatically to ADRs.type:adrA decision to make and record. Not a work item.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions