Skip to content

Claude/breaker19 mvp build tf3b3i - #68

Open
chelstein wants to merge 12 commits into
Leonxlnx:mainfrom
chelstein:claude/breaker19-mvp-build-tf3b3i
Open

Claude/breaker19 mvp build tf3b3i#68
chelstein wants to merge 12 commits into
Leonxlnx:mainfrom
chelstein:claude/breaker19-mvp-build-tf3b3i

Conversation

@chelstein

Copy link
Copy Markdown

No description provided.

claude and others added 12 commits June 30, 2026 14:04
…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
…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

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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,

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 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:

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

Comment thread reefguard/.do/app.yaml
repo: chelstein/taste-skill
branch: main
deploy_on_push: true
build_command: npm install && npx prisma generate && npm run build

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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;

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

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

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.

2 participants