Tasks completed: 2/2 - Initialize the real app database through plugin migrations - Serve the seeded genre list behind real cross-plugin JWT middleware SUMMARY: .planning/phases/03-first-vertical-slice-genres-end-to-end/03-01-SUMMARY.md Co-authored-by: Cursor <cursoragent@cursor.com>
8.8 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 03-first-vertical-slice-genres-end-to-end | 01 | api |
|
|
|
|
|
|
|
|
|
17 min | 2026-09-17 |
Phase 03 Plan 01: Boot the Postgres-backed JWT genre route Summary
Shared pgx-stdlib pool, per-plugin gormigrate, HS256 jwt.auth, and GET /_fonoteka/api/v1/genres serving the 15 seeded rows
Performance
- Duration: 17 min
- Started: 2026-09-17T17:47:49Z
- Completed: 2026-09-17T18:04:34Z
- Tasks: 2
- Files modified: 52
Accomplishments
- Fresh ICU
pl-PLPostgres migratesgolem15.userthengolem15.fonotekawith separate history tables and the 15 canonical genre slugs; libc/non-Polish databases fail before migrate; noAutoMigrate. surfcompiles Laravel-like groups ontohttp.ServeMuxwith recover → CORS → locale → named auth → must-change-password → org slot → no-op rate limit → handler.bouncerverifies pinned HS256 tokens (exp+subrequired) andgolem15.userregistersjwt.auth;golem15.fonotekaregistersinv.must-change-password(423) and mountsGET /_fonoteka/api/v1/genres.- A valid test-only token returns 200 with a nonempty
dataarray from Postgres; missing/malformed/expired/wrong-alg/bad-sig/missing-sub/unknown-user tokens never reach the handler.
Task Commits
Each task was committed atomically (framework summercms.go then app fonoteka.go):
- Task 1: Initialize the real app database through plugin migrations
d0d845052bb5de883646c699eeeb0d18aad23708(feat, summercms.go)55f110e7d7968977c3abaa3d73905dc7408de30a(feat, fonoteka.go)
- Task 2: Serve the seeded genre list behind real cross-plugin JWT middleware
4ee4c4a2fc27d644cdfac9131cb369e8617df861(feat, summercms.go)d7915a80e655329bb726c64dc2488c9a1de9a48c(feat, fonoteka.go)
Plan metadata: (this commit)
Files Created/Modified
lagoon/connection.go— shared pgx stdlib pool, ICU locale check, GORM onpostgres.Config{Conn: sqlDB}lagoon/migrations.go— per-plugin gormigrate sets and history tablessurf/router.go/surf/serve.go— Group/Get/Assemble and signal-awareservebouncer/jwt.go/bouncer/context.go— HS256 verifier and unexported user context keypact/capabilities.go— HasMigrations, HasMiddleware, HasRoutes, HasModels../fonoteka.go/app/app.go— in-process Handler seam used by genre smoke tests../fonoteka.go/plugins/golem15/user/— users migration, jwt.auth, UserProvider../fonoteka.go/plugins/golem15/fonoteka/— schema/seed, 423 gate, genre DTO handler../fonoteka.go/parity/genre_smoke_test.go— valid token plus reject/423 cases; corpus stays pending
Decisions Made
- One
*sql.DBfor GORM and application queries; do not create a River listener pool until Phase 11. - Generated
main.gocannot importfonoteka/app;surf.ServeCommandandapp.Handlerboth callsurf.Assemble. - Empty JWT secret fails Boot (
SUMMER_GOLEM15__USER__JWT__SECRET); issuing stays out of production APIs.
Deviations from Plan
Auto-fixed Issues
1. [Rule 3 - Blocking] Generated main cannot share the fonoteka/app import path
- Found during: Task 2 (serve / parity seam)
- Issue: Plan text says generated main and parity tests call the same importable app package, but
summer buildis framework-generic and must not import Fonoteka. - Fix: Keep generated main on
lagoon.RuntimeCommands+surf.ServeCommand; putapp.Handler(cfg, pluginIDs, sqlDB)infonoteka.go/appfor tests. - Files modified:
internal/build/build.go,../fonoteka.go/app/app.go,../fonoteka.go/main.go - Verification:
summer buildregenerates ServeCommand; genre smoke bootsapp.Handler - Committed in:
4ee4c4a/d7915a8(Task 2)
2. [Rule 1 - Bug] go mod tidy drops toolchain go1.27.0
- Found during: Task 1 and Task 2
- Issue: tidy removes the pinned toolchain line required by project convention.
- Fix: Restore
toolchain go1.27.0after tidy in framework and plugin modules. - Files modified:
go.mod, plugingo.modfiles - Verification: modules still build under Go 1.27
- Committed in: Task 1 and Task 2 commits
3. [Discretion] JWT malformed/bad-signature copy from library source
- Found during: Task 2
- Issue: Plan asked to capture malformed/bad-signature PHP bodies on the isolated Phase 2 server before finalizing translations.
- Fix: Used the php-open-source-saver/jwt-auth (Namshi) messages already named in CONTEXT D-10:
Wrong number of segmentsandToken Signature could not be verified. - Files modified:
bouncer/jwt.go - Verification: genre smoke table-driven 401 bodies
- Committed in:
4ee4c4a(Task 2)
Total deviations: 3 auto-fixed (1 blocking, 1 bug, 1 copy-source discretion) Impact on plan: No scope creep. QA-04 parity-green remains Plan 03; this plan keeps the corpus pending.
Issues Encountered
None that blocked the slice. go mod tidy dropping toolchain is now a known restore step.
User Setup Required
None - no external service configuration required beyond the existing Postgres ICU pl-PL database and SUMMER_DATABASE__DSN / SUMMER_GOLEM15__USER__JWT__SECRET env vars documented in ../fonoteka.go/README.md.
Next Phase Readiness
Ready for 03-02-PLAN.md (active-collection album counts, non_empty validation, Polish ordering). Do not mark the genres corpus route ported until Plan 03. QA-04 stays pending until that parity diff is green.
Self-Check: PASSED
- Key files exist on disk (
lagoon/connection.go,surf/router.go,bouncer/jwt.go,../fonoteka.go/app/app.go,../fonoteka.go/parity/genre_smoke_test.go) git log --grep=03-01returns Task 1 and Task 2 commits- Acceptance: 15 seeded genres, ICU locale fail, shared
*sql.DB, JWT 200/401/423, missing middleware names plugin+name, framework does not import Fonoteka,serveon both binaries,go vet/go test ./...green in both repos
Phase: 03-first-vertical-slice-genres-end-to-end Completed: 2026-09-17