Files
summercms/CLAUDE.md
Jakub Zych d89e18bc8e docs(11.1): record the docs update rule and the wristband default todo
- CLAUDE.md: API, config-key and CLI changes update the affected docs
  pages; the docs checkers are named; config-key checking is deferred
- todo: wristband's default resource URL and comments name a consuming
  application
2026-09-30 21:41:11 +02:00

32 KiB
Raw Permalink Blame History

CLAUDE.md

Guidance for Claude Code when working in this repository.

What this is

SummerCMS in Go: a rewrite of the WinterCMS/OctoberCMS content management framework for the Golem15 stack. Read README.md first, then .planning/notes/ for decisions and .planning/research/ for ecosystem findings.

The reference implementation is WinterCMS. The Golem15 starter lives at ../examples/golem15-wintercms-starter, and the v1 port target (Płytarium) at /media/nvme/dev/golem15/fonoteka.

GSD workflow rules (lean mode)

These rules apply to every GSD phase in this project and override defaults:

  1. Lean planning. Prefer fewer, larger plans per phase. Skip optional agents unless a phase touches security or the plugin API.
  2. Checkpoint on plan count. Before writing plans for a phase, present the suggested number of plans with a one-line scope for each and wait for confirmation. The user adjusts the number; only then write PLAN.md files.
  3. Unit tests are always the last plan of a phase. Every phase ends with a dedicated plan that brings full unit test coverage for that phase's code. Earlier plans in the phase may include smoke tests but must not be blocked on coverage.
  4. Go conventions. Standard library first (net/http ServeMux, html/template, encoding/json). Add a dependency only when the research doc or a phase decision names it. Keep go vet and go test ./... green at every commit.
  5. Compiled plugins. Plugins are Go modules registered at build time. Do not introduce runtime plugin loading (stdlib plugin, yaegi) without a decision note.
  6. API parity is the acceptance test. When porting Płytarium endpoints, the existing Nuxt app's requests define the contract. Do not "improve" response shapes during the port.

Commit rules

  • Never add co-author tags to commit messages.
  • One logical change per commit. Planning docs and code in separate commits.

Documentation

  • Any change to a package under modules/ that touches its exported API, config keys, CLI commands or dependencies must update that module's README.md in the same change (the same commit or PR).
  • A new module ships with a README.md that follows the standard structure: H1 name, one-sentence summary, import line, then Overview, Features, Usage, API reference, the optional Configuration and CLI commands sections, Dependencies and Testing. It also gets a row in the root README.md modules table, whose purpose text reuses the summary sentence.
  • Framework READMEs never name a consuming application. Say "the application" or "host application", and use neutral example names such as blog or acme.
  • Every identifier named in a README or a docs page must exist in the package. The docs checker verifies this automatically; go doc ./modules/<name> <Identifier> remains the manual check.
  • A change to a module's exported API, config keys or CLI commands also updates the affected pages under docs/ in the same change. go test ./cmd/summer -run TestDocsTree and summer docs:build --check check identifiers, internal links and anchors, src= snippets, command names and consuming-application names across docs/ and every module README.
  • Config keys named in README or docs pages are not checked automatically yet (deferred in Phase 11.1); review them by hand.

Project

SummerCMS (Go)

SummerCMS is a Go rewrite of the WinterCMS/OctoberCMS content management framework for the Golem15 stack. It keeps what makes WinterCMS productive for us (plugins that extend each other, YAML-driven admin forms and lists, models/controllers/components, scaffolding commands, a headless API layer) and drops the parts that do not survive a compiled language (runtime plugin autoloading, PHP-style mutable magic). It is built by Golem15 developers and AI agents, for Golem15 projects that today run on the WinterCMS starter.

v1 is a headless backend that runs one real project, Płytarium (fonoteka), with its existing Nuxt 4 app and MCP server unchanged.

Core Value: An existing WinterCMS-shaped app can be ported plugin by plugin to a single Go binary without its frontend noticing: the PHP version's API contract is the acceptance test.

