|
|
|
|
@@ -135,12 +135,12 @@ ROADMAP Phase 12 goal (verbatim, not in user-story form; MVP precedent of Phases
|
|
|
|
|
This plan's slice: the framework can produce every Laravel 422 body, record and replay multipart uploads, emit Winter-shaped upload URLs, decode webp, report the search engine's `found` count and rank fields by weight; the user plugin knows user groups; and the roadmap and requirements say what Phase 12 actually ships. Nothing here is user-visible on its own: plans 12-02 to 12-04 build every endpoint on these pieces.
|
|
|
|
|
|
|
|
|
|
<objective>
|
|
|
|
|
Close the framework gaps RESEARCH Finding 5 lists (summercms.go), add user groups to the Go user plugin (fonoteka.go, the user plugin lives at `../fonoteka.go/plugins/golem15/user`), and correct the planning-doc wording.
|
|
|
|
|
Close the framework gaps RESEARCH Finding 5 lists (summercms.go), add user groups to the Go user plugin (repo sm-user-plugin, module `git.golem15.com/golem15/sm-user-plugin`, mounted as a git submodule at `../fonoteka.go/plugins/golem15/user`), and correct the planning-doc wording.
|
|
|
|
|
|
|
|
|
|
Purpose: every Phase 12 endpoint needs Laravel-exact 422 bodies (D-21), multipart recordings (D-11), PHP upload URLs (D-22), webp (D-24), a re-gated search total (D-19) and the site-admin predicate (D-25).
|
|
|
|
|
Output: `lagoon.ValidateRequest` with pl/en catalogs; attach `URL`/`PublicURL` and webp; tide multipart and upload/publication masks; beachcomber `PageSearcher` and weights; user groups; README and docs updates; reworded ROADMAP/REQUIREMENTS.
|
|
|
|
|
|
|
|
|
|
Repos: summercms.go (framework and planning docs) and fonoteka.go (user plugin). Framework code, tests, READMEs and docs use neutral names (acme, blog, posts) and never name the application. Planning docs and code go in separate commits; never add co-author tags.
|
|
|
|
|
Repos: summercms.go (framework and planning docs), sm-user-plugin (user groups, committed inside the submodule and pushed to its origin master first) and fonoteka.go (parity schema allow-list plus the bumped submodule pointer). Framework code, tests, READMEs and docs use neutral names (acme, blog, posts) and never name the application. Planning docs and code go in separate commits; never add co-author tags.
|
|
|
|
|
</objective>
|
|
|
|
|
|
|
|
|
|
<execution_context>
|
|
|
|
|
@@ -268,11 +268,13 @@ Detector run on the Phase 12 ROADMAP section: detected=false. Considered D-25 (u
|
|
|
|
|
|
|
|
|
|
(2) Docs in the same change: modules/beachcomber/README.md and docs/services/search.md (PageSearcher, SearchResult, the helper, QueryByWeights, the 250 per-page limit, and that ids remain candidates only that callers re-gate in SQL).
|
|
|
|
|
|
|
|
|
|
(3) User groups, per D-25 (fonoteka.go user plugin, additive): models/user_group.go `UserGroup{ID uint; Name string; Code *string; Description *string; Permissions *string; CreatedAt, UpdatedAt *time.Time}` with TableName `user_groups`, registered in the models registry like the other models; add `Groups []UserGroup` to models.User with tag `gorm:"many2many:users_groups;joinForeignKey:user_id;joinReferences:user_group_id"` and `json:"-"` (GORM never writes it unless a caller associates groups; nothing in the user plugin does). Migration file updates/202610020001_create_user_groups.go (ID `202610020001_create_user_groups`): create `user_groups` (id serial primary key, name varchar(255) not null, code varchar(255) null with an index, description text null, permissions text null, created_at and updated_at timestamp null) and `users_groups` (user_id integer not null, user_group_id integer not null, primary key (user_id, user_group_id) named user_group), then insert the Guest/guest and Registered/registered rows with PHP's descriptions; Rollback drops both tables. classes/user_groups.go: `UserGroupCodes(ctx, db, userID uint) ([]string, error)` (codes of the user's groups ordered by user_groups.id, null codes skipped) and `HasGroupCode(ctx, db, userID uint, code string) (bool, error)`. The user API payload keeps `"groups":[]` exactly as today (D-25: contract unchanged); do not read the new table in any user-plugin handler.
|
|
|
|
|
(3) User groups, per D-25 (sm-user-plugin, additive): models/user_group.go `UserGroup{ID uint; Name string; Code *string; Description *string; Permissions *string; CreatedAt, UpdatedAt *time.Time}` with TableName `user_groups`, registered in the models registry like the other models; add `Groups []UserGroup` to models.User with tag `gorm:"many2many:users_groups;joinForeignKey:user_id;joinReferences:user_group_id"` and `json:"-"` (GORM never writes it unless a caller associates groups; nothing in the user plugin does). Migration file updates/202610020001_create_user_groups.go (ID `202610020001_create_user_groups`): create `user_groups` (id serial primary key, name varchar(255) not null, code varchar(255) null with an index, description text null, permissions text null, created_at and updated_at timestamp null) and `users_groups` (user_id integer not null, user_group_id integer not null, primary key (user_id, user_group_id) named user_group), then insert the Guest/guest and Registered/registered rows with PHP's descriptions; Rollback drops both tables. classes/user_groups.go: `UserGroupCodes(ctx, db, userID uint) ([]string, error)` (codes of the user's groups ordered by user_groups.id, null codes skipped) and `HasGroupCode(ctx, db, userID uint, code string) (bool, error)`. The user API payload keeps `"groups":[]` exactly as today (D-25: contract unchanged); do not read the new table in any user-plugin handler.
|
|
|
|
|
|
|
|
|
|
(4) parity/schema_diff_test.go: add allowedDiffs entries `user_groups` and `users_groups` with a reason naming D-25 and that the frozen PHP snapshot predates the user-plugin dump (the same justification as user_throttle). Keep every other entry.
|
|
|
|
|
|
|
|
|
|
(5) Tests: updates/user_groups_test.go on the plugin's Postgres harness: migrate up creates both tables and the two seed rows, RollbackLast drops them, re-up works; UserGroupCodes returns `admin` for a user linked to a group with code admin and an empty slice for a user with no groups.</action>
|
|
|
|
|
(5) Tests: updates/user_groups_test.go on the plugin's Postgres harness: migrate up creates both tables and the two seed rows, RollbackLast drops them, re-up works; UserGroupCodes returns `admin` for a user linked to a group with code admin and an empty slice for a user with no groups.
|
|
|
|
|
|
|
|
|
|
(6) Commits: commit the user-plugin files inside the submodule (`git -C ../fonoteka.go/plugins/golem15/user`), push its master, then commit parity/schema_diff_test.go together with the bumped submodule pointer in fonoteka.go, no co-author tags.</action>
|
|
|
|
|
<verify>
|
|
|
|
|
<automated>go vet ./... && go test ./modules/beachcomber/... -count=1 -v -run '^(TestSearchPage.*|TestTypesenseSearchPage.*)$' && go test ./cmd/summer -run TestDocsTree -count=1 && go -C ../fonoteka.go vet ./... && go -C ../fonoteka.go test ./plugins/golem15/user/updates -count=1 -v -run '^(TestUserGroups.*)$' && go -C ../fonoteka.go test ./parity -run '^(TestSchemaMatchesPHPSnapshot|TestUserAPINuxtFlows)$' -count=1</automated>
|
|
|
|
|
<fails_when>Any command exits non-zero; a verbose run prints "no tests to run", "--- FAIL" or "--- SKIP", or lacks "--- PASS" for a TestSearchPage test and a TestUserGroups test; TestSchemaMatchesPHPSnapshot reports an extra Go table; TestUserAPINuxtFlows fails (user payload changed).</fails_when>
|
|
|
|
|
@@ -283,7 +285,7 @@ Detector run on the Phase 12 ROADMAP section: detected=false. Considered D-25 (u
|
|
|
|
|
- `grep -c 'PageSearcher' modules/beachcomber/README.md` and `grep -c 'PageSearcher' docs/services/search.md` each print at least 1.
|
|
|
|
|
- `grep -c '"user_groups"' ../fonoteka.go/parity/schema_diff_test.go` and `grep -c '"users_groups"' ../fonoteka.go/parity/schema_diff_test.go` each print 1.
|
|
|
|
|
- `grep -c 'json:"-"' ../fonoteka.go/plugins/golem15/user/models/user.go` increases by one relative to HEAD (the Groups field is never serialized).
|
|
|
|
|
- `grep '"groups":' ../fonoteka.go/plugins/golem15/user/controllers/api_controller.go | grep -c '\[\]any{}'` prints 1, and this task's fonoteka.go commit touches no file under `plugins/golem15/user/controllers/` (payload untouched).
|
|
|
|
|
- `grep '"groups":' ../fonoteka.go/plugins/golem15/user/controllers/api_controller.go | grep -c '\[\]any{}'` prints 1, and this task's sm-user-plugin commit touches no file under `controllers/` (payload untouched).
|
|
|
|
|
</acceptance_criteria>
|
|
|
|
|
<done>Callers can ask the search engine for one page of candidate ids and the total it found, ranked with explicit weights, and any plugin can ask which group codes a user has without the user API changing.</done>
|
|
|
|
|
</task>
|
|
|
|
|
|