feat(backend): Clean Architecture, migrations, and label taxonomy#8
Conversation
Replaces bare labels (backend, web, mobile, ci) and GitHub defaults with the area/type/priority/needs taxonomy. Dependency file changes now auto-apply type: chore instead of the removed dependencies label.
Adds github.com/pressly/goose/v3 and a cmd/migrate entry point that reuses the existing postgres.NewPostgresDB connection and reads the same BLUEPRINT_DB_* env vars as the server. Makefile targets added: migrate-up apply all pending migrations migrate-up-one apply the next migration only migrate-down roll back the last migration migrate-down-to roll back to a specific version (version=N) migrate-reset roll back all migrations to 0 migrate-status print applied/pending state migrate-version print current schema version migrate-create create a new SQL migration (name=<slug>) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- backend/docs/migrations.md — full goose workflow: make targets, SQL format rules, new-table checklist, Go migrations exclusion, Testcontainers/migration isolation explanation, hard rules - backend/docs/_index.md — add migrations.md to the topic index - CLAUDE.md — migration commands block, cmd/migrate + migrations/ in project layout, Migrations section in Go conventions, migration step added to the feature development workflow, docs list updated to include migrations topic Agents reading CLAUDE.md will now know to create a migration whenever a feature introduces new tables.
- migrate-create no longer passes 'sql' as a CLI arg; type is hardcoded in Go so the Makefile stays clean and the arg can't be misinterpreted - create command runs before DB connection (filesystem-only op), so make migrate-create works without Docker running - Removed bash-specific 'test' guard; Go logs a clear fatal when name is absent, which works on all platforms - Adds 20260614201325_init.sql (users table) as the starter migration, validated end-to-end with migrate-up / migrate-down
|
Warning Review limit reached
More reviews will be available in 50 minutes and 19 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughIntroduces a goose v3-based database migration system for the backend: a new ChangesBackend goose migration system
CI Labeler Update
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/labeler.yml (1)
28-30:⚠️ Potential issue | 🟡 MinorAdd missing
mobile/settings.gradle.ktsto the labeler patterns.The current patterns miss
mobile/settings.gradle.kts, which defines the module structure and can contain dependency-related configuration changes. Additionally, consider using glob patterns likemobile/**/*.gradle.ktsto simplify maintenance and prepare for potential multi-module expansion.Suggested fix
"type: chore": - changed-files: - any-glob-to-any-file: - "backend/go.mod" - "backend/go.sum" - "web/package.json" - "web/pnpm-lock.yaml" - - "mobile/gradle/libs.versions.toml" - - "mobile/build.gradle.kts" - - "mobile/app/build.gradle.kts" + - "mobile/gradle/libs.versions.toml" + - "mobile/**/*.gradle.kts"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/labeler.yml around lines 28 - 30, The labeler.yml file is missing the mobile/settings.gradle.kts pattern in the gradle-related file labels section. Add "mobile/settings.gradle.kts" to the patterns list alongside the existing entries (mobile/gradle/libs.versions.toml, mobile/build.gradle.kts, and mobile/app/build.gradle.kts). To improve maintainability and prepare for multi-module expansion, consider consolidating these individual patterns into a single glob pattern mobile/**/*.gradle.kts that will automatically catch all gradle files in the mobile directory and subdirectories.
🧹 Nitpick comments (1)
backend/docs/migrations.md (1)
19-29: 💤 Low valueAdd blank line before table per Markdown formatting rules.
The table starting at line 20 should be surrounded by blank lines. Add a blank line between the heading and the table.
✏️ Proposed formatting fix
## Makefile targets + | Target | What it does |🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/docs/migrations.md` around lines 19 - 29, Add a blank line between the heading "## Makefile targets" and the table that begins with "| Target | What it does |". This follows standard Markdown formatting rules which require blank lines to separate headings from content blocks like tables.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/migrations/20260614201325_init.sql`:
- Around line 1-9: The CREATE TABLE IF NOT EXISTS users statement is missing a
name column that downstream code expects when executing queries like SELECT id,
name FROM users. Add a name column to the users table definition in the
migration, choosing an appropriate type such as VARCHAR or TEXT with a NOT NULL
constraint. Verify the column definition matches the expected schema used by
downstream queries in backend/docs/database.md and the repository layer.
---
Outside diff comments:
In @.github/labeler.yml:
- Around line 28-30: The labeler.yml file is missing the
mobile/settings.gradle.kts pattern in the gradle-related file labels section.
Add "mobile/settings.gradle.kts" to the patterns list alongside the existing
entries (mobile/gradle/libs.versions.toml, mobile/build.gradle.kts, and
mobile/app/build.gradle.kts). To improve maintainability and prepare for
multi-module expansion, consider consolidating these individual patterns into a
single glob pattern mobile/**/*.gradle.kts that will automatically catch all
gradle files in the mobile directory and subdirectories.
---
Nitpick comments:
In `@backend/docs/migrations.md`:
- Around line 19-29: Add a blank line between the heading "## Makefile targets"
and the table that begins with "| Target | What it does |". This follows
standard Markdown formatting rules which require blank lines to separate
headings from content blocks like tables.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ecbe142f-f060-4729-bd19-b9c7c4124190
⛔ Files ignored due to path filters (1)
backend/go.sumis excluded by!**/*.sum
📒 Files selected for processing (9)
.github/labeler.ymlCLAUDE.mdbackend/Makefilebackend/cmd/migrate/main.gobackend/docs/_index.mdbackend/docs/migrations.mdbackend/go.modbackend/migrations/.gitkeepbackend/migrations/20260614201325_init.sql
Resolves schema mismatch flagged in PR review — database.md example queries SELECT id, name FROM users but the table had no name column.
Summary
database/servermonolith to Clean Architecture:domain→usecase→repository/postgres+handler→servercmd/migrateentry point and full set ofmake migrate-*targetsarea/type/priority/needstaxonomy and updates the labeler to matchWhat changed
Architecture
internal/domain/—HealthStatstyped struct (wasmap[string]string)internal/usecase/—HealthReaderinterface +HealthUseCasewith connection pool message thresholdsinternal/repository/postgres/— raw DB adapter; business logic moved to use caseinternal/handler/—Handlerstruct wired on use case interfaces;HealthHandlerexportedinternal/server/server.go— composition root only;NewServer()returnserrorinternal/database/andinternal/server/routes.goMigrations
cmd/migrate/main.go— goose wrapper;createruns without DB, all other commands usepostgres.NewPostgresDBmigrations/20260614201325_init.sql— starteruserstable migrationmake migrate-create name=<slug>always produces.sqlfiles; Go migrations intentionally unsupported viago runCI / Labels
.github/labeler.yml— area labels renamed toarea: backend,area: web,area: mobile,area: infra; dependency changes now auto-applytype: chorearea:,type:,priority:,needs:, meta)Docs & agents
backend/docs/migrations.md— full goose workflow, format rules, Testcontainers isolation note, hard rulesbackend/docs/_index.md— migrations added to topic indexCLAUDE.md— migration commands,cmd/migrate+migrations/in layout, Migrations conventions section, migration step in feature workflowTest plan
go vet ./...passesmake testpasses (handler unit tests)make itestpasses against Testcontainers Postgres (requires Docker)make migrate-statusshows pending/applied statemake migrate-create name=test_tablecreates a.sqlfile without Docker runningmake migrate-upapplies the init migration;make migrate-downrolls it backGET /→{"message":"Hello World"}200GET /health→ typed JSON stats 200 (503 when DB is down)Summary by CodeRabbit
New Features
userstable to the database schema.Documentation
Chores