Skip to content

feat(backend): /api/internal/notify endpoint (homelab notifications) - #625

Merged
LucasSantana-Dev merged 6 commits into
mainfrom
feature/internal-notify-endpoint
Apr 15, 2026
Merged

LucasSantana-Dev merged 6 commits into
mainfrom
feature/internal-notify-endpoint

Conversation

@LucasSantana-Dev

Copy link
Copy Markdown
Owner

Summary

Adds a key-gated POST endpoint that proxies messages from the homelab host to Discord using the bot's existing token. Replaces the brittle webhook URL fan-out (4 of 4 webhooks went 404 unnoticed for weeks).

Why

Webhooks expire silently when a Discord admin removes them; messages then disappear without any signal in the homelab logs. Routing through Lucky uses the bot identity, so as long as the bot is in the channel the messages get through.

Endpoint

  • POST /api/internal/notify
  • Header: X-Notify-Key: ${LUCKY_NOTIFY_API_KEY}
  • Body: { channelId: string, content?: string, embeds?: object[] }
  • Returns 204 on success; 401 / 400 / 502 with detail on failure.
  • Rate-limited via writeLimiter.

Files

  • packages/backend/src/routes/internalNotify.ts — handler
  • packages/backend/src/routes/internalNotify.spec.ts — auth + happy path + Discord 4xx
  • packages/backend/src/routes/index.ts — wired into setupRoutes
  • docker-compose.yml + .env.example — LUCKY_NOTIFY_API_KEY pass-through

Manual deploy steps

  1. Set LUCKY_NOTIFY_API_KEY=<32-char random> in ~/Lucky/.env on the homelab host.
  2. cd ~/Lucky && docker compose up -d backend
  3. Apply matching homelab repo PR that swaps webhook URL → this endpoint.

Risk

None on the bot itself: endpoint is additive, key-gated, rate-limited, and only uses the existing bot token. If the key env is missing, every request 401s.

Replaces fragile per-channel webhooks with a bot-token-backed REST proxy.
The homelab watchdog and other host-side scripts post {channelId,content}
to http://lucky-backend:3000/api/internal/notify with X-Notify-Key header.
The route forwards to Discord REST API using the bot's existing token,
so messages appear from the Lucky bot user (no webhook expiry).

- New route in packages/backend/src/routes/internalNotify.ts
- Spec file with auth + happy path + Discord 4xx handling
- Wired into setupRoutes(app)
- LUCKY_NOTIFY_API_KEY pass-through in docker-compose.yml + .env.example
- Bot token already in backend env (DISCORD_TOKEN)

Manual follow-up after merge:
  1. Set LUCKY_NOTIFY_API_KEY=<random-32-char> in ~/Lucky/.env on homelab
  2. Restart lucky-backend
  3. Apply matching homelab repo PR that swaps webhook URL for this endpoint
@vercel

vercel Bot commented Apr 15, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment Apr 15, 2026 1:01am

Request Review

@coderabbitai

coderabbitai Bot commented Apr 15, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@LucasSantana-Dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 23 minutes and 0 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 23 minutes and 0 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0a5cb19d-0bb6-4e24-ab12-d3710dd13cbb

📥 Commits

Reviewing files that changed from the base of the PR and between a7b3737 and 176d876.

📒 Files selected for processing (7)
  • .env.example
  • docker-compose.yml
  • packages/backend/src/routes/index.ts
  • packages/backend/src/routes/internalNotify.ts
  • packages/backend/tests/integration/routes/internalNotify.test.ts
  • packages/backend/tests/unit/routes/index.test.ts
  • packages/backend/tests/unit/routes/internalNotify.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/internal-notify-endpoint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

