Skip to content

[codex] Add admin dashboard job lead review#374

Merged
michaelmwu merged 2 commits into
mainfrom
michaelmwu/gig-leads-dashboard
Jul 9, 2026
Merged

[codex] Add admin dashboard job lead review#374
michaelmwu merged 2 commits into
mainfrom
michaelmwu/gig-leads-dashboard

Conversation

@michaelmwu

@michaelmwu michaelmwu commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds a Gigs > Leads tab in the admin dashboard for sourced HN/job leads.
  • Adds dashboard endpoints to list, approve/reject, enqueue HN scraping, and post approved leads to Discord.
  • Reuses the Discord bot jobs cog posting path through a new authenticated internal bot endpoint, so approved leads become forum threads and are marked posted only after Discord succeeds.
  • Rebuilds the checked-in admin dashboard static assets.

Validation

  • ./scripts/test.sh
  • ./scripts/lint.sh
  • ./scripts/pyrefly.sh
  • cd apps/admin_dashboard && bun run build

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

  • New Features
    • Added sourced job-lead management to the Admin Dashboard, including a new gigs/leads tab, lead status filtering, refresh, and lead summary counts.
    • Enabled lead review (approve/reject), lead syncing (including HN scraping when permitted), and posting approved leads to Discord with confirmation details and loading feedback.
  • Bug Fixes
    • Improved lead loading/reloading so the dashboard stays consistent after actions and filter changes.
  • Tests
    • Added unit coverage for listing, reviewing, syncing, and posting job leads (including error mappings).

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This 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.

Changes

Gig Leads Feature

