Shared core plugins live in their own sm-<name>-plugin repos mounted as submodules; golem15.user is git.golem15.com/golem15/sm-user-plugin (supersedes the Phase 1 keios.eu extraction trigger)
Quick 261002-esz: Extract golem15.user into sm-user-plugin Summary
golem15.user now lives in its own repo git@git.golem15.com:golem15/sm-user-plugin.git. Its 21-commit history was split out with git subtree, the module is renamed to git.golem15.com/golem15/sm-user-plugin, and fonoteka.go mounts it back as a submodule at the unchanged path plugins/golem15/user. There is no behaviour change and the full Docker suite is green.
The secret scan of git log -p on the split branch (T-261002-01) found no private key blocks, DSNs with credentials or real secrets. The only hits were test fixtures: sessionSecret = "summercms-test-only-hs256-secret", the correct-horse test passwords and secret: "" in config.
Commits
sm-user-plugin (submodule fonoteka.go/plugins/golem15/user, pushed to origin master by fast-forward only, never forced):
SHA
Subject
2004678
(split tip) chore(11-01): pick up the framework job queue tables and River dependency
02ba1f0
refactor: rename module to git.golem15.com/golem15/sm-user-plugin
1f2ea57
build: tidy go.mod for standalone module mode
44f3c4c
docs: describe the user plugin
Remote refs/heads/master = 44f3c4c9863e867cce4bd5b055bf1de49e2d7e07 = submodule HEAD = gitlink recorded in fonoteka.go 18576db.
fonoteka.go (no remote, not pushed):
SHA
Subject
176df56
refactor(user): mount golem15.user from the sm-user-plugin submodule
18576db
refactor(user): import golem15.user from git.golem15.com/golem15/sm-user-plugin
summercms.go (not pushed):
SHA
Subject
947aabe
docs: move golem15.user to sm-user-plugin and supersede the Phase 1 extraction deferral (7 files, all under .planning/)
None of these commits has a co-author or attribution trailer.
go.sum, added lines only: robfig/cron/v3 v3.0.1 (h1 + go.mod), tidwall/gjson v1.14.2/go.mod, tidwall/match v1.1.1/go.mod, tidwall/pretty v1.2.0/go.mod. No direct requirement changed or moved.
Verification
Task 1 gates: submodule status clean, .gitmodules url is SSH, go.work unchanged, remote master = gitlink, submodule tree = pre-extraction tree, workspace vet and go test -short green, tree clean.
Task 2 gates: gofmt clean; no text file under fonoteka.go (outside .git) contains the old app-nested path; workspace vet, GOWORK=off vet and submodule-module vet green; go build -o bin/fonoteka . OK (the running dev server was not touched); the README names no consuming application. Pure-move diff gates pass: every changed .go, go.mod and summer.yaml line in both the plugin and fonoteka.go is a module-path line. main.go is unchanged by summer build, and the submodule and fonoteka.go are clean and pushed.
Full Docker suite go test -count=1 -timeout 30m ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/...: exit 0, 82 s for the first run (35-45 s for the post-commit re-run), no FAIL. ok for: git.golem15.com/golem15/fonoteka, .../parity, .../plugins/golem15/fonoteka (plus classes, classes/auth, console, controllers/api, middleware, models, updates), and git.golem15.com/golem15/sm-user-plugin (plus classes and updates).
Task 3 gates: note has Supersedes, the new module path and the submodule workflow; 01-CONTEXT pointer present, keios.eu line kept; PROJECT, ROADMAP Phase 12 (Repos line and 12-01 entry only; goal and criteria byte-identical) and the three Phase 12 plans updated; all three pass verify.plan-structure; the commit holds exactly 7 .planning/ files, without state.json; no summercms.go code or docs reference an app-nested plugin path; go vet ./... green.
Deviations from Plan
The plan was executed as written. Notes:
The README Features list was written from the code and states only what the code does. The user plugin has no personal API tokens, so the plan's example "personal API tokens" was left out. The must-change-password lock is described as the flag carried on bouncer.Principal.MustChangePassword and cleared by POST /change-password. golem15.user.jwt.leeway is marked as declared but not read yet.
The decision note uses the header style of the existing notes (**Date:**, **Status:**, **Context:**, **Supersedes:**) instead of YAML frontmatter, following the lagoon-per-query-collation.md precedent.
STATE.md was not updated, and SUMMARY.md, STATE.md and PLAN.md were not committed. The orchestrator handles the docs commit for quick tasks.
Follow-ups
TestRegisterCORSPath (plugin register_test.go) walks up to the host application's config/http.yaml, so the plugin's full test suite passes only when it is mounted inside an application checkout. Make the test self-contained (embedded fixture) in a later change to the plugin.
Two code comments in the plugin still name the first consuming application: models/organisation.go:5 and updates/10_organisations.go:12. They were left unchanged in the pure move; neutralise them in a later plugin commit. TestRegisterImportDirection also guards against the app plugin's path string plugins/golem15/fonoteka; that is acceptable but could be generalised.
The rename of fonoteka.go itself to sm-fonoteka-app is still pending (separate task).