- classes.FrontendPermissionCatalog: the seeded rows, then codes activated
plugins declare through pact.HasFrontendPermissions (seeded row wins);
both permission editors offer it
- classes.MCPUserGuard (guard "user"): reads user.api_token, user.scope:*
and user.permission:*, allows with the route's checks (session scopes,
group grants, every code), dispatches with an in-memory token credential,
resolves usr_ personal tokens; registered in *pact.MCPGuards and published
as pact.MCPPersonalTokenResolver
- GET /_user/api/v1/token/me (user.api_token, user.scope:read) and the MCP
tool me (user_me)
- pact.MCPSubjectChanged on token revoke, Users saves and User Groups saves
and deletes
- golem15_user_backend_links (1:1, both sides unique) and one-shot hashed
golem15_user_backend_link_requests (golem15.user.backend_links.request_ttl, 10m)
- classes.BackendLinks: CreateLinkRequest, ConfirmLinkRequest (row lock,
JWT iat not before the request), SetLink, RemoveLink, LinkedBackendUser;
published as *classes.BackendLinks and pact.MCPLinkedBackendResolver
- GET /_user/api/v1/backend-link/{code} and POST /backend-link/confirm (jwt.auth)
- My account section frontend_account with link and unlink
- BackendLinkedEvent, BackendUnlinkedEvent and pact.MCPSubjectChanged after commit;
deleting or deactivating a frontend user removes its link
- golem15.user.frontend_url (falls back to app.url)
Boot runs before summer serve publishes the database, so the plugin's GORM
hooks, the Postgres jwt_blacklist store and its sweep now go through
lagoon.OnDatabase, and the jwt guard resolves the published store on every
request. A logged-out token is refused on jwt.auth, /fetch and /refresh.
The jwt guard reads the cookie names from classes.SessionCookieNames().
Every command gets long help and examples, descriptions in imperative
sentence case, and a warn-only TestCommandsDocumented over bonfire.CheckDocs.
The plugin logs through a diary component logger instead of the process
default logger. Requires SummerCMS v0.4.0; command names and flags unchanged.
user:token:create and user:token:list gain --json, user:backfill-handles a
progress bar; planning IDs leave the descriptions.
Register lighthouse user:{id} if the namespace is free, fire user.Deleting before unscoped delete, and backfill missing handles.
Co-authored-by: Cursor <cursoragent@cursor.com>
- password with confirmation on create, optional reset on update that
ends the user's sessions; the hash is never returned
- send_invite sends one invitation with an activation link after the
create commits
- organisation picker, avatar upload shared with the user API and the
frontend permission editor on the user form
- an email held by a deactivated user answers 422 instead of failing
on the unique constraint
- the privileged-member guard now also refuses a submitted password
Prefix replacement of the old application-nested module path in go.mod
and every import. No identifier, string, table, migration ID, config key
or comment changes.
Match PHP payloads, already-activated Winter 500 HTML, and direct-DB
seeding so the corpus can flip those routes to ported without onboarding.
Co-authored-by: Cursor <cursoragent@cursor.com>
Wire the user API session loop to the JWT blacklist and a pre-password throttle gate so a logged-out token cannot be fetched again.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Verify inv_ tokens against ApiToken hash, expiry, revocation, last-used
- InvScope writes PHP TokenScope 401/403 bodies and gates on HasScope
- Register jwt and inv_token on the shared bouncer.Registry at plugin Boot
- Move models, classes, controllers, middleware, and updates into subpackages
- Add self-registering models/updates/classes registries so later plans add files
- Keep the genres route and shipped migration SQL unchanged
golem15.user registers jwt.auth, golem15.fonoteka mounts GET /_fonoteka/api/v1/genres
through that guard, and a smoke test reads the 15 migrated rows with a test-only token.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add compiled golem15.user and golem15.fonoteka plugins, squash schema
to the genre slice tables, and seed the 15 canonical genres on ICU pl-PL.
Co-authored-by: Cursor <cursoragent@cursor.com>