Files
summercms/.planning/phases/03-first-vertical-slice-genres-end-to-end/03-PATTERNS.md
2026-09-17 18:40:13 +02:00

3.9 KiB

Phase 3 — Codebase Pattern Map

Mapped: 2026-09-17
Scope: framework mechanisms and the first Fonoteka app route

New or modified area Closest existing analog Pattern to preserve
lagoon connection and service publishing backpack/app.go, backpack/services.go backpack.App owns per-instance config/services; publish *sql.DB and *gorm.DB there, avoid request globals
pact.HasMigrations, HasRoutes, HasMiddleware, HasModels pact/capabilities.go Small optional interfaces type asserted by the kernel; no framework import of app plugin packages
Plugin migration/route assembly party/registry.go Activate topologically orders Requires(), runs all Register before any Boot; use that order for migrations and fail on missing dependencies/names
Named route builder and HTTP server bonfire/command.go, cmd/summer/main.go, examples/hello/main.go Generic command values on bonfire; app generated entry point composes plugin capabilities; handlers remain standard http.Handler
Request context towel/context.go Unexported key type plus exported getter/setter functions, no package-level current user
Configuration compass/config.go, compass/env.go, examples/hello/plugins/base/config/config.yaml Plugin namespace config merges before env override; missing auth secret fails boot
App workspace/plugins examples/hello/go.mod, examples/hello/summer.yaml, examples/hello/plugins.gen.go; ../fonoteka.go/go.mod Separate modules and generated blank imports; app requires framework by module path with local replace
App parity seam ../fonoteka.go/parity/parity_test.go, ../fonoteka.go/parity/synthetic_test.go newTarget returns a handler, seedHooks maps names to trusted Go functions, corpus status marks pending/ported; tide stays generic
Genre contract PHP GenreApiController.php, ActiveCollectionResolver.php, PolishOrder.php, SerializesFonoteka.php Port exact query and DTO; use local PHP source as behavioral oracle and fixture as recorded acceptance test

Reusable Signatures and Boundaries

party.Plugin requires ID() string, Requires() []string, Register(*backpack.App) error, and Boot(*backpack.App) error. party.Activate returns plugins in dependency order after full register/boot completion. Optional capability methods should be declared in pact and discovered by type assertion at assembly time, following HasConfig and HasCommands. Avoid adding app-specific identifiers or imports to party, pact, surf, lagoon, or bouncer.

backpack.App has Config, Services, and Events. Its generic Publish and Lookup wrappers already supply per-app services. towel uses context accessor functions; follow that for authenticated identity, locale, and organization slots.

The bonfire.Command value carries Name, Description, Flags, Args, and Run(context.Context, bonfire.Input, bonfire.Output) error. New serve, migrate, migrate:rollback, and migrate:status commands should reuse this command kernel. The existing app parity test already starts Postgres and calls newTarget(t, db); use that exact seam for the real app.

Cross-Repo Ownership

  • summercms.go: lagoon, surf, bouncer, capability interfaces, generic CLI and tests, hello typed-route example. No Płytarium models or route names.
  • ../fonoteka.go: user and Fonoteka plugins, migrations, domain query, HTTP handler, generated app binary, parity seed hook/manifest and app tests.
  • /media/nvme/dev/golem15/fonoteka: read-only PHP reference. The source contract is not edited in Phase 3.

Security Review Targets

The JWT guard and middleware resolver are load bearing. Plans must provide a threat model for token verification and route authorization, plus an execution-time security review before declaring the slice ready. The final test plan exercises each high severity threat's mitigation.