[codex] Add admin dashboard job lead review#374
Conversation
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_b34a36fe-32c0-49ec-a255-c3f3587e209d) |
📝 WalkthroughWalkthroughThis PR adds sourced gig-lead management across the admin dashboard, backend API, Discord bot, internal API, scripts, tests, and dashboard build assets. It introduces listing, review, sync, and posting flows with matching UI, routing, and validation updates. ChangesGig Leads Feature
Estimated code review effort: 4 (Complex) | ~75 minutes Sequence Diagram(s)sequenceDiagram
participant AdminDashboard
participant BackendAPI
participant DiscordBot
participant DiscordServer
AdminDashboard->>BackendAPI: GET /dashboard/api/gig-leads
BackendAPI-->>AdminDashboard: JobLead[]
AdminDashboard->>BackendAPI: POST /dashboard/api/gig-leads/{lead_id}/review
BackendAPI-->>AdminDashboard: reviewed lead
AdminDashboard->>BackendAPI: POST /dashboard/api/gig-leads/{lead_id}/post
BackendAPI->>DiscordBot: internal post_job_lead request
DiscordBot->>DiscordServer: create forum thread
DiscordServer-->>DiscordBot: thread_id
DiscordBot-->>BackendAPI: post result
BackendAPI-->>AdminDashboard: thread/channel metadata
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 291a8d2d4a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (4)
tests/unit/test_backend_api.py (1)
3984-4058: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider testing
_post_job_lead_to_discord's own failure branches.All tests mock
_post_job_lead_to_discorddirectly, so its internal error paths (missingdiscord_bot_internal_base_url/api_shared_secret,httpx.HTTPError) are never exercised.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/test_backend_api.py` around lines 3984 - 4058, Add direct tests for _post_job_lead_to_discord’s internal failure branches instead of only mocking it at the dashboard layer. Cover the cases where discord_bot_internal_base_url or api_shared_secret is missing, and where the underlying httpx request raises httpx.HTTPError, so the function’s own error handling and returned status/payload are exercised. Locate this in tests/unit/test_backend_api.py рядом with test_dashboard_post_job_lead_* and target the _post_job_lead_to_discord helper itself.apps/discord_bot/src/five08/discord_bot/cogs/jobs.py (3)
3491-3501: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate guild-resolution logic with
internal_api.py.
_resolve_configured_guildreimplementsInternalAPIRoutes._resolve_target_guild(samediscord_server_id-then-single-guild-fallback logic) almost verbatim. Two independent copies risk silent drift if the resolution policy changes later.♻️ Extract a shared helper
Move this logic into a small shared utility (e.g. a module both the cog and
InternalAPIRoutescan import) and have both call sites delegate to it.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/discord_bot/src/five08/discord_bot/cogs/jobs.py` around lines 3491 - 3501, The guild resolution logic in _resolve_configured_guild duplicates InternalAPIRoutes._resolve_target_guild, so extract the shared discord_server_id parsing and single-guild fallback into a common helper module and have both callers delegate to it. Keep the behavior identical by reusing the same get_guild/int conversion and fallback rules, so any future changes happen in one place only.
3569-3672: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftMissing direct unit test coverage for the new centralized posting helper.
post_job_lead_to_discordand its helpers (_resolve_job_lead_post_channel,_resolve_configured_guild,_fetch_forum_channel) contain non-trivial branching (status gating, channel resolution fallbacks, Forbidden/HTTPException handling) but the only tests provided (test_internal_api.py) mock the cog entirely, so this logic itself is untested in this diff.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/discord_bot/src/five08/discord_bot/cogs/jobs.py` around lines 3569 - 3672, Add direct unit tests for post_job_lead_to_discord and the helper path it relies on, since the current tests only mock the cog and miss the new branching logic. Cover the main branches in post_job_lead_to_discord plus _resolve_job_lead_post_channel, _resolve_configured_guild, and _fetch_forum_channel: approved vs non-approved leads, approve_before_post behavior, channel resolution fallbacks, and discord.Forbidden/discord.HTTPException failures. Use the real helper methods with focused mocks for Discord and job-lead storage so the centralized posting flow is exercised end to end.
3794-3806: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAll 409 conflict reasons collapse into one generic failure message.
post_job_lead_to_discorddistinguishesjob_lead_already_posted,job_lead_rejected, andjob_lead_not_approved, but the command only branches onstatus_code == 404vs>= 400, so a reviewer gets the same "❌ Failed to approve and post this job lead." message whether the lead was already posted, rejected, or otherwise not approvable.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/discord_bot/src/five08/discord_bot/cogs/jobs.py` around lines 3794 - 3806, The approval/post flow in the jobs cog is collapsing all 409 conflicts into one generic error message. Update the `post_job_lead_to_discord` result handling in the command path so it inspects the conflict reason returned in `result` and sends a specific followup for `job_lead_already_posted`, `job_lead_rejected`, and `job_lead_not_approved` instead of always using the generic failure text. Keep the existing `status_code == 404` branch, and refine the `status_code >= 400` path in the same `interaction.followup.send`/`logger.warning` block to map each reason to a distinct user-facing message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/api/src/five08/backend/api.py`:
- Around line 4057-4094: The dashboard review flow in
dashboard_review_job_lead_handler is missing an audit write for approve/reject
actions. After review_job_lead succeeds, add a call to _write_auth_audit_event
using the current session/reviewer and the lead review action details, matching
the pattern used in dashboard_post_job_lead_handler and
dashboard_sync_job_leads_handler. Also update the test cases for
test_dashboard_review_job_lead_* to assert that insert_audit_event is called for
successful review requests.
- Around line 1041-1082: In _post_job_lead_to_discord, empty or unparsable
response bodies from the Discord bot currently fall through as an empty payload
on non-2xx responses, leaving callers without an error message. Update the
response handling after response.json() so that when the status is not
successful and payload has no error field, you return a generic error value in
the payload (while preserving the bot’s actual error when present). Keep the
behavior localized to _post_job_lead_to_discord and ensure the returned dict
always includes a useful error message on failure.
In `@apps/discord_bot/src/five08/discord_bot/cogs/jobs.py`:
- Around line 3786-3811: The approve/post flow in approve_sourced_job_lead is
missing the required best-effort audit write, unlike the other
Steering-Committee-gated commands in this cog. Add an audit call using
_audit_command or _audit_command_safe for this human-triggered CRM action, and
make sure it runs for both the success path and the failure paths around
post_job_lead_to_discord / the status_code checks, without blocking the existing
followup responses if auditing fails.
---
Nitpick comments:
In `@apps/discord_bot/src/five08/discord_bot/cogs/jobs.py`:
- Around line 3491-3501: The guild resolution logic in _resolve_configured_guild
duplicates InternalAPIRoutes._resolve_target_guild, so extract the shared
discord_server_id parsing and single-guild fallback into a common helper module
and have both callers delegate to it. Keep the behavior identical by reusing the
same get_guild/int conversion and fallback rules, so any future changes happen
in one place only.
- Around line 3569-3672: Add direct unit tests for post_job_lead_to_discord and
the helper path it relies on, since the current tests only mock the cog and miss
the new branching logic. Cover the main branches in post_job_lead_to_discord
plus _resolve_job_lead_post_channel, _resolve_configured_guild, and
_fetch_forum_channel: approved vs non-approved leads, approve_before_post
behavior, channel resolution fallbacks, and
discord.Forbidden/discord.HTTPException failures. Use the real helper methods
with focused mocks for Discord and job-lead storage so the centralized posting
flow is exercised end to end.
- Around line 3794-3806: The approval/post flow in the jobs cog is collapsing
all 409 conflicts into one generic error message. Update the
`post_job_lead_to_discord` result handling in the command path so it inspects
the conflict reason returned in `result` and sends a specific followup for
`job_lead_already_posted`, `job_lead_rejected`, and `job_lead_not_approved`
instead of always using the generic failure text. Keep the existing `status_code
== 404` branch, and refine the `status_code >= 400` path in the same
`interaction.followup.send`/`logger.warning` block to map each reason to a
distinct user-facing message.
In `@tests/unit/test_backend_api.py`:
- Around line 3984-4058: Add direct tests for _post_job_lead_to_discord’s
internal failure branches instead of only mocking it at the dashboard layer.
Cover the cases where discord_bot_internal_base_url or api_shared_secret is
missing, and where the underlying httpx request raises httpx.HTTPError, so the
function’s own error handling and returned status/payload are exercised. Locate
this in tests/unit/test_backend_api.py рядом with test_dashboard_post_job_lead_*
and target the _post_job_lead_to_discord helper itself.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9f358839-e4f0-49ab-bfd1-e541681e9fde
📒 Files selected for processing (14)
apps/admin_dashboard/src/main.tsxapps/api/src/five08/backend/api.pyapps/api/src/five08/backend/routes.pyapps/api/src/five08/backend/schemas.pyapps/api/src/five08/backend/static/dashboard/.vite/manifest.jsonapps/api/src/five08/backend/static/dashboard/assets/index-BQDfJvUA.cssapps/api/src/five08/backend/static/dashboard/assets/index-DJVNsvDL.jsapps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.cssapps/api/src/five08/backend/static/dashboard/assets/index-mTDqJ4Z1.jsapps/api/src/five08/backend/static/dashboard/index.htmlapps/discord_bot/src/five08/discord_bot/cogs/jobs.pyapps/discord_bot/src/five08/discord_bot/utils/internal_api.pytests/unit/test_backend_api.pytests/unit/test_internal_api.py
💤 Files with no reviewable changes (1)
- apps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.css
291a8d2 to
2b07659
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_3655aebc-d7a2-4176-a2d7-2b5f9037dc59) |
|
Addressed the review feedback in amended commit
Validation passed locally:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2b076592e1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/unit/test_backend_api.py (1)
3978-4047: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding steering-level 403 tests for the post and sync endpoints.
The review endpoint has
test_dashboard_review_job_lead_requires_steeringverifying non-steering users get 403, but the post (POST /dashboard/api/gig-leads/{lead_id}/post) and sync (POST /dashboard/api/gig-leads/sync) endpoints lack equivalent tests. Adding 403 tests for these endpoints would ensure their steering checks aren't accidentally removed, consistent with the PR objective of restricting all gig-lead mutations to steering-level access.🧪 Suggested 403 tests for post and sync endpoints
def test_dashboard_post_job_lead_requires_steering(client: TestClient) -> None: session = api.AuthSession( subject="123456789", email="member@508.dev", display_name="Member User", groups=["Member"], is_admin=False, id_token="", expires_at=4_102_444_800, actor_provider=api.ActorProvider.DISCORD.value, ) with ( patch( "five08.backend.api._current_session", new_callable=AsyncMock, return_value=("session-1", session), ), patch("five08.backend.api._post_job_lead_to_discord") as mock_post, ): response = client.post("/dashboard/api/gig-leads/lead-1/post", json={}) assert response.status_code == 403 assert response.json() == {"error": "steering_required"} mock_post.assert_not_called() def test_dashboard_sync_job_leads_requires_steering(client: TestClient) -> None: session = api.AuthSession( subject="123456789", email="member@508.dev", display_name="Member User", groups=["Member"], is_admin=False, id_token="", expires_at=4_102_444_800, actor_provider=api.ActorProvider.DISCORD.value, ) with ( patch( "five08.backend.api._current_session", new_callable=AsyncMock, return_value=("session-1", session), ), patch("five08.backend.api.enqueue_job") as mock_enqueue, ): response = client.post( "/dashboard/api/gig-leads/sync", json={"source": "hackernews_who_is_hiring"}, ) assert response.status_code == 403 assert response.json() == {"error": "steering_required"} mock_enqueue.assert_not_called()Also applies to: 4050-4123
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/test_backend_api.py` around lines 3978 - 4047, Add steering-level 403 coverage for the gig-lead mutation endpoints to match the existing `test_dashboard_review_job_lead_requires_steering` check. Extend the `test_backend_api.py` suite with tests for `POST /dashboard/api/gig-leads/{lead_id}/post` and `POST /dashboard/api/gig-leads/sync` using a non-steering `api.AuthSession`, and assert they return `403` with `{"error": "steering_required"}`. Use the same mocking pattern around `_current_session`, `_post_job_lead_to_discord`, and `enqueue_job` to verify the handlers abort before any side effects.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/unit/test_backend_api.py`:
- Around line 3978-4047: Add steering-level 403 coverage for the gig-lead
mutation endpoints to match the existing
`test_dashboard_review_job_lead_requires_steering` check. Extend the
`test_backend_api.py` suite with tests for `POST
/dashboard/api/gig-leads/{lead_id}/post` and `POST
/dashboard/api/gig-leads/sync` using a non-steering `api.AuthSession`, and
assert they return `403` with `{"error": "steering_required"}`. Use the same
mocking pattern around `_current_session`, `_post_job_lead_to_discord`, and
`enqueue_job` to verify the handlers abort before any side effects.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 95b89422-4f90-49eb-8f70-4e3bea68ed4a
📒 Files selected for processing (15)
apps/admin_dashboard/src/main.tsxapps/api/src/five08/backend/api.pyapps/api/src/five08/backend/routes.pyapps/api/src/five08/backend/schemas.pyapps/api/src/five08/backend/static/dashboard/.vite/manifest.jsonapps/api/src/five08/backend/static/dashboard/assets/index-BQDfJvUA.cssapps/api/src/five08/backend/static/dashboard/assets/index-DJVNsvDL.jsapps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.cssapps/api/src/five08/backend/static/dashboard/assets/index-YYDvtMqw.jsapps/api/src/five08/backend/static/dashboard/index.htmlapps/discord_bot/src/five08/discord_bot/cogs/jobs.pyapps/discord_bot/src/five08/discord_bot/utils/internal_api.pytests/unit/test_backend_api.pytests/unit/test_internal_api.pytests/unit/test_jobs.py
💤 Files with no reviewable changes (1)
- apps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.css
✅ Files skipped from review due to trivial changes (2)
- apps/api/src/five08/backend/static/dashboard/.vite/manifest.json
- apps/api/src/five08/backend/static/dashboard/index.html
🚧 Files skipped from review as they are similar to previous changes (7)
- tests/unit/test_internal_api.py
- apps/api/src/five08/backend/schemas.py
- apps/discord_bot/src/five08/discord_bot/utils/internal_api.py
- apps/discord_bot/src/five08/discord_bot/cogs/jobs.py
- apps/api/src/five08/backend/routes.py
- apps/api/src/five08/backend/api.py
- apps/admin_dashboard/src/main.tsx
2b07659 to
1db946b
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_ecedf890-eac2-43be-9d25-d38cdaacca92) |
1db946b to
e94740e
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_da07a59e-e9ae-4cbd-9d13-33bed46b69c9) |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/unit/test_backend_api.py (1)
4125-4228: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueTests are correct and well-structured.
The direct unit tests for
_post_job_lead_to_discordcover the key failure paths (401, missing endpoint, missing secret, empty body, connect error) and all assertions match the implementation. Consider adding a direct unit test for the success case (status < 200) and the error-passthrough case (status ≥ 400 with"error"already in the bot response payload) to fully exercise the function in isolation, since those paths are currently only covered indirectly through the endpoint-level tests.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/test_backend_api.py` around lines 4125 - 4228, Add direct unit coverage for the remaining _post_job_lead_to_discord branches that are only exercised indirectly: the success path when the bot returns a 2xx response, and the error-passthrough path when the bot returns a 4xx/5xx response with an "error" field. Extend the tests in test_post_job_lead_to_discord_* using the same Mock/AsyncMock and _http_client_from_app patch pattern, and assert the returned status code and payload from _post_job_lead_to_discord match the implementation for those cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/unit/test_backend_api.py`:
- Around line 4125-4228: Add direct unit coverage for the remaining
_post_job_lead_to_discord branches that are only exercised indirectly: the
success path when the bot returns a 2xx response, and the error-passthrough path
when the bot returns a 4xx/5xx response with an "error" field. Extend the tests
in test_post_job_lead_to_discord_* using the same Mock/AsyncMock and
_http_client_from_app patch pattern, and assert the returned status code and
payload from _post_job_lead_to_discord match the implementation for those cases.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d8c7bb2e-ae80-47ec-8475-0460e0d70079
📒 Files selected for processing (18)
apps/admin_dashboard/src/main.tsxapps/api/src/five08/backend/api.pyapps/api/src/five08/backend/routes.pyapps/api/src/five08/backend/schemas.pyapps/api/src/five08/backend/static/dashboard/.vite/manifest.jsonapps/api/src/five08/backend/static/dashboard/assets/index-BQDfJvUA.cssapps/api/src/five08/backend/static/dashboard/assets/index-DJVNsvDL.jsapps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.cssapps/api/src/five08/backend/static/dashboard/assets/index-YYDvtMqw.jsapps/api/src/five08/backend/static/dashboard/index.htmlapps/discord_bot/src/five08/discord_bot/cogs/jobs.pyapps/discord_bot/src/five08/discord_bot/utils/internal_api.pyscripts/dev.shscripts/worktree-env.shtests/unit/test_backend_api.pytests/unit/test_internal_api.pytests/unit/test_jobs.pytests/unit/test_worktree_env.py
💤 Files with no reviewable changes (1)
- apps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.css
✅ Files skipped from review due to trivial changes (2)
- apps/api/src/five08/backend/static/dashboard/.vite/manifest.json
- apps/api/src/five08/backend/static/dashboard/index.html
🚧 Files skipped from review as they are similar to previous changes (8)
- tests/unit/test_internal_api.py
- apps/api/src/five08/backend/schemas.py
- tests/unit/test_jobs.py
- apps/discord_bot/src/five08/discord_bot/utils/internal_api.py
- apps/api/src/five08/backend/routes.py
- apps/api/src/five08/backend/api.py
- apps/admin_dashboard/src/main.tsx
- apps/discord_bot/src/five08/discord_bot/cogs/jobs.py
e94740e to
24198d1
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_372df942-ea29-4f04-a0d0-aaf2e4ac20d7) |
3511ac6 to
ba17f98
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_b9c35e58-8558-4f7a-9d6b-4f254d0f2144) |
ba17f98 to
72c4a9e
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_e8eb9e3d-afaf-4a5d-ad7c-5dd58e1521a6) |
72c4a9e to
1ecde46
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_8d7aa04e-2487-4cc2-b237-811ee050c405) |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_09be7b38-7011-4029-85f9-978e0932252b) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 47c6207990
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| async function loadGigLeads() { | ||
| setBusy("gigLeads", true) | ||
| try { | ||
| const payload = await requestJson<JobLead[]>(gigLeadsUrl()) |
There was a problem hiding this comment.
Gate lead fetches for non-steering gig viewers
For regular Member sessions, /dashboard/api/gig-leads now returns 403 because the API requires steering access, but loadGigLeads is still called whenever the Gigs view loads or refreshes. Opening or searching the normal Gigs tab therefore shows an error toast even though the user has valid gigs:read access; guard this fetch on the same manage-leads/steering condition or only run it when the Leads tab is available.
Useful? React with 👍 / 👎.
| const detail = await requestJson<JobDetail>( | ||
| `/dashboard/api/jobs/${encodeURIComponent(jobId)}`, | ||
| ) |
There was a problem hiding this comment.
Allow lead sync pollers to read their job status
When a Steering Committee user clicks Scrape HN, this polls /dashboard/api/jobs/{job_id}, but that dashboard job-detail endpoint requires jobs:read while steering users only get the gig/people/project permissions needed to queue the scrape. The poll therefore gets a 403, shows “Unable to monitor HN lead scrape,” and never refreshes the lead list even if the job succeeds; use a lead-sync status endpoint/response that is permitted for these users or otherwise allow them to read this job.
Useful? React with 👍 / 👎.
| created = await target_channel.create_thread( | ||
| name=self._truncate_job_lead_text(thread_title, 100), |
There was a problem hiding this comment.
Claim the lead before creating the Discord thread
If two operators post the same pending/approved lead at nearly the same time, both requests can pass the current status checks and reach this Discord side effect before either call to mark_job_lead_posted flips the row to posted. The losing request then returns job_lead_post_marker_failed, but it has already created a duplicate forum thread; claim or transition the lead under the database guard before calling Discord, or make the Discord create idempotent.
Useful? React with 👍 / 👎.
| except Exception: | ||
| return JSONResponse({"error": "invalid_payload"}, status_code=400) | ||
|
|
||
| reviewer = _session_discord_actor_id(session) or session.subject |
There was a problem hiding this comment.
Require Discord actors for recruiting lead posts
For Admin SSO sessions that are not Discord-linked, this fallback sends the OIDC subject as reviewer_discord_user_id; the bot then persists it as posted_by_discord_user_id on the created engagement. If the operator posts the lead as recruiting, _send_due_recruiting_reminders later calls int(poster_id) to mention the poster, so every stale reminder for that gig fails instead of notifying anyone; require a Discord-backed actor for Discord posts or avoid storing non-Discord subjects in that column.
Useful? React with 👍 / 👎.
Summary
Validation
Note
Medium Risk
New steering-gated mutations and Discord posting integrate with the bot and queue; misconfiguration or bot failures surface as 502/503, but scope is confined to admin dashboard operators.
Overview
Adds sourced job lead management to the admin Gigs view: a Leads tab alongside gigs, with status filtering, summary metrics, HN scrape/sync, approve/reject, and Post to Discord (channel, engagement status, forum tags).
The API gains dashboard routes for listing leads, job channels, syncing (
scrape_job_leads_job), reviewing, and posting via the Discord bot internal API. Lead list/sync/review/post mutations require steering access; reads use existing gig permissions. Audit events cover review, post, and sync.The UI polls background jobs after scrape using new
isTerminalJobStatus, adds lead to gig status filters, and rebuilds static dashboard assets. Unit tests cover terminal job status detection.Reviewed by Cursor Bugbot for commit 47c6207. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit