Claude/breaker19 mvp build tf3b3i - #68
Conversation
…dashboard - Next.js 14 app with TypeScript, Tailwind, dark ocean theme - Prisma schema: Customer, Domain, ScanRun, Finding, ReputationCheck, DnsRecordSnapshot - Real DNS scanners: SPF (multi-record, lookup count), DMARC, DKIM (13 selectors), DNSSEC, CAA - Reputation module: Spamhaus DBL (live), Google Safe Browsing/VirusTotal/Talos/URLScan/SmartScreen (placeholders) - Scoring engine: starts at 100, deductions per spec, posture: healthy/watch/needs_improvement/poor - Dashboard, Customers, Domains, Findings, Reputation, Settings pages - API routes: GET/POST /api/domains, /api/domains/[id], /api/scan/domain, /api/scan/all, /api/findings, PATCH /api/findings/[id] - Slack alert abstractions: score drop, poor posture, DMARC disappear, SPF invalid, blacklist hit - Scanner worker: npm run scan:all (tsx scripts/scan-all.ts) - Seed data: Spinato's Pizza (score 35, poor) and Atlas Healthcare Partners (score 65, needs_improvement) - DigitalOcean App Platform config: .do/app.yaml with web service + hourly scheduled scanner job - GitHub Actions CI: lint, tsc, build Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RMiVydSVDjTrqBCeG8k8PJ
…schema Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RMiVydSVDjTrqBCeG8k8PJ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RMiVydSVDjTrqBCeG8k8PJ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RMiVydSVDjTrqBCeG8k8PJ
…ds, bento dashboard, spring-physics animations Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RMiVydSVDjTrqBCeG8k8PJ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RMiVydSVDjTrqBCeG8k8PJ
…eist font, Doppelrand cards, spring-physics motion, bento dashboard
- FastAPI backend with async SQLAlchemy, call CRUD, upload endpoint, stats API, and Alembic migrations (PostgreSQL schema with all 10 statuses) - WhisperX worker: pulls from Redis queue, normalizes audio with proven ffmpeg preprocessing (volume=30dB, dynaudnorm, bandpass), transcribes, scores quality, and routes to correct status - QA scorer: mean word confidence < 0.60 poor_audio; avg_logprob < -1.0 needs_review; duration < 20s needs_review; PCI terms compliance_review; cancellation/legal language needs_review - Next.js 14 board UI: status filter tabs with live counts, quality bars, upload modal, call detail slide-over with reviewer notes and status override - Docker Compose wiring all services with GPU reservation for worker - DigitalOcean deployment docs targeting 146.190.240.94
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f18cfd50d0
ℹ️ 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".
| ENV NODE_ENV=production | ||
| COPY --from=builder /app/.next/standalone ./ | ||
| COPY --from=builder /app/.next/static ./.next/static | ||
| COPY --from=builder /app/public ./public |
There was a problem hiding this comment.
Stop copying a public directory that is not in the image
The current breaker19/frontend tree has no public/ directory, so the frontend Docker build reaches this COPY --from=builder /app/public ./public step and fails with a missing source path before docker compose up --build can start the UI. Either add the directory or remove/guard this copy when no public assets are needed.
Useful? React with 👍 / 👎.
| REDIS_URL: redis://redis:6379 | ||
| AUDIO_UPLOAD_DIR: /data/audio | ||
| SECRET_KEY: ${SECRET_KEY:-changeme-in-production} | ||
| CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000} |
There was a problem hiding this comment.
Encode CORS_ORIGINS as a list value
With the compose default (and the .env.example value), this sets CORS_ORIGINS to a bare URL string, but app.core.config.Settings declares it as List[str]; pydantic-settings 2.x decodes list fields from JSON, so importing settings raises during backend startup instead of starting FastAPI. Use a JSON list such as ["http://localhost:3000"] or add a validator that accepts comma-separated strings.
Useful? React with 👍 / 👎.
| depends_on: | ||
| - backend | ||
| environment: | ||
| NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8000} |
There was a problem hiding this comment.
Provide NEXT_PUBLIC_API_URL during the image build
This runtime-only environment variable is too late for the browser bundle: src/lib/api.ts reads process.env.NEXT_PUBLIC_API_URL in client code, and Next embeds NEXT_PUBLIC_* values when npm run build runs in the Dockerfile. In a remote deployment, the built JS therefore falls back to http://localhost:8000, causing users' browsers to call their own localhost instead of the API unless the value is also passed as a build arg/env.
Useful? React with 👍 / 👎.
| @router.post("/", response_model=dict) | ||
| async def upload_audio( | ||
| file: UploadFile = File(...), | ||
| agent_name: str | None = None, |
There was a problem hiding this comment.
Read agent_name from the multipart form
The upload modal appends agent_name to the multipart FormData, but this FastAPI parameter is declared as a plain optional string, so FastAPI treats it as a query parameter rather than a form field. Any agent name entered during upload is silently stored as NULL unless the client also adds ?agent_name=...; declare it with Form(None) to match the request body.
Useful? React with 👍 / 👎.
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp: | ||
| clean_path = tmp.name | ||
|
|
||
| try: |
There was a problem hiding this comment.
Mark failed transcriptions instead of leaving them in progress
If normalize_audio, WhisperX transcription, scoring, or the final database update raises after the row has been set to transcribing/qa_scoring, this block only deletes the temp file and then the outer loop logs the exception and continues. Those calls remain stuck in an in-progress status forever, so users cannot distinguish a failed job from one still running; catch processing errors here and update the call to failed before re-raising or continuing.
Useful? React with 👍 / 👎.
| repo: chelstein/taste-skill | ||
| branch: main | ||
| deploy_on_push: true | ||
| build_command: npm install && npx prisma generate && npm run build |
There was a problem hiding this comment.
Apply the Prisma schema during deploy
The DigitalOcean spec provisions a fresh Postgres database, but the service build only runs prisma generate and next build; the local setup requires prisma db push, and there are no migrations for migrate deploy. On a new App Platform deployment the database has no tables, so API routes and the scheduled scanner hit Prisma errors until someone manually pushes the schema; add a deploy/release step that applies the schema before the app/job runs.
Useful? React with 👍 / 👎.
| const hardfail = primary.includes('-all'); | ||
|
|
||
| // Count DNS-lookup mechanisms (a, mx, include, exists, redirect) | ||
| const lookupMechanisms = (primary.match(/\b(include:|a:|mx:|exists:|redirect=)/gi) ?? []).length; |
There was a problem hiding this comment.
Count bare SPF a and mx mechanisms
For SPF records that use common bare mechanisms like a or mx, this regex only matches a: and mx:, so those DNS lookups are omitted from the 10-lookup budget. Domains can exceed the SPF lookup limit while tooManyLookups remains false, causing the scanner to miss the PermError risk and avoid the intended score deduction.
Useful? React with 👍 / 👎.
| @@ -0,0 +1,36 @@ | |||
| name: CI | |||
There was a problem hiding this comment.
Move the workflow to the repository root
GitHub Actions only discovers workflows under the repository root .github/workflows, but this file is nested under reefguard/.github/workflows. As committed, the lint/typecheck/build workflow described in the README will not run on pushes or pull requests for this repo; place it at .github/workflows/ci.yml with the existing working-directory: reefguard settings.
Useful? React with 👍 / 👎.
No description provided.