Layer / File(s) Summary
JobLead state and loading
apps/admin_dashboard/src/main.tsx
Adds JobLead state, lead status filtering, the gig-leads API URL builder, and lead-loading effects for the gigs view.
Lead actions and GigsView
apps/admin_dashboard/src/main.tsx
Adds sync, review, and post handlers; passes lead data and callbacks into GigsView; renders the gigs/leads tab UI and per-lead actions.
Backend job-lead endpoints
apps/api/src/five08/backend/api.py, apps/api/src/five08/backend/routes.py, apps/api/src/five08/backend/schemas.py
Adds request schemas, route contracts and registrations, a Discord post helper, and dashboard handlers for listing, reviewing, posting, and syncing leads.
Discord bot posting pipeline
apps/discord_bot/src/five08/discord_bot/cogs/jobs.py, apps/discord_bot/src/five08/discord_bot/utils/internal_api.py
Adds job-lead channel resolution, centralized Discord posting, the rewritten approve command, and the authenticated internal post route.
Startup output and port summary
scripts/dev.sh, scripts/worktree-env.sh
Adds shared startup banner output and a port-summary helper for local workflow scripts.
Tests and dashboard assets
tests/unit/test_backend_api.py, tests/unit/test_internal_api.py, tests/unit/test_jobs.py, tests/unit/test_worktree_env.py, apps/api/src/five08/backend/static/dashboard/*
Adds unit coverage for the new lead workflows and updates the dashboard’s hashed build assets and stylesheet bundle.

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
Loading

Possibly related PRs

  • 508-dev/508-workflows#215: Both PRs modify the Discord bot’s internal aiohttp internal_api.py surface to add/extend authenticated internal routes.
  • 508-dev/508-workflows#288: Both PRs modify apps/admin_dashboard/src/main.tsx’s GigsView/gigs UI flow with additional dashboard tab and state wiring.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is relevant and describes a real part of the changes, though it only covers the dashboard review workflow and not the broader leads/posting work.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch michaelmwu/gig-leads-dashboard

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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 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".

Comment thread apps/api/src/five08/backend/api.py
Comment thread apps/api/src/five08/backend/api.py
Comment thread apps/api/src/five08/backend/api.py
Comment thread apps/discord_bot/src/five08/discord_bot/cogs/jobs.py Outdated

@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.

Actionable comments posted: 3

🧹 Nitpick comments (4)
tests/unit/test_backend_api.py (1)

3984-4058: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider testing _post_job_lead_to_discord's own failure branches.

All tests mock _post_job_lead_to_discord directly, so its internal error paths (missing discord_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 win

Duplicate guild-resolution logic with internal_api.py.

_resolve_configured_guild reimplements InternalAPIRoutes._resolve_target_guild (same discord_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 InternalAPIRoutes can 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 lift

Missing direct unit test coverage for the new centralized posting helper.

post_job_lead_to_discord and 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 win

All 409 conflict reasons collapse into one generic failure message.

post_job_lead_to_discord distinguishes job_lead_already_posted, job_lead_rejected, and job_lead_not_approved, but the command only branches on status_code == 404 vs >= 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

📥 Commits

Reviewing files that changed from the base of the PR and between 8b98c75 and 291a8d2.

📒 Files selected for processing (14)
  • apps/admin_dashboard/src/main.tsx
  • apps/api/src/five08/backend/api.py
  • apps/api/src/five08/backend/routes.py
  • apps/api/src/five08/backend/schemas.py
  • apps/api/src/five08/backend/static/dashboard/.vite/manifest.json
  • apps/api/src/five08/backend/static/dashboard/assets/index-BQDfJvUA.css
  • apps/api/src/five08/backend/static/dashboard/assets/index-DJVNsvDL.js
  • apps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.css
  • apps/api/src/five08/backend/static/dashboard/assets/index-mTDqJ4Z1.js
  • apps/api/src/five08/backend/static/dashboard/index.html
  • apps/discord_bot/src/five08/discord_bot/cogs/jobs.py
  • apps/discord_bot/src/five08/discord_bot/utils/internal_api.py
  • tests/unit/test_backend_api.py
  • tests/unit/test_internal_api.py
💤 Files with no reviewable changes (1)
  • apps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.css

Comment thread apps/api/src/five08/backend/api.py
Comment thread apps/api/src/five08/backend/api.py
Comment thread apps/discord_bot/src/five08/discord_bot/cogs/jobs.py
@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@michaelmwu

Copy link
Copy Markdown
Member Author

Addressed the review feedback in amended commit 2b076592:

  • Restricted dashboard lead review/post/sync mutations to steering-level access, and hid mutation controls from regular Gigs writers.
  • Mapped bot 401 responses to 502 bot_auth_failed so the dashboard does not treat bot auth failures as browser session expiry.
  • Validated scrape sources before enqueueing lead sync jobs.
  • Restricted explicit Discord channel IDs to registered jobs forums in the configured guild.
  • Added audit logging for dashboard review and slash-command approval flows.
  • Improved bot error passthrough fallback and conflict messages.
  • Added focused backend and bot tests for the new branches.

Validation passed locally:

  • uv run pytest tests/unit/test_backend_api.py -k "dashboard_job_leads or dashboard_review_job_lead or dashboard_sync_job_leads or dashboard_post_job_lead or post_job_lead_to_discord" tests/unit/test_jobs.py -k "job_lead"
  • cd apps/admin_dashboard && bun run typecheck && bun run lint && bun run build
  • ./scripts/test.sh
  • ./scripts/lint.sh
  • ./scripts/pyrefly.sh

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 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".

Comment thread apps/api/src/five08/backend/api.py Outdated

@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.

🧹 Nitpick comments (1)
tests/unit/test_backend_api.py (1)

3978-4047: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding steering-level 403 tests for the post and sync endpoints.

The review endpoint has test_dashboard_review_job_lead_requires_steering verifying 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

📥 Commits

Reviewing files that changed from the base of the PR and between 291a8d2 and 2b07659.

📒 Files selected for processing (15)
  • apps/admin_dashboard/src/main.tsx
  • apps/api/src/five08/backend/api.py
  • apps/api/src/five08/backend/routes.py
  • apps/api/src/five08/backend/schemas.py
  • apps/api/src/five08/backend/static/dashboard/.vite/manifest.json
  • apps/api/src/five08/backend/static/dashboard/assets/index-BQDfJvUA.css
  • apps/api/src/five08/backend/static/dashboard/assets/index-DJVNsvDL.js
  • apps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.css
  • apps/api/src/five08/backend/static/dashboard/assets/index-YYDvtMqw.js
  • apps/api/src/five08/backend/static/dashboard/index.html
  • apps/discord_bot/src/five08/discord_bot/cogs/jobs.py
  • apps/discord_bot/src/five08/discord_bot/utils/internal_api.py
  • tests/unit/test_backend_api.py
  • tests/unit/test_internal_api.py
  • tests/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

@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@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.

🧹 Nitpick comments (1)
tests/unit/test_backend_api.py (1)

4125-4228: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Tests are correct and well-structured.

The direct unit tests for _post_job_lead_to_discord cover 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

📥 Commits

Reviewing files that changed from the base of the PR and between 2b07659 and 1db946b.

📒 Files selected for processing (18)
  • apps/admin_dashboard/src/main.tsx
  • apps/api/src/five08/backend/api.py
  • apps/api/src/five08/backend/routes.py
  • apps/api/src/five08/backend/schemas.py
  • apps/api/src/five08/backend/static/dashboard/.vite/manifest.json
  • apps/api/src/five08/backend/static/dashboard/assets/index-BQDfJvUA.css
  • apps/api/src/five08/backend/static/dashboard/assets/index-DJVNsvDL.js
  • apps/api/src/five08/backend/static/dashboard/assets/index-O0VUJuOk.css
  • apps/api/src/five08/backend/static/dashboard/assets/index-YYDvtMqw.js
  • apps/api/src/five08/backend/static/dashboard/index.html
  • apps/discord_bot/src/five08/discord_bot/cogs/jobs.py
  • apps/discord_bot/src/five08/discord_bot/utils/internal_api.py
  • scripts/dev.sh
  • scripts/worktree-env.sh
  • tests/unit/test_backend_api.py
  • tests/unit/test_internal_api.py
  • tests/unit/test_jobs.py
  • tests/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

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@cursor

cursor Bot commented Jul 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@michaelmwu
michaelmwu added this pull request to the merge queue Jul 9, 2026
Merged via the queue into main with commit e4025d8 Jul 9, 2026
13 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/gig-leads-dashboard branch July 9, 2026 05:33

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 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())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +1136 to +1138
const detail = await requestJson<JobDetail>(
`/dashboard/api/jobs/${encodeURIComponent(jobId)}`,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +3842 to +3843
created = await target_channel.create_thread(
name=self._truncate_job_lead_text(thread_title, 100),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant