Scaffold basketball-api project #2

Closed
forgejo_admin wants to merge 9 commits from 1-scaffold-project into main

FastAPI + SQLAlchemy + Stripe webhooks + gmail-sdk + k8s manifests + Woodpecker CI

Closes #1

FastAPI + SQLAlchemy + Stripe webhooks + gmail-sdk + k8s manifests + Woodpecker CI Closes #1
FastAPI app with Stripe webhooks, gmail-sdk email, Postgres via SQLAlchemy/Alembic.
Includes k8s manifests (deployment, service, postgres), Woodpecker CI, and Dockerfile
for deployment to pal-e cluster.

Closes #1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Escape all user-controlled values in HTML roster and email templates
- Remove hardcoded credentials from alembic.ini
- Set stripe.api_key on app startup
- Return 400 (not 422) for missing stripe-signature header
- Add postgres subPath for k3s compatibility
- Document single-replica constraint for migrations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/ copy to Dockerfile builder stage
- Add idempotency check on stripe_checkout_session_id in webhook handler
- Use stripe.SignatureVerificationError (stable import path)
- Migrate from deprecated on_event to lifespan pattern
- Fix seed script session cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add unique constraint on Registration.stripe_checkout_session_id
- Add IntegrityError catch as secondary idempotency defense
- Return 200 for permanent webhook failures (ValueError), 500 only for transient
- Add initial Alembic migration for all tables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

Automated Review Summary (4 rounds)

Round 1 Fixes

  • XSS in HTML roster and email templates (html.escape)
  • Hardcoded credentials removed from alembic.ini
  • stripe-signature header returns 400 (not 422) when missing
  • Stripe API key set on app startup with warnings
  • Postgres subPath for k3s compatibility
  • Documented single-replica migration constraint

Round 2 Fixes

  • Dockerfile builder stage: added src/ copy for hatchling
  • Webhook idempotency: check stripe_checkout_session_id before processing
  • stripe.SignatureVerificationError stable import path
  • Migrated from deprecated on_event to lifespan pattern
  • Seed script session cleanup

Round 3 Fixes

  • Unique constraint on Registration.stripe_checkout_session_id
  • IntegrityError catch as secondary idempotency defense
  • Webhook returns 200 for permanent failures (ValueError), 500 only for transient
  • Initial Alembic migration for all 4 tables

Round 4: PASS (zero blockers)

Remaining nits are standard MVP trade-offs (no auth on roster, no resource limits, Deployment vs StatefulSet) — all documented.

## Automated Review Summary (4 rounds) ### Round 1 Fixes - XSS in HTML roster and email templates (html.escape) - Hardcoded credentials removed from alembic.ini - stripe-signature header returns 400 (not 422) when missing - Stripe API key set on app startup with warnings - Postgres subPath for k3s compatibility - Documented single-replica migration constraint ### Round 2 Fixes - Dockerfile builder stage: added src/ copy for hatchling - Webhook idempotency: check stripe_checkout_session_id before processing - stripe.SignatureVerificationError stable import path - Migrated from deprecated on_event to lifespan pattern - Seed script session cleanup ### Round 3 Fixes - Unique constraint on Registration.stripe_checkout_session_id - IntegrityError catch as secondary idempotency defense - Webhook returns 200 for permanent failures (ValueError), 500 only for transient - Initial Alembic migration for all 4 tables ### Round 4: PASS (zero blockers) Remaining nits are standard MVP trade-offs (no auth on roster, no resource limits, Deployment vs StatefulSet) — all documented.
- .woodpecker.yaml: switch to kaniko plugin, full SHA tags, proper path
  exclude, add pytest test step
- k8s manifests: add namespace to all resources, add resource
  requests/limits, fix Service port to 8000 with name: http
- k8s/postgres.yaml: add subPath for k3s, PGDATA env, strategy: Recreate,
  resource limits
- k8s/servicemonitor.yaml: new file for Prometheus scraping
- /metrics endpoint: stub returning basketball_api_up gauge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ArgoCD destination.namespace controls placement, making manifests
environment-agnostic. This enables branch-based dev/prod promotion.

Refs: forgejo_admin/basketball-api#1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
forgejo_admin closed this pull request 2026-03-07 21:29:43 +00:00

Pull request closed

Sign in to join this conversation.
No description provided.