Skip to content

Security: production defense-in-depth baseline - #6

Open
arena-ai-coding-agent[bot] wants to merge 20 commits into
mainfrom
arena/019f5f46-yummy
Open

arena-ai-coding-agent[bot] wants to merge 20 commits into
mainfrom
arena/019f5f46-yummy

Conversation

@arena-ai-coding-agent

@arena-ai-coding-agent arena-ai-coding-agent Bot commented Jul 14, 2026

Copy link
Copy Markdown

Summary

  • enforce object-level authorization and tenant isolation for partner resources
  • redact public order responses and replace short pickup codes with 50-bit CSPRNG codes
  • move browser authentication to same-origin Secure/HttpOnly/SameSite cookies with CSRF and strict script CSP
  • add Argon2id migration, strict JWT claims, refresh-family rotation/reuse detection, and mandatory encrypted TOTP MFA for admins
  • add email verification/password recovery, partner approval/suspension, and owner-scoped refund requests with MFA-admin decisions
  • add request/Host/body hardening, security headers, audit events, production fail-fast checks, and optional Redis distributed rate limiting
  • split frontend assets, harden PWA caching, add reproducible lock files, security architecture/implementation plans, and expanded security tests

Validation

  • 115 pytest tests pass
  • Ruff passes
  • Bandit reports 0 findings
  • pip-audit reports no known vulnerabilities
  • Python compileall and JavaScript syntax checks pass
  • generated Pages bundle is reproducible
  • production smoke checks cover HttpOnly cookie flags, CSRF denial/allow, strict CSP, MFA assurance, and private API access

Deployment notes

  • production now requires separate YUMMY_SECRET_KEY and YUMMY_DATA_KEY
  • production browser UI must be served same-origin from the backend; GitHub Pages remains an isolated demo
  • configure Resend variables to enable transactional email; disabled mode supports audited manual verification
  • set REDIS_URL and YUMMY_RATE_LIMIT_KEY for distributed limits across replicas
  • new partner accounts start pending and require verified email plus MFA-admin approval

CI permission note

Arena's GitHub App token cannot update .github/workflows/* because it lacks the workflows permission. The complete Actions pipeline is included as ci/github-actions.yml.example; copy it to .github/workflows/ci.yml from an account with workflow permission to activate it.

PostgreSQL / Alembic update

  • production now requires DATABASE_URL and fails fast on SQLite
  • repositories support PostgreSQL through a psycopg DB-API compatibility adapter
  • complete initial Alembic schema covers auth, MFA, email actions, partners, inventory, orders, reviews, and refunds
  • Render provisions managed PostgreSQL and runs alembic upgrade head pre-deploy
  • SQLite remains the explicit dev/test fallback
  • migration tests apply the schema to fresh SQLite, compile PostgreSQL offline DDL, and provide an optional real-PostgreSQL integration flow
  • Redis distributed limiting plus PostgreSQL removes the previous single-file/single-instance boundary

PostgreSQL pooling update

  • all PostgreSQL repositories now share a lazy bounded psycopg_pool.ConnectionPool
  • pool min/max/checkout timeout are configurable and connection budgets are documented per replica
  • transaction contexts commit on success, roll back on exception, and return clean connections to the pool
  • application shutdown closes all pools gracefully
  • optional real-PostgreSQL integration now runs two independent repository instances concurrently against the last inventory item and asserts exactly one successful order

Stripe Checkout state machine

  • added test-mode Stripe Checkout gateway with server-side amount/currency and idempotency keys
  • inventory is reserved as payment_pending; Stripe/API failures and expired reservations release it exactly once
  • added raw-body webhook signature adapter, unique event deduplication, and amount/currency/order reconciliation
  • QR/pickup data is returned only after a reconciled paid webhook
  • added Alembic payment/event schema and tests for success, duplicate events, amount mismatch, provider failure, and reservation expiry
  • live Stripe/Connect remains gated on merchant-country availability and production credentials

Invitation-only staff access

  • removed the public demo PIN and all buyer-visible partner/admin navigation
  • production partner registration is blocked unless a server-issued invitation is used
  • MFA-admin can create seven-day, single-use, hashed invitation links for a new owner or existing partner manager/cashier
  • invitation acceptance creates a personal HttpOnly-cookie account bound to one tenant
  • owner/manager can publish inventory; cashier is limited to operational order access/redeem
  • added Alembic staff invitation schema and negative tests for token replay, public signup bypass, tenant binding, and cashier privilege escalation

Strict production/demo isolation

  • production startup now rejects YUMMY_PAYMENT_MODE=demo
  • empty production databases remain empty; demo seed data is development-only
  • fake-paid /orders, /admin/seed, static venues.json, local venue bookings, demo reviews, and demo staff access are blocked/hidden in production
  • payment_mode=disabled supports a fail-closed catalog while real provider credentials are pending
  • buyer UI receives explicit environment/payment capability flags and disables checkout when payments are unavailable

