Skip to content

[#648] Add Career Discord settings in Blade - #665

Open
StevScripts wants to merge 4 commits into
KnightHacks:mainfrom
StevScripts:stevin/career-discord-config-648-squashed
Open

StevScripts wants to merge 4 commits into
KnightHacks:mainfrom
StevScripts:stevin/career-discord-config-648-squashed

Conversation

@StevScripts

Copy link
Copy Markdown

Why

Officers need a way to change the Career channels and reminder roles when the Discord server gets reorganized. This puts them on Blade's existing Discord config page.

What

Closes: #648

Five new settings:

  • Internship and new-grad posting channels (digests post there too)
  • Internship and new-grad digest roles
  • An optional channel for job source failure alerts

The channels and roles use the supplied production IDs. The failure channel starts empty ("Not configured") until an officer sets it. Every other setting still requires a production ID.

Permissions, audit logs and caching didn't change. The new getOptionalDiscordConfigId returns null for the empty failure channel, so alert code can skip it.

These show as "Unused" until #651, #653 and #654 read them. The names follow #633's internship/new-grad split, not #648's three keys, so downstream owners please confirm them.

About the size: the migration is 21 lines. Almost everything else is meta/0064_snapshot.json, Drizzle's full-schema snapshot, which you can skip.

Test Plan

  • pnpm db:generate finds no schema drift.
  • A fresh database migrates cleanly twice. All five rows are seeded, and re-running the seed keeps officer edits.
  • All @forge/db tests (167) and the API config tests (50) pass against real Postgres. They cover upgrades, required IDs, setting and clearing the failure channel, audit records and cache refresh.
  • pnpm verify:precommit passes.
  • In Chromium I saved, reloaded and cleared the failure channel, and checked desktop and 320px mobile layouts.

The full workspace tests and build passed earlier. Since then only the migration files and their tests changed.

Screenshots

Career posting channels

career-channels-desktop

Digest roles

career-roles-desktop

Empty failure channel

failure-channel-desktop

Officer editor

failure-channel-dialog-desktop

Rollout

  • Deploy this code before running the migration. Old Blade can't show the new rows or an empty production ID. The CI migrate job doesn't wait for the deploy, so please confirm the order.
  • Development IDs are empty, so dev falls back to the production IDs. Set dev channels before testing real delivery outside production.

Checklist

  • Database: No schema changes, OR I ran pnpm db:generate and committed the generated files in packages/db/drizzle/
  • Environment Variables: No environment variables changed, OR I have contacted the Development Lead to modify them on Coolify BEFORE merging.

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Walkthrough

The change adds five Career Discord settings: three channels and two digest roles. It seeds the settings and allows the source-health channel to remain unset. Validation and configuration readers distinguish optional destinations from required ones. The Blade editor supports configuring or clearing the optional destination and displays unset values separately from production fallback values. Tests cover migration, validation, reads, updates, auditing, and the editor.

Pre-merge checks: Passed 8
Check name Status Explanation
Title check Passed Title is "[#648] Add Career Discord settings in Blade", which contains the issue number in brackets, is under 72 characters, and describes the main change: five Career Discord settings added to Blade'…
Description check Passed The description explains why (officers need to change Career channels and reminder roles after a Discord reorganization), what changed (five new settings, optional failure channel, getOptionalDiscordC…
Linked Issues check Passed [#648] Scope items are implemented at head. CONFIG_KEYS in packages/consts/src/discord.ts adds the three Career channel keys and two digest role keys. CONFIG_KEY_CONSUMERS gives each new key an …
Out of Scope Changes check Passed The changes support [#648]. They include the Career keys, the seed migration and journal entry, the nullable production_id with its check constraint, the optional-ID reader and validator, the Blade …
Docstring Coverage Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentati…
No Hardcoded Secrets Passed No changed file adds a hardcoded API key, password, access token, or secret literal. The new long numeric values are Discord channel and role IDs or test fixtures. Token-related additions in the gener…
Validated Env Access Passed The pull request adds no direct process.env usage. The authoritative diff has no added process.env lines, and pickaxe inspection finds no changes containing that reference. Existing repository usa…
No Typescript Escape Hatches Passed No TypeScript escape hatch was introduced. The pull-request additions contain no any type, @ts-ignore, @ts-expect-error, or non-null assertion (!.).
Full details: Title check

Explanation

Title is "[#648] Add Career Discord settings in Blade", which contains the issue number in brackets, is under 72 characters, and describes the main change: five Career Discord settings added to Blade's Discord config page. The title meets the configured requirement.

Full details: Description check

Explanation

The description explains why (officers need to change Career channels and reminder roles after a Discord reorganization), what changed (five new settings, optional failure channel, getOptionalDiscordConfigId), test plan, rollout order, and screenshots. It is directly related to the changeset.

Full details: Linked Issues check

Explanation

[#648] Scope items are implemented at head. CONFIG_KEYS in packages/consts/src/discord.ts adds the three Career channel keys and two digest role keys. CONFIG_KEY_CONSUMERS gives each new key an empty consumer list, which the PR states is intentional until #651, #653, and #654 land. Migration packages/db/drizzle/0064_career_discord_config.sql seeds all five rows with production IDs. It leaves career_source_health_channel unset, and it uses ON CONFLICT DO NOTHING so replays keep officer edits. Blade's config page lists and edits these rows, including the empty optional channel. The API validates, lists, updates, audits, and caches them. The generic readers in packages/utils/src/discord-config.ts resolve the registered keys. getOptionalDiscordConfigId returns null for an unset optional row. The 'Cron and the API can read them' criterion holds at the reader level. No cron consumer reads the keys yet, and the PR defers that work to the blocked issues. Non-coding checklist items do not apply.

Full details: Out of Scope Changes check

Explanation

The changes support [#648]. They include the Career keys, the seed migration and journal entry, the nullable production_id with its check constraint, the optional-ID reader and validator, the Blade dialog and section display, API and cache behavior, seed_devdb.ts (its guildIds now requires a production ID, which follows from the nullable column), resolveDiscordConfigId return type, documentation, and tests. The .forge/features/career-discord-config files are feature documentation for this change. No delivery consumer or unrelated runtime behavior was added.

Full details: Docstring Coverage

Explanation

Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 12 functions across 17 files. (7 skipped: 7 unsupported.)

Full details: No Hardcoded Secrets

Explanation

No changed file adds a hardcoded API key, password, access token, or secret literal. The new long numeric values are Discord channel and role IDs or test fixtures. Token-related additions in the generated snapshot are schema column names and constraints, not credential values.

Full details: Validated Env Access

Explanation

The pull request adds no direct process.env usage. The authoritative diff has no added process.env lines, and pickaxe inspection finds no changes containing that reference. Existing repository usages are pre-existing and do not cause a pull-request violation.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/blade/src/app/_components/admin/roles/discord-config-dialog.tsx

ESLint execution timed out; analysis is incomplete

apps/blade/src/app/_components/admin/roles/discord-config-section.tsx

ESLint skipped: the matched ESLint configuration already failed (timeout).

apps/blade/src/tests/admin/admin-config-console.test.tsx

ESLint skipped: the matched ESLint configuration already failed (timeout).

Review coverage is incomplete: 1 file could not be fully reviewed. Findings from completed review steps are included; see review info for details.

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

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up Comments

Minor follow-up Update the publication status for PR `#665`.

3-5: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the publication status for PR #665.

This status still says the squashed change is unpublished and requires approval to open a PR. Record the current PR and remove the obsolete publication instruction. Align the stale status lines in spec.md and srd.md at the same time.

Open the source location

Comment on lines +15 to +20
INSERT INTO "knight_hacks_discord_config" ("key", "kind", "label", "description", "production_id", "development_id") VALUES
('career_internship_channel', 'channel', 'Career internship posting channel', 'Channel for internship posts and digests.', '1537949209867583499', NULL),
('career_new_grad_channel', 'channel', 'Career new-grad posting channel', 'Channel for new-grad posts and digests.', '1537949230742900827', NULL),
('career_source_health_channel', 'channel', 'Career source-health alert channel', 'Optional channel for job source failure alerts.', NULL, NULL),
('career_internship_digest_role', 'role', 'Career internship digest role', 'Discord role pinged for internship digests.', '1537949002031562862', NULL),
('career_new_grad_digest_role', 'role', 'Career new-grad digest role', 'Discord role pinged for new-grad digests.', '1537948941348503683', NULL)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Heavy lift

Supported by static analysis

Script executed:

set -u
printf '%s\n' '--- migration ---'
nl -ba packages/db/drizzle/0064_career_discord_config.sql
printf '%s\n' '--- changed files ---'
git diff --name-status b88d4de35ac47f7cb1555658741778a792351c90 9b0c9847bdd6278aec9e1c03e13b9a65131b67c9 -- packages/db/drizzle/0064_career_discord_config.sql apps packages | sed -n '1,160p'
printf '%s\n' '--- config key and metadata references ---'
rg -n -F --glob '*.{ts,tsx,sql,md,yml,yaml}' -e 'career_internship_channel' -e 'career_source_health_channel' -e 'knight_hacks_discord_config' -e 'DiscordConfig' apps packages docs 2>/dev/null || true
printf '%s\n' '--- migration/deployment ordering references ---'
rg -n -i --glob '*.{md,ts,tsx,yml,yaml,json,toml,sql}' -e 'migrate_prod' -e 'migration.*deploy' -e 'deploy.*migration' -e 'drain' -e 'old.*instance' -e 'deployment.*depend' . 2>/dev/null | sed -n '1,240p'

Repository: KnightHacks/forge

Length of output: 36899


Script executed:

set -u
printf '%s\n' '--- current Blade section ---'
nl -ba apps/blade/src/app/_components/admin/roles/discord-config-section.tsx | sed -n '1,380p'
printf '%s\n' '--- current Blade dialog ---'
nl -ba apps/blade/src/app/_components/admin/roles/discord-config-dialog.tsx | sed -n '1,240p'
printf '%s\n' '--- API router ---'
nl -ba packages/api/src/routers/discord-config.ts | sed -n '1,230p'
printf '%s\n' '--- current constants and utils ---'
nl -ba packages/consts/src/discord.ts | sed -n '1,130p'
nl -ba packages/utils/src/discord-config.ts | sed -n '1,180p'
printf '%s\n' '--- base versions of relevant files ---'
for f in apps/blade/src/app/_components/admin/roles/discord-config-section.tsx apps/blade/src/app/_components/admin/roles/discord-config-dialog.tsx packages/api/src/routers/discord-config.ts packages/consts/src/discord.ts; do
  printf '\\n--- %s at base ---\\n' \"$f\"
  git show b88d4de35ac47f7cb1555658741778a792351c90:\"$f\" 2>/dev/null | nl -ba | sed -n '1,380p' || true
done
printf '%s\n' '--- migration execution and deployment docs ---'
rg -n -i --glob '*.{ts,tsx,md,yml,yaml,json,toml,sql}' -e 'db:migrate' -e 'drizzle.*migrat' -e 'migrate_prod' -e 'deployment gate' -e 'deploy.*before' -e 'before.*deploy' packages apps docs .github 2>/dev/null | sed -n '1,260p'

Repository: KnightHacks/forge

Length of output: 42464


Script executed:

set -u
printf '%s\n' '--- revision availability ---'
git rev-parse --verify b88d4de35ac47f7cb1555658741778a792351c90^{commit} 2>&1 || true
git rev-parse --verify 9b0c9847bdd6278aec9e1c03e13b9a65131b67c9^{commit} 2>&1 || true
git status --short --branch
printf '%s\n' '--- base tree candidates ---'
git ls-tree -r --name-only b88d4de35ac47f7cb1555658741778a792351c90 -- apps/blade/src/app/_components/admin/roles packages/api/src/routers packages/consts/src/discord.ts 2>&1 | sed -n '1,120p'
printf '%s\n' '--- base file existence and source ---'
for f in apps/blade/src/app/_components/admin/roles/discord-config-section.tsx apps/blade/src/app/_components/admin/roles/discord-config-dialog.tsx packages/api/src/routers/discord-config.ts packages/consts/src/discord.ts; do
  printf '\\n--- %s ---\\n' \"$f\"
  git cat-file -e \"b88d4de35ac47f7cb1555658741778a792351c90:$f\" 2>&1 || true
  git show \"b88d4de35ac47f7cb1555658741778a792351c90:$f\" 2>&1 | sed -n '1,360p'
done
printf '%s\n' '--- production migration job ---'
nl -ba .github/workflows/ci.yml | sed -n '250,315p'
printf '%s\n' '--- explicit migration gate ---'
nl -ba packages/db/drizzle/0034_dry_shriek.sql | sed -n '112,145p'
printf '%s\n' '--- db README ---'
nl -ba packages/db/README.md | sed -n '1,42p'

Repository: KnightHacks/forge

Length of output: 9211


Script executed:

printf '%s\n' '--- base discord section ---'
git show b88d4de35ac47f7cb1555658741778a792351c90:apps/blade/src/app/_components/admin/roles/discord-config-section.tsx | nl -ba | sed -n '1,380p'
printf '%s\n' '--- base discord dialog ---'
git show b88d4de35ac47f7cb1555658741778a792351c90:apps/blade/src/app/_components/admin/roles/discord-config-dialog.tsx | nl -ba | sed -n '1,260p'
printf '%s\n' '--- base API router ---'
git show b88d4de35ac47f7cb1555658741778a792351c90:packages/api/src/routers/discord-config.ts | nl -ba | sed -n '1,230p'
printf '%s\n' '--- base constants ---'
git show b88d4de35ac47f7cb1555658741778a792351c90:packages/consts/src/discord.ts | nl -ba | sed -n '1,130p'
printf '%s\n' '--- diff for these consumers ---'
git diff --unified=25 b88d4de35ac47f7cb1555658741778a792351c90 9b0c9847bdd6278aec9e1c03e13b9a65131b67c9 -- apps/blade/src/app/_components/admin/roles/discord-config-section.tsx apps/blade/src/app/_components/admin/roles/discord-config-dialog.tsx packages/api/src/routers/discord-config.ts packages/consts/src/discord.ts | sed -n '1,500p'

Repository: KnightHacks/forge

Length of output: 42476


Script executed:

printf '%s\n' '--- head API list and view transformation ---'
nl -ba packages/api/src/routers/discord-config.ts | sed -n '1,115p'
printf '%s\n' '--- base API list and view transformation ---'
git show b88d4de35ac47f7cb1555658741778a792351c90:packages/api/src/routers/discord-config.ts | nl -ba | sed -n '1,115p'
printf '%s\n' '--- API diff ---'
git diff --stat b88d4de35ac47f7cb1555658741778a792351c90 9b0c9847bdd6278aec9e1c03e13b9a65131b67c9 -- packages/api/src/routers/discord-config.ts

Repository: KnightHacks/forge

Length of output: 9864


Script executed:

git show b88d4de35ac47f7cb1555658741778a792351c90:packages/consts/src/discord.ts | nl -ba | sed -n '60,120p'

Repository: KnightHacks/forge

Length of output: 2971


Deploy compatible Blade instances before applying migration 0064.

Old Blade does not define consumer metadata for the five new keys. It then evaluates row.readBy.length and can fail while rendering the Discord configuration page. Enforce the compatible deployment and old-instance drain before this migration runs.

@coderabbitai

coderabbitai Bot commented Nov 3, 2026

Copy link
Copy Markdown

Add Carrot credits or activate Agent usage billing to use Autofix

@StevScripts

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@StevScripts

Copy link
Copy Markdown
Author

@coderabbitai run pre-merge checks

@coderabbitai

coderabbitai Bot commented Nov 4, 2026

Copy link
Copy Markdown
✅ Actions performed

Running Pre-merge checks. Results will be posted in the summary comment once complete.

@StevScripts

Copy link
Copy Markdown
Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Action performed

Full review finished.

@StevScripts StevScripts self-assigned this Nov 4, 2026
@StevScripts StevScripts added Feature New Feature or Request Blade Change modifies code in Blade app Database Change modifies code in the DB package API Change modifies code in the global API/tRPC package Major Big change - 2+ reviewers required labels Nov 4, 2026
StevScripts and others added 4 commits November 3, 2026 22:01
Closes KnightHacks#648

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
@StevScripts
StevScripts force-pushed the stevin/career-discord-config-648-squashed branch from 1cbfbfb to c4f6d0e Compare November 4, 2026 03:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

Other comments: 1
.forge/features/career-discord-config/spec.md: 1

3-3: Minor · Maintainability & Code Quality · Quick win

Update the publication status.

This revision is under PR #665, but this line says the work was not republished. Update this line and the matching statement in .forge/features/career-discord-config/status.md (Line 3). Keep the account of PR #664 as history.

Review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 7abb64a and c4f6d0e.

Files selected for processing: 25
  • .forge/features/career-discord-config/spec.md
  • .forge/features/career-discord-config/srd.md
  • .forge/features/career-discord-config/status.md
  • .forge/features/career-discord-config/test-cases.md
  • apps/blade/src/app/_components/admin/roles/discord-config-dialog.tsx
  • apps/blade/src/app/_components/admin/roles/discord-config-section.tsx
  • apps/blade/src/tests/admin/admin-config-console.test.tsx
  • docs/DATABASE-USAGE.md
  • packages/api/src/tests/config/discord-config-validation.test.ts
  • packages/api/src/tests/config/discord-config.test.ts
  • packages/api/src/tests/integration/platform-config.test.ts
  • packages/consts/src/discord.ts
  • packages/db/drizzle/0064_career_discord_config.sql
  • packages/db/drizzle/meta/0064_snapshot.json
  • packages/db/drizzle/meta/_journal.json
  • packages/db/scripts/seed_devdb.ts
  • packages/db/src/schemas/discord-config.ts
  • packages/db/src/tests/career-discord-config-migration.test.ts
  • packages/db/src/tests/discord-config-migration.test.ts
  • packages/db/src/tests/migration-lineage.test.ts
  • packages/db/src/tests/support/career-discord-config.ts
  • packages/utils/src/discord-config.ts
  • packages/utils/src/tests/discord-config-consumers.test.ts
  • packages/utils/src/tests/discord-config.test.ts
  • packages/validators/src/platform-config.ts
Files not fully reviewed because their changes were unavailable: 1
  • packages/db/drizzle/meta/0064_snapshot.json

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@StevScripts StevScripts left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code rabbit fix

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

Labels

API Change modifies code in the global API/tRPC package Blade Change modifies code in Blade app Database Change modifies code in the DB package Feature New Feature or Request Major Big change - 2+ reviewers required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SPRINT-04] Career: add Discord config keys for posting channels and digest roles

1 participant