diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md index cbb4044..4fc8889 100644 --- a/.planning/PROJECT.md +++ b/.planning/PROJECT.md @@ -20,7 +20,7 @@ An existing WinterCMS-shaped app can be ported plugin by plugin to a single Go b Framework kernel -- [ ] A single `summer` binary boots an application from HOCON-style layered config (base + env overlays + plugin namespaces), the design carried over from summer-compass +- [ ] A single `summer` binary boots an application from layered YAML config via koanf (base + env overlays + per-plugin namespaces + environment variables), the layering design carried over from summer-compass (HOCON syntax itself is not used: no maintained Go parser exists) - [ ] Plugins are Go modules registered at build time through a generated import list; `summer make:plugin` scaffolds one and `summer build` rebuilds the binary; a dev watch loop rebuilds on change - [ ] Plugins declare models, migrations, routes, console commands, jobs, event listeners, admin controllers and navigation through one plugin descriptor, and can extend other plugins' models through ordinary Go interfaces and events - [ ] A typed in-process event bus lets plugins subscribe to each other's events @@ -30,7 +30,7 @@ Framework kernel Data layer -- [ ] GORM models with Eloquent-like flows on Postgres; per-plugin migrations runnable up and down, with a "drop the last migration and fix it" workflow +- [ ] GORM models with Eloquent-like flows on Postgres; per-plugin gormigrate migration sets runnable up and down, with a "roll back this plugin's last migration and fix it" workflow - [ ] All 25 Płytarium models ported (Album, Artist, Collection, Genre, Style, AlbumRating, AlbumReservation, ApiToken, CollectionEditor, CollectionInvitation, CsvImport, CsvImportRow, Notification, OAuthAuthCode, OAuthClient, OAuthRefreshToken, OrgAiCredential, OrgDiscogsCredential, PendingInvitationRegistration, Settings, UserAiCredential, UserCollectionContext, UserDiscogsCredential, WishlistDigestQueue, WishlistSubscription) and its 27 migrations - [ ] Pagination, soft deletes, timestamps, relations (has-many, belongs-to, many-to-many) and JSON columns behave like the PHP originals for the API responses @@ -53,7 +53,7 @@ Background and integrations Admin - [ ] Backend admin users with roles, separate from frontend users, as in WinterCMS -- [ ] `fields.yaml` and `columns.yaml` parsed into a JSON form and list schema served per controller, with the WinterCMS field types Płytarium uses (text, textarea, number, switch, dropdown, relation, repeater, fileupload, datepicker) +- [ ] `fields.yaml` and `columns.yaml` parsed (goccy/go-yaml) into a JSON form and list schema served per controller, with the field types Płytarium actually uses (text, textarea, checkbox, switch, dropdown with model-method options, relation with nameFrom/emptyOption) plus layout hints (span, tabs, context, attributes), and a first-class relation-manager schema replacing the one `partial` field - [ ] A minimal Vue 3 + TypeScript admin SPA that renders those schemas as lists and forms for the five Płytarium controllers (Albums, Artists, Collections, Genres, Styles), with types generated from the API's OpenAPI document Quality @@ -73,12 +73,14 @@ Quality - Porting Illuminate module by module — the target app pulls what is needed; unneeded WinterCMS subsystems stay unported - "Improving" API response shapes during the port — parity is the acceptance test; improvements come after cutover - Porting the JVM/Scala modules as code — their designs carry over, their code does not +- Sluggable, Sortable, NestedTree, Revisionable model behaviors — Płytarium uses none of them (slugs are hand-rolled in lifecycle hooks); build only when a later port needs them +- A generic response envelope or blanket error middleware — the PHP API deliberately has three envelope families (house REST, Laravel-shaped 422 errors, unwrapped RFC 8414/6749 OAuth); unifying them breaks parity ## Context **History.** SummerCMS started in February 2026 as a Scala 3 rewrite (Tapir, Ox, Magnum, Jig). Three infrastructure modules shipped as sbt projects in the meta repo (`../modules/summer-compass`, `summer-phrasebook`, `summer-bonfire`) before the effort stalled: it was building Illuminate-shaped infrastructure bottom-up with no real app pulling requirements, and the deciding test (an OAuth2/OIDC server) found no reusable Scala library. Go passed the same test with zitadel/oidc. The decision is recorded in `.planning/notes/why-go-not-scala.md` and is not to be relitigated. -**Prior research.** `.planning/research/go-ecosystem.md` is a verified (2026-09-16, GitHub API) ecosystem report with picks per concern and a plugin-architecture comparison. It is the starting point for stack decisions; phase research should extend it, not redo it. +**Prior research.** `.planning/research/go-ecosystem.md` is a verified (2026-09-16, GitHub API) ecosystem report with picks per concern and a plugin-architecture comparison. Project research on 2026-09-16 added `STACK.md`, `FEATURES.md`, `ARCHITECTURE.md`, `PITFALLS.md` and `SUMMARY.md`, all grounded in direct reads of the Płytarium PHP source. Phase research should extend them, not redo them. **Reference implementations.** @@ -120,6 +122,11 @@ Quality | Reuse IDEA_LIB_NAMES module names as Go packages | Continuity with the Scala work and its docs | — Pending | | WASM extension API deferred | Plugin surface too wide to marshal until the compiled API settles | — Pending (seed) | | Themes and payments deferred to keios.eu port | Smallest Golem15 project with both a Twig theme and a payment flow | — Pending (seed) | +| gormigrate over goose for migrations | Plain `[]*gormigrate.Migration` slices compose per plugin at boot and give `RollbackLast()`/`RollbackTo()` on a `*gorm.DB`; goose's provider/FS model fits worse (research STACK.md, 2026-09-16) | — Pending | +| koanf + YAML config, goccy/go-yaml everywhere | No maintained Go HOCON parser; `gopkg.in/yaml.v3` upstream archived April 2025; one YAML library for config and admin schemas | — Pending | +| swaggo/swag for OpenAPI, not Huma | Comment annotations on plain net/http handlers keep 154 ported routes byte-compatible; Huma would reshape every handler | — Pending | +| GORM + River share one `*sql.DB` (pgx stdlib) with a separate pgx pool for LISTEN/NOTIFY | River's documented GORM integration; transactional enqueue inside GORM transactions | — Pending | +| Parity harness is a day-one workstream | Fixture recording needs only the running PHP backend; it is the acceptance mechanism for every port phase | — Pending | ## Evolution @@ -139,4 +146,4 @@ This document evolves at phase transitions and milestone boundaries. 4. Update Context with current state --- -*Last updated: 2026-09-16 after initialization* +*Last updated: 2026-09-16 after project research*