Constraints

  • Tech stack: Go 1.27, standard library first (net/http ServeMux, html/template, encoding/json); a dependency is added only when the research doc or a phase decision names it — keeps the binary boring and the dependency tree auditable
  • Data: GORM on Postgres only — chosen for Eloquent-like DX and a line-by-line model port; River needs Postgres
  • Compatibility: vue-fonoteka-app and fonoteka-mcp must run unchanged; the Nuxt app's requests define the contract and response shapes are not improved during the port
  • Realtime: keep the Centrifugo server and port only the publisher and token issuing — the Nuxt client connects to Centrifugo directly
  • Plugins: compiled at build time; no runtime plugin loading without a decision note
  • Two repositories: summercms.go is the framework only (the summer packages, the CLI, the admin SPA shell, the parity harness tooling) and knows nothing about Płytarium; fonoteka.go, a sibling directory in the meta repo, is the application: a go.work workspace holding the ported plugins (user, websockets, translate, feedback, sitemap, fonoteka) and the app binary, requiring the framework by module path with a local replace during development. Roadmap phases name which repo each plan writes to; planning docs stay in summercms.go/.planning
  • Workflow: lean planning (few, large plans per phase), a plan-count checkpoint before PLAN.md files are written, unit tests as the last plan of every phase, go vet and go test ./... green at every commit
  • Commits: no co-author tags; one logical change per commit; planning docs and code in separate commits
  • Core plugin contracts: the PHP user, blog, pages and payment plugins are shared across many projects; the Go ports must preserve their contracts and the PHP originals are not changed as part of this project

Technology Stack

Core Technologies

Technology Version Purpose Why Recommended
Go 1.27 (Aug 2026) Language/runtime Already decided. Generic methods clean up repository/query-builder APIs; encoding/json is now json/v2-backed (stricter: rejects duplicate keys, invalid UTF-8) — matters for hand-authored fields.yaml/columns.yaml round-tripped through JSON for the admin SPA.
GORM v1.31.2 (Jun 22, 2026) ORM, Postgres only Already decided. Current stable line; v1.31.x added generics-based Count etc. Confirmed via pkg.go.dev version list. HIGH confidence.
gorm.io/driver/postgres v1.6.3 (Sep 14, 2026) Postgres driver for GORM Latest patch release, two days before this research. Its go.mod pins github.com/jackc/pgx/v5 v5.10.0 — GORM's "Postgres driver" is pgx under the hood, not lib/pq. This is the crux of the River pool-sharing question below. HIGH confidence (read go.mod directly).
River v0.47.0 (confirmed via multiple independent 2026 dependabot PRs bumping to this version; GitHub releases page fetch returned stale cached 2024 dates — do not trust that page directly, cross-checked against riverdriver/riverpgxv5/riverdatabasesql sub-package publish dates of Apr–Jul 2026) Postgres-backed job queue Already decided. MEDIUM-HIGH confidence on the exact patch version; HIGH confidence it's the current v0.4x line and actively maintained.
zitadel/oidc v3.51.0 (Sep 14, 2026) OAuth2/OIDC provider Already decided, and confirmed correct: v4 exists only as v4.0.0-next.4 (pre-release, Jul 30, 2026). v3 is the maintained stable line (v3.51.0 shipped two days before this research, newer than the v4 pre-release). Stay on v3; do not chase v4 until it ships stable. Flagged explicitly per the quality gate — this does not contradict the existing decision, it confirms it.
golang-jwt/jwt v5.3.1 (Jan 28, 2026), import path github.com/golang-jwt/jwt/v5 JWT for the SPA and for signing Centrifugo connection/subscription tokens Already decided. One library covers both jobs — see Centrifugo section.
go-playground/validator v10.30.4 (Sep 3, 2026), import path .../validator/v10 Struct-tag validation from YAML rules: Already decided. Current.
cobra v1.10.2 (Dec 3, 2025) CLI framework Already decided. Current stable.
gocloud.dev v0.46.0 (Jun 2, 2026) Blob storage abstraction Already decided. Current.
Vue 3 + TypeScript (frontend, out of Go versioning scope) Minimal admin SPA Already decided. Types generated from OpenAPI — see OpenAPI section.

Supporting Libraries