Partner billing and VPS deployment

  • added encrypted per-partner merchant accounts with masked API responses and MFA-admin activation/suspension
  • added versioned commission rules in integer basis points, idempotent commission ledger, and invoice schema
  • production checkout now requires an active payment-ready account for the selected partner
  • added partner self-service payment readiness and commission ledger endpoints
  • added Alembic partner billing revision and encryption/commission tests
  • added hardened VPS Docker Compose, Caddy automatic TLS, internal Redis, health checks, env template, and deploy script
  • added a read-only production checker for Supabase revision/tables, Redis, timeouts, and secret presence without printing DSNs

Admin control plane, customer UX, and notifications

  • added MFA-only admin APIs/UI for users, partners, staff, payment accounts, payments, webhook mismatches, refunds, commission data, audit events, blocking/session revoke, and MFA rotation
  • added persistent audit event storage and payment reconciliation mismatch alerts
  • added encrypted transactional notification outbox with dedupe, exponential retry, ARQ delivery, and dead-letter state
  • expanded partner cabinet with inventory edit/close, staff/invitation management, billing status, invoices, daily analytics, and CSV export
  • added approved-partner cards, geolocation sorting, payment/refund status display, email resend flow, and modal focus trapping

Observability and disaster recovery

  • added structured JSON logs, Sentry integration, OTLP tracing, and a secret-protected Prometheus endpoint
  • metrics cover HTTP latency/status, DB pool waiters, Redis failures, oldest pending payment/refund, webhook failures, reservation expiry, and email delivery retries/dead letters
  • added age-encrypted pg_dump with SHA-256 verification and retention
  • added a restore drill that refuses the production target, restores only to a separate database, and validates Alembic revision/table count
  • added RPO/RTO targets and incident/payment/database recovery runbooks

Load, DAST, and pentest tooling

  • added k6 catalog thresholds, last-box checkout race, signed webhook burst, partner-order load, and redeem race scenarios
  • added Locust catalog/authenticated customer workloads
  • added guarded Redis outage and PostgreSQL failover/pool saturation drills
  • added ZAP baseline configuration and manual staging-only workflow template
  • added a detailed manual pentest checklist for auth, BOLA, browser/API, payment races, infrastructure, backup, and exit criteria
  • all active load/DAST/chaos scripts require explicit authorization flags and refuse production-looking targets

wpalish and others added 5 commits July 14, 2026 10:38
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
wpalish pushed a commit that referenced this pull request Jul 14, 2026
PR #6 (+7908/−3565) не мерджится целиком: отведён от 37e0557 (удалил бы
Telegram-уведомления и связку Pages→бэкенд), требует новые обязательные env
и ломает 10-минутный онбординг партнёра (pending+email-верификация+MFA).
Оставлен открытым как банк решений. Отсюда взято лучшее малое, реализовано
своими руками (их код не исполнялся, только читался):

- коды выдачи: 6 символов из криптостойкого алфавита без похожих символов
  (0/O, 1/I/L) — 27^6 ≈ 387 млн комбинаций вместо 65 тыс. у hex-4; легко
  диктовать на кассе (идея дублируется и в Devin PR #5)
- security-заголовки: + Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy
- Dockerfile: non-root пользователь, PYTHONDONTWRITEBYTECODE/UNBUFFERED,
  YUMMY_DB_PATH=/data по умолчанию
- tools/create_admin.py: bootstrap/повышение админа через getpass (пароль не
  светится в history), promote отзывает все сессии (token_ver+1)
- .github/dependabot.yml: еженедельные обновления pip/actions/docker
- ci/github-actions.yml.example: полный CI (pytest+bandit+CodeQL+trivy+доксборка),
  как example — токен без scope workflow не может пушить воркфлоу

Проверено: 75 тестов зелёные, create_admin смок (created/promoted) на врем. БД.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
wpalish and others added 4 commits July 14, 2026 11:28
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
wpalish pushed a commit that referenced this pull request Jul 16, 2026
…арточка); +контраст футера

По UX-ревью:
- #1 localStorage-нотис был плавающей центр-карточкой (читалось как «глюк»
  поверх секций) → тонкая полоса во всю ширину, приклеена к низу (над bottom-nav
  на мобиле, к краю на десктопе). Показ один раз (флаг ym_cookies уже был).
- #6 контраст копирайта/FAQ-текста в футере поднят (.6→.78, .7→.82 opacity) —
  запас под WCAG AA.
Уже было в коде: #4 срочность («🔥 осталось N» + окно выдачи), #7 соцсети на
светлом --on-ink (не бледные). Требуют ассетов (отдельно): #2 превью карты,
#3 логотипы партнёров/отзывы, #5 лого-марка, #8 PWA-бейджи.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
wpalish and others added 11 commits July 17, 2026 06:34
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
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