dev into master #1
Reference in New Issue
Block a user
Delete Branch "dev"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Scaffold app/ package, pinned requirements.txt, multi-stage Dockerfile, docker-compose.yml, and .env.example. Add typed pydantic-settings loader with full env contract and a production validator that refuses the dev-sentinel SECRET_KEY. Wire structlog with an APP_ENV-driven renderer (console in dev, JSON in prod). Ship a minimal unauthenticated /healthz returning {status, version, commit_sha} with commit SHA fed through a GIT_COMMIT_SHA build arg. Also mark Phase 0 complete in docs/ROADMAP.md.End-to-end passwordless admin auth. /admin/login accepts an email, POSTs mint a 256-bit magic-link token stored only as SHA-256 in magic_link_tokens (15-min TTL, single-use via atomic rowcount UPDATE). Resend delivers the link; in dev with no API key, EmailService logs a structured magic_link_dev_fallback event with the URL so the flow works offline. /admin/auth/consume/{token} verifies, upserts a users row (display_name from email local-part), creates a sessions row, and drops an itsdangerous-signed cb_session cookie (HttpOnly, SameSite=Lax, Secure in prod). /admin renders a placeholder "Welcome, <name>" page pending Phase 4 CMS. /admin/logout flips revoked_at rather than deleting the row to preserve the audit trail. Rate limits use SlowAPI's in-memory limiter (5/15min/IP on login, 20/15min/IP on consume) plus a DB per-email count to catch IP-rotating abuse. ADMIN_EMAILS enforces allowlist; non-allowlisted submissions return the same "check your inbox" page with no token inserted and no email sent (anti-enumeration). Every event lands in auth_events via AuditService: link_requested, link_consumed, consume_failed, session_created, session_revoked, rate_limited. Add a production config validator refusing empty RESEND_API_KEY, RESEND_FROM, or ADMIN_EMAILS; add PUBLIC_BASE_URL for email link construction. CSRF deferred to Phase 6 per roadmap scoping; logout handler marked # TODO(phase-6-csrf). Mark Phase 3 complete in docs/ROADMAP.md.Phase 1 brand palette reused --c-sky for both the header background and the word "Babies" inside the logo art, erasing it visually. Same class of problem hit the contact page mailto callout. - Split logo into chick mark + HTML site title so the wordmark colors no longer need to coexist with the header surface. Generator gains build_logo_mark_{png,webp} with a widest-gap column scan to crop. - Header moves to --c-wheat; nav active state flips to ink pill with cream text; muted Shop link reads as coming-soon (italic + dim + not-allowed). - Contact page mailto callout reskinned to ink/cream (strong CTA) and form note shifts from pale sky-deep to ink at 70% opacity. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Post cards on the home page have linked to /posts/<slug> since Phase 1 (per the partial's inline comment), but the matching route and template were never registered — clicking a post title returned a JSON 404 from FastAPI. This adds: - PostService.get_published_by_slug() — status-filtered, parameterized read that treats "draft" and "unknown slug" as the same 404 so unpublished titles cannot be enumerated via URL guessing. - GET /posts/{slug} public route that 404s on miss. - public/post.html detail template mirroring about.html's safe-render pattern for the bleach-sanitized body_html_cached. - Supporting .page-article__date / .page-article__back CSS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>