Library Version Purpose When to Use
go-gormigrate/gormigrate/v2 latest tag as of May 26, 2026 (1.2k stars, actively maintained, PostgreSQL 18 in its own CI matrix) Migrations, up/down, per-plugin Recommended primary migration tool. See "Migration tooling" below for why this beats goose and atlas for this project's shape.
pressly/goose v3.27.3 (Jul 27, 2026, 11.5k stars) Alternative migration tool Use instead of gormigrate only if a future plugin needs pure-SQL migrations independent of *gorm.DB, or a non-GORM connection. Not recommended as primary — see rationale below.
jackc/pgx/v5 v5.10.0 (pinned by gorm.io/driver/postgres's own go.mod) Postgres driver, shared by GORM and River Not a separate app-level choice — it's already there transitively through GORM's driver. River's own driver (riverpgxv5) also needs pgx v5. Pin the same pgx/v5 version across go.sum (Go's module resolution does this automatically via MVS; just don't force a divergent replace directive).
koanf/v2 (github.com/knadh/koanf/v2) v2.3.4 (Mar 21, 2026) Layered config with plugin namespaces Already decided per go-ecosystem.md. See "Config format" below for the HOCON question.
koanf providers: providers/file, providers/env, providers/confmap ships alongside koanf/v2, versioned independently as sub-modules Base file + env-var overlay + programmatic plugin defaults file provider loads base.yaml/<env>.yaml; env provider overlays SUMMER_-prefixed env vars with a transform func mapping SUMMER_DB__HOST → db.host; confmap lets each plugin register its own namespaced defaults (plugins.<name>.*) before the file/env layers are merged on top.
koanf/parsers/yaml tracks koanf/v2 YAML parsing for koanf Wraps goccy/go-yaml as of koanf's current release — not gopkg.in/yaml.v3, which is why the direct fields/columns parsing question below matters independently.
goccy/go-yaml v1.19.2 (Jan 8, 2026) Parse fields.yaml / columns.yaml Use this, not gopkg.in/yaml.v3. See "What NOT to Use" — yaml.v3's upstream repo (go-yaml/yaml) was archived by its maintainer on Apr 1, 2025 and is explicitly marked unmaintained. goccy/go-yaml passes 355/402 cases of the YAML test suite vs 295/402 for yaml.v3, has an AST/tokenizer API useful for round-tripping comments if summer make:* scaffolds YAML files, and is what koanf itself has moved to. HIGH confidence — this is a load-bearing finding, not a style preference.
swaggo/swag v1.16.6 (Jul 29, 2026, stable; v2.0.0-rc6 exists but is not production-ready) Generate OpenAPI from annotated net/http handlers Recommended primary. See "OpenAPI generation" below.
openapi-typescript current npm release (JS ecosystem, not Go-versioned) Generate TS types for the Vue admin SPA from the OpenAPI doc swag produces Already decided (types generated from OpenAPI). Feeds directly off swag's output JSON/YAML.
typesense-go v3.2.0 (Mar 27, 2025), confirms Typesense server API v28 support Typesense client Already decided. This is the most recent tagged release found; no newer tag surfaced in this research pass — treat the exact patch as MEDIUM confidence (worth a re-check at implementation time since it is over a year old relative to today) but the library itself is the only real Go client and is the correct pick.
centrifugal/gocent/v3 current release, import path github.com/centrifugal/gocent/v3 Centrifugo HTTP API client (publish/broadcast/presence) Official client from the Centrifugo org. Small (87 stars is normal for a niche official SDK, not a red flag — same maintainers as Centrifugo itself). Given it wraps ~4 REST calls, hand-rolling a thin net/http client is a legitimate stdlib-first alternative if the team wants zero non-decided dependencies; gocent is the pragmatic default.
— (no separate library for Centrifugo tokens) — Sign Centrifugo connection/subscription JWTs Centrifugo does not need its own token library — it verifies plain JWTs signed with an HMAC secret (or RSA/ECDSA). Use the already-decided golang-jwt/jwt/v5 to sign these tokens too, with claims shaped per Centrifugo's connection/subscription token spec. One JWT library, two token types (SPA auth, Centrifugo realtime auth).
go-i18n/v2 (github.com/nicksnyder/go-i18n/v2) v2.6.1 (Jan 1, 2026) CLDR-plural i18n Already decided. CLDR v48 as of this release (up from CLDR 44 in older v2.3.0 — make sure any tutorial/blog post referencing go-i18n is checked against the current release, plural-rule edge cases have shifted). Also replaced an unmaintained YAML dependency internally in a recent release — another confirmation that the Go YAML-library churn described above is a live, current issue, not stale training-data noise.
testcontainers-go + testcontainers-go/modules/postgres v0.44.0 (Aug 7, 2026) Spin up real Postgres in tests For GORM model tests, migration up/down tests, and River job tests that need real Postgres behavior (JSON columns, LISTEN/NOTIFY, constraint behavior) rather than SQLite-in-CI approximations.
stretchr/testify v1.12.1 (Aug 17, 2026) Assertions in Go tests Standard choice; use assert/require for readability in the API-parity diff tests, not as a BDD framework — keep tests as plain func Test...(*testing.T).
air-verse/air v1.67.4 (Aug 1, 2026), actively maintained Dev watch-rebuild loop This is the "watch loop that rebuilds the compiled-plugin binary on change" the plugin architecture already calls for. Config via .air.toml; point cmd/bin at go build -o ./tmp/summer ./cmd/summer && ./tmp/summer serve.
golangci-lint v2.13.2 (Aug 27, 2026) Linting v2's config schema (version: "2" in .golangci.yml) is a breaking change from v1 — do not copy a v1 config from an older Go project without migrating it.

Development Tools

Tool Purpose Notes
air live rebuild in dev Config as above; combine with the plugin system's own plugins.go regeneration step so editing a plugin's route/model file triggers both codegen and rebuild.
golangci-lint v2 static analysis in CI and pre-commit Enable govet, staticcheck, errcheck, revive at minimum; the stdlib-first constraint makes depguard worth configuring to fail CI if an undecided dependency is imported.
testcontainers-go integration tests against real Postgres Gate these behind a build tag or -short skip so unit tests stay fast; the phase-ending "unit tests" plan (per this repo's lean-mode rule) should still run everywhere, with testcontainers tests as a separate, slower suite.
golden-file API parity tests diff Go backend responses against recorded PHP responses Not a library — a pattern: record Płytarium's actual JSON responses per route as fixtures (testdata/parity/<route>.golden.json), replay the same requests against the Go backend in httptest.Server, diff with testify/assert.JSONEq or a small custom normalizer for non-deterministic fields (timestamps, IDs). This is the literal implementation of the PROJECT.md requirement "an API parity test suite replays the Nuxt app's and MCP server's requests against both backends and diffs responses."

Installation

Core (already decided, versions confirmed this session)

Migrations

Config

YAML for fields.yaml / columns.yaml (NOT gopkg.in/yaml.v3)

i18n

OpenAPI

Search / realtime clients

Dev / test dependencies

Dev tools (not go.mod dependencies)

golangci-lint installed via its install script, pinned to v2.13.2, not go install

Deep Dives on the Milestone's Specific Questions

GORM: plain structs, not gorm gen or the new GORM CLI

Migration tooling: gormigrate, not goose or atlas

  • gormigrate (go-gorm/gormigrate/v2) defines migrations as {ID, Migrate(tx *gorm.DB) error, Rollback(tx *gorm.DB) error} structs, operates directly on the shared *gorm.DB, and — confirmed by reading the source (gormigrate.go) directly rather than trusting a README excerpt — exposes RollbackLast() and RollbackTo(id) as first-class methods, plus MigrateTo(id). This is a literal implementation of "drop the last migration and fix it": run RollbackLast(), edit the migration's Migrate/Rollback funcs, run Migrate() again. No separate migration-file format, no separate driver, no SQL string embedding required (though tx.Exec(...) is available inside a migration when raw SQL is easier than Migrator() calls).
  • goose supports Go-code migrations (not just .sql files) via goose.NewGoMigration, which is the reason it was flagged as a candidate. But it registers migrations into its own provider backed by an embed.FS per source tree; making per-plugin migration sets compose cleanly (each plugin contributing its own ordered slice, aggregated by the kernel at boot from the generated plugin import list) is more natural with gormigrate's plain []*gormigrate.Migration slices than with goose's filesystem-and-provider model. goose is still the right tool if a future plugin needs raw-SQL migrations decoupled from *gorm.DB entirely (e.g. a plugin that talks to Postgres via bare pgx for performance reasons) — keep it as the named fallback, not the default.
  • atlas is a declarative schema-diff tool (desired-state HCL/SQL compared against actual state, migration generated automatically). It is the better fit when GORM's own struct tags are treated as the single source of truth and hand-written data-backfill migrations are rare. This project's port needs custom, hand-authored up/down logic per PHP migration (27 of them, with real data semantics, not just DDL) — atlas's diffing model fights that instead of helping it, and it adds a second DSL and a separate binary. Not recommended for v1.

River + GORM: share one *sql.DB, not one pgxpool.Pool

zitadel/oidc v3 storage interface: what to implement

  • AuthStorage — the core of the authorization-code + PKCE flow: CreateAuthRequest, AuthRequestByID, AuthRequestByCode, SaveAuthCode, DeleteAuthRequest, CreateAccessToken, CreateAccessAndRefreshTokens, TokenRequestByRefreshToken, TerminateSession, RevokeToken, GetRefreshTokenInfo, SigningKey, SignatureAlgorithms, KeySet. This is the interface Płytarium's OAuthAuthCode, OAuthClient, OAuthRefreshToken models map onto directly.
  • OPStorage — GetClientByClientID, AuthorizeClientIDSecret, SetUserinfoFromToken, SetIntrospectionFromToken, GetPrivateClaimsFromScopes, GetKeyByIDAndClientID, ValidateJWTProfileScopes. SetUserinfoFromScopes exists but is explicitly documented as deprecated in favor of the optional CanSetUserinfoFromRequest interface — implement the newer one, leave the old one empty.
  • ClientCredentialsStorage (optional) — needed only if the client-credentials grant is used (worth checking whether the MCP server or ChatGPT connector needs it; Płytarium's OAuth models list doesn't obviously call for it, flag as an open question for the phase that implements this).
  • TokenExchangeStorage / TokenExchangeTokensVerifierStorage (optional) — RFC 8693 token exchange; almost certainly out of scope for a straight port unless the existing PHP OAuth server implements it (check wavepath.org/plugins/golem15/oauthserver for this before assuming it's unneeded).
  • Optional Can* interfaces (CanTerminateSessionFromRequest, CanSetUserinfoFromRequest, and others in the same file) let the request object itself (not just IDs) reach the storage implementation — worth implementing from the start rather than the older, more limited required methods, since they carry richer context.

Config: koanf + YAML, not a literal HOCON parser

go-i18n + CLDR plurals

YAML parsing: goccy/go-yaml, confirmed necessary not just preferred

OpenAPI generation: swaggo/swag (code-first, comment-driven), not Huma, not hand-written

Testing stack

  • testcontainers-go (v0.44.0, Aug 7, 2026) + its modules/postgres for real-Postgres integration tests: GORM migrations up/down, River job processing (needs real LISTEN/NOTIFY), JSON column round-tripping. Gate behind a build tag/-short so the fast unit-test loop stays fast.
  • testify (v1.12.1, Aug 17, 2026) for assertions only (assert/require) — keep tests as plain stdlib func TestX(t *testing.T), no BDD DSL, consistent with stdlib-first.
  • Golden-file API parity tests: no library needed. Record real Płytarium PHP responses as JSON fixtures per route, replay identical requests against the Go backend via httptest.NewServer, diff with a normalizer that ignores non-deterministic fields (timestamps, generated IDs) before comparing. This directly implements the PROJECT.md acceptance test.

Dev loop and linting

  • air (v1.67.4, Aug 1, 2026) for the watch-rebuild loop the compiled-plugin architecture needs to "feel like WinterCMS's drop-in loop" (go-ecosystem.md's own phrase). Point its build command at the full go build of the summer binary plus the plugin-import-list regeneration step, not just a bare go build ./....
  • golangci-lint v2.13.2 (Aug 27, 2026). v2's .golangci.yml schema (version: "2") is a breaking change from v1 configs — do not reuse a v1 config verbatim. Configure depguard to enforce the stdlib-first / decided-dependency-only constraint at CI time, not just by convention.

Alternatives Considered

Recommended Alternative When to Use Alternative
gormigrate goose A future plugin needs raw-SQL migrations independent of *gorm.DB/GORM entirely.
gormigrate atlas Schema is treated as pure declarative state (GORM struct tags as source of truth) with rare hand-authored data migrations — not this project's shape for v1.
plain GORM structs go-gorm/cli or gorm.io/gen A later, non-ported plugin wants compile-time-checked queries and is willing to add a codegen step.
swaggo/swag huma + humago A later, non-parity API surface where request/response shape isn't constrained by an existing contract, and the team accepts Huma's handler-shape convention project-wide.
swaggo/swag hand-written OpenAPI + oapi-codegen A small, from-scratch API (not a 154-route port) where authoring the spec first is cheaper than annotating existing handlers.
YAML (via koanf) literal HOCON via a Go parser Never, for this project — no maintained Go HOCON library exists at the bar this project applies elsewhere.
gocent/v3 hand-rolled Centrifugo HTTP client Team wants zero additional non-decided dependencies; Centrifugo's HTTP API is small enough (~4 calls) that this is a legitimate, if slightly more work, stdlib-first option.

What NOT to Use

Avoid Why Use Instead
gopkg.in/yaml.v3 (go-yaml/yaml) Archived by its maintainer Apr 1, 2025; README explicitly says "THIS PROJECT IS UNMAINTAINED." No further fixes, security patches, or Go-compatibility work will land. goccy/go-yaml v1.19.2
gorm.io/gen or go-gorm/cli for v1 model code Adds a codegen layer that works against the explicit goal of a simple, reviewable, line-by-line Eloquent-to-GORM port of 25 models. Plain GORM structs and methods
atlas for v1 migrations Declarative schema-diff model fights hand-authored, data-aware up/down migrations for 27 real PHP migrations with actual data semantics, and adds a second DSL/binary. gormigrate
Sharing a raw pgxpool.Pool directly between GORM's postgres driver and River's riverpgxv5 driver as two independent pools Two separate pools against the same database is wasteful and defeats the point of "share one pool"; naively wiring them both to the same pool object isn't how either library's constructor is designed to be used. One shared *sql.DB (via pgx/v5/stdlib) for both GORM and River's queries, plus one small separate pgxpool.Pool used only for River's LISTEN/NOTIFY wake-ups
zitadel/oidc v4 Only exists as v4.0.0-next.4, a pre-release from Jul 30, 2026 — not production-ready, and older than the current v3.51.0 stable release. zitadel/oidc v3 (/v3), already decided
Huma for the v1 parity port specifically Requires restructuring every ported handler into Huma's typed Input/Output convention rather than ordinary net/http handlers, right when byte-compatible parity with an existing contract is the entire point. swaggo/swag, annotating existing handlers
swaggo/swag v2 (v2.0.0-rc6) Still a release candidate as of Sep 13, 2026; OpenAPI 3.1 support and dependency cleanup are still in flux. swaggo/swag v1.16.6
A literal HOCON parser in Go (gurkankaymak/hocon, go-hocon/hocon) Both are tiny, single-or-zero-star projects with unclear or no active maintenance — far below this project's ecosystem-depth bar for every other pick. koanf + YAML, achieving the same layering design without literal HOCON syntax
golangci-lint v1-style config on a v2 install v2 changed the .golangci.yml schema; a copied v1 config will not behave as expected. A version: "2" config written against v2's current schema

Stack Patterns by Variant

  • Use goose's Go-code migrations for that plugin specifically
  • Because gormigrate assumes *gorm.DB-shaped Migrate/Rollback funcs; a plugin that deliberately bypasses GORM for a hot path has no natural *gorm.DB to hand it
  • Consider Huma instead of hand-annotated swag comments, and go-gorm/cli instead of plain structs
  • Because the byte-compatible-parity constraint that rules both out for v1 doesn't apply to code with no existing contract to match

Version Compatibility

Package A Compatible With Notes
gorm.io/gorm v1.31.2 gorm.io/driver/postgres v1.6.3 Driver's own go.mod targets this gorm version; keep them bumped together.
gorm.io/driver/postgres v1.6.3 jackc/pgx/v5 v5.10.0 Pinned directly in the driver's go.mod — this is the pgx version that ends up in go.sum for the whole binary via GORM.
River v0.47.0 jackc/pgx/v5 (River's own riverpgxv5 driver requires v5; riverdatabasesql driver works with any database/sql-registered driver, including pgx's stdlib registration) Go's module resolution (MVS) will pick one pgx/v5 version for the whole build; do not force a divergent replace for either GORM's or River's sake — let them converge.
zitadel/oidc v3.51.0 go-jose/go-jose/v4 (imported directly in pkg/op/storage.go) v3's storage interfaces use jose.SignatureAlgorithm and *jose.JSONWebKey types from go-jose v4 in method signatures — a storage implementation's key-handling code will import this directly.
koanf/v2 v2.3.4 koanf/parsers/yaml (wraps goccy/go-yaml) Confirms goccy/go-yaml is already in the dependency tree via koanf; using it directly for fields.yaml/columns.yaml doesn't add a new library, just a direct dependency on one already present transitively.
go-i18n/v2 v2.6.1 golang.org/x/text v0.32.0+ go-i18n's own recent release notes cite bumping to this x/text version alongside the CLDR v48 update.
golangci-lint v2.13.2 .golangci.yml schema version: "2" Not backward compatible with v1-style config files without migration.

Sources

  • pkg.go.dev version pages for gorm.io/gorm, gorm.io/driver/postgres, github.com/golang-jwt/jwt/v5, github.com/go-playground/validator/v10, github.com/spf13/cobra, gocloud.dev, github.com/goccy/go-yaml, github.com/stretchr/testify, github.com/testcontainers/testcontainers-go — versions and dates, fetched 2026-09-16. HIGH confidence.
  • raw.githubusercontent.com/go-gorm/postgres/master/go.mod — read directly for the pgx/v5 pin. HIGH confidence.
  • riverqueue.com/docs/gorm — official River+GORM integration guide, the source for the shared-*sql.DB pattern. HIGH confidence.
  • raw.githubusercontent.com/zitadel/oidc/main/pkg/op/storage.go — read directly for interface definitions. HIGH confidence.
  • github.com/zitadel/oidc releases page — v3.51.0 vs v4.0.0-next.4 dates. HIGH confidence.
  • raw.githubusercontent.com/go-gormigrate/gormigrate/master/gormigrate.go and README.md — read directly for RollbackLast/RollbackTo/MigrateTo API and usage pattern. HIGH confidence.
  • github.com/go-yaml/yaml repo page — archived status and "UNMAINTAINED" README notice, read directly. HIGH confidence.
  • WebSearch results on koanf's yaml parser migrating to goccy/go-yaml — MEDIUM confidence (WebSearch-sourced, not independently re-verified against koanf's own go.mod, but corroborated by two independent search results and by go-i18n's own release notes mentioning a similar unmaintained-YAML-dependency swap).
  • github.com/swaggo/swag releases page, huma.rocks docs (bring-your-own-router, humago adapter), oapi-codegen GitHub — OpenAPI approach comparison. HIGH confidence on version/maintenance facts, MEDIUM-HIGH (judgment call) on the recommendation itself.
  • github.com/gurkankaymak/hocon, github.com/go-hocon/hocon — star counts and activity, read directly. HIGH confidence these are not viable options.
  • github.com/typesense/typesense-go releases — v3.2.0, Mar 27 2025. MEDIUM confidence this is still the latest tag; worth a fresh check at implementation time given the gap since this research date.
  • github.com/centrifugal/gocent repo page — v3 module path, star count. MEDIUM confidence (couldn't confirm an exact latest tag/date from the page content retrieved).
  • github.com/air-verse/air releases — v1.67.4, Aug 1 2026. HIGH confidence.
  • golangci-lint changelog/release references — v2.13.2, Aug 27 2026, v2 config schema change. HIGH confidence.

Conventions

Conventions not yet established. Will populate as patterns emerge during development.

Architecture

Architecture not yet mapped. Follow existing patterns found in the codebase.

Project Skills

No project skills found. Add skills to any of: .claude/skills/, .agents/skills/, .cursor/skills/, .github/skills/, or .codex/skills/ with a SKILL.md index file.

GSD Workflow Enforcement

Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.

Use these entry points:

  • /gsd-quick for small fixes, doc updates, and ad-hoc tasks
  • /gsd-debug for investigation and bug fixing
  • /gsd-execute-phase for planned phase work

Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.

Developer Profile

Profile not yet configured. Run /gsd-profile-user to generate your developer profile. This section is managed by generate-claude-profile -- do not edit manually.