LucasSantana-Dev added a commit to LucasSantana-Dev/homelab that referenced this pull request Apr 15, 2026
Replaces dead WATCHDOG_DISCORD_WEBHOOK URL with POST to Lucky's new
/api/internal/notify (LucasSantana-Dev/Lucky#625). Lucky forwards via
the bot identity, eliminating silent webhook-expiry failure mode.

- send_discord() in homelab-watchdog.sh now POSTs JSON to Lucky.
- New env: LUCKY_NOTIFY_URL / LUCKY_NOTIFY_KEY / LUCKY_NOTIFY_CHANNEL_ID
- WUD/Alertmanager/update-containers will migrate next wave.

Manual deploy after both PRs merge:
  1. Set LUCKY_NOTIFY_API_KEY in ~/Lucky/.env (any 32-char random)
  2. docker compose up -d backend in ~/Lucky
  3. Set LUCKY_NOTIFY_KEY in ~/homelab/.env to the same value
  4. Set LUCKY_NOTIFY_CHANNEL_ID=1480939399922323567 (#homelab)
  5. Watchdog picks up new env on next tick
- Add 17 integration tests for POST /api/internal/notify
- Cover happy path: valid content + embeds delivery
- Cover auth: missing/wrong/unconfigured API key (401)
- Cover validation: missing channelId, missing content+embeds (400)
- Cover errors: missing Discord token (500), Discord API errors (502)
- Cover edge cases: content truncation, special chars, text parsing
- All tests pass with 100% endpoint coverage
LucasSantana-Dev added a commit to LucasSantana-Dev/homelab that referenced this pull request Apr 15, 2026
* feat(notify): route watchdog alerts through Lucky bot internal endpoint

Replaces dead WATCHDOG_DISCORD_WEBHOOK URL with POST to Lucky's new
/api/internal/notify (LucasSantana-Dev/Lucky#625). Lucky forwards via
the bot identity, eliminating silent webhook-expiry failure mode.

- send_discord() in homelab-watchdog.sh now POSTs JSON to Lucky.
- New env: LUCKY_NOTIFY_URL / LUCKY_NOTIFY_KEY / LUCKY_NOTIFY_CHANNEL_ID
- WUD/Alertmanager/update-containers will migrate next wave.

Manual deploy after both PRs merge:
  1. Set LUCKY_NOTIFY_API_KEY in ~/Lucky/.env (any 32-char random)
  2. docker compose up -d backend in ~/Lucky
  3. Set LUCKY_NOTIFY_KEY in ~/homelab/.env to the same value
  4. Set LUCKY_NOTIFY_CHANNEL_ID=1480939399922323567 (#homelab)
  5. Watchdog picks up new env on next tick

* fix: remove orphan send_discord tail leftover from regex replace

---------

Co-authored-by: LucasSantana-Dev <LucasSantana-Dev@users.noreply.github.com>
@github-actions github-actions Bot added size/xl and removed size/l labels Apr 15, 2026
@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 114794c into main Apr 15, 2026
12 checks passed
@LucasSantana-Dev
LucasSantana-Dev deleted the feature/internal-notify-endpoint branch April 15, 2026 01:04
LucasSantana-Dev added a commit that referenced this pull request Apr 15, 2026
Seeds the first two specs for Lucky:
- 2026-04-15-internal-notify-endpoint (shipped via #625, archived)
- 2026-04-15-autoplay-diversity (proposed)

Derived docs/roadmap.md generated from spec frontmatters.
Generator: ~/.claude/rag-index/specs.py (personal tooling).

Future specs land under docs/specs/<date>-<slug>/{spec,tasks}.md;
shipped specs auto-archive to docs/specs/archived/ via spec-ship.
LucasSantana-Dev added a commit that referenced this pull request Apr 15, 2026
Seeds the first two specs for Lucky:
- 2026-04-15-internal-notify-endpoint (shipped via #625, archived)
- 2026-04-15-autoplay-diversity (proposed)

Derived docs/roadmap.md generated from spec frontmatters.
Generator: ~/.claude/rag-index/specs.py (personal tooling).

Future specs land under docs/specs/<date>-<slug>/{spec,tasks}.md;
shipped specs auto-archive to docs/specs/archived/ via spec-ship.
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
…625)

* feat(backend): add /api/internal/notify endpoint for homelab alerts

Replaces fragile per-channel webhooks with a bot-token-backed REST proxy.
The homelab watchdog and other host-side scripts post {channelId,content}
to http://lucky-backend:3000/api/internal/notify with X-Notify-Key header.
The route forwards to Discord REST API using the bot's existing token,
so messages appear from the Lucky bot user (no webhook expiry).

- New route in packages/backend/src/routes/internalNotify.ts
- Spec file with auth + happy path + Discord 4xx handling
- Wired into setupRoutes(app)
- LUCKY_NOTIFY_API_KEY pass-through in docker-compose.yml + .env.example
- Bot token already in backend env (DISCORD_TOKEN)

Manual follow-up after merge:
  1. Set LUCKY_NOTIFY_API_KEY=<random-32-char> in ~/Lucky/.env on homelab
  2. Restart lucky-backend
  3. Apply matching homelab repo PR that swaps webhook URL for this endpoint

* test(backend): drop spec until tsconfig wires jest globals

* test(backend): mock setupInternalNotifyRoutes in routes/index.test

* test(backend): cover internalNotify route (auth + happy path + Discord errors)

* test(backend): cover /api/internal/notify endpoint

- Add 17 integration tests for POST /api/internal/notify
- Cover happy path: valid content + embeds delivery
- Cover auth: missing/wrong/unconfigured API key (401)
- Cover validation: missing channelId, missing content+embeds (400)
- Cover errors: missing Discord token (500), Discord API errors (502)
- Cover edge cases: content truncation, special chars, text parsing
- All tests pass with 100% endpoint coverage

---------

Co-authored-by: LucasSantana-Dev <LucasSantana-Dev@users.noreply.github.com>
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
Seeds the first two specs for Lucky:
- 2026-04-15-internal-notify-endpoint (shipped via #625, archived)
- 2026-04-15-autoplay-diversity (proposed)

Derived docs/roadmap.md generated from spec frontmatters.
Generator: ~/.claude/rag-index/specs.py (personal tooling).

Future specs land under docs/specs/<date>-<slug>/{spec,tasks}.md;
shipped specs auto-archive to docs/specs/archived/ via spec-ship.

This branch was successfully deployed

1 active deployment
Preview — 176d8763 Deployed Apr 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant