Files
summercms/.planning/phases/12.1-user-plugin-admin-screens/12.1-DISCUSSION-LOG.md
2026-10-04 14:52:44 +02:00

194 lines
8.7 KiB
Markdown

# Phase 12.1: User plugin admin screens - Discussion Log
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
**Date:** 2026-10-04
**Phase:** 12.1-user-plugin-admin-screens
**Areas discussed:** Impersonate and convert-guest, Group membership and the admin group, User actions and trashed users, Fields the Go model lacks, Release
---
## Impersonate and convert-guest
### Should 'impersonate user' be part of this phase?
| Option | Description | Selected |
|--------|-------------|----------|
| Out of scope (Recommended) | PHP impersonation is session-based and never reaches the JWT-driven Nuxt app; permission not registered | |
| Out, but register the permission | No action, but `golem15.users.impersonate_user` is registered so imported roles stay valid | ✓ |
| In scope: mint a user JWT | Admin gets a short-lived frontend token for the user, with audit; needs security review and a Nuxt entry point | |
**User's choice:** Out, but register the permission
### What happens to convert-guest and the guest concept?
| Option | Description | Selected |
|--------|-------------|----------|
| Drop it entirely (Recommended) | No action, no `is_guest` column or list column, no guest hint | ✓ |
| Add is_guest, skip the action | Column and invisible list column for schema fidelity, no popup | |
| Port convert-guest fully | Column, popup with group choice, optional registration mail | |
**User's choice:** Drop it entirely
**Notes:** The application never creates guests and the Go users table has no `is_guest`.
---
## Group membership and the admin group
### Which backend permission is required to change a user's group membership?
| Option | Description | Selected |
|--------|-------------|----------|
| Extra permission for privileged groups (Recommended) | `access_users` for ordinary groups; privileged groups need a new permission, server-side | ✓ |
| access_users only (PHP parity) | Any user editor can put a user in any group, including `admin` | |
| New permission for all membership changes | Any `users_groups` change needs a dedicated permission | |
### How does the plugin know which groups are privileged?
| Option | Description | Selected |
|--------|-------------|----------|
| Config list, default [admin] (Recommended) | `golem15.user` config key listing privileged codes | ✓ |
| Hard-coded code `admin` | Only `admin` is privileged, no config | |
| A flag column on user_groups | New boolean on the group row | |
### How should the User Groups screen guard privileged codes?
| Option | Description | Selected |
|--------|-------------|----------|
| Privileged codes need the extra permission (Recommended) | Create with, rename to/from, and delete of a privileged code need the extra permission | ✓ |
| Code is read-only after create | Code never changes once saved | |
| No guard (PHP parity) | `access_groups` edits any group including its code | |
### How do privileged groups behave for an admin without the permission?
| Option | Description | Selected |
|--------|-------------|----------|
| Shown but locked, 403 on tamper (Recommended) | Visible and disabled; a tampered save is refused and changes nothing | ✓ |
| Hidden from the options | Left out of the field; existing memberships kept | |
| Whole save refused, no UI hint | Field looks normal; validation error if a privileged group changed | |
---
## User actions and trashed users
### How should the Go admin carry the six bulk actions and three record actions?
| Option | Description | Selected |
|--------|-------------|----------|
| Extend cabana generically (Recommended) | Framework gains declared bulk actions and record actions | ✓ |
| Plugin-side with existing pieces | Widget buttons on the form; bulk actions dropped except delete | |
| Record actions only, bulk later | Record buttons now, bulk to the backlog | |
### Delete semantics and trashed users
| Option | Description | Selected |
|--------|-------------|----------|
| PHP parity (Recommended) | Trashed users listed; deactivate = soft delete, restore, delete = permanent | ✓ |
| Parity, but force delete needs confirmation by email | Same, plus typing the user's email before a permanent delete | |
| Soft delete only | No permanent delete in the admin | |
### Where do the status and the actions live (PHP has a preview screen)?
| Option | Description | Selected |
|--------|-------------|----------|
| On the update form (Recommended) | Status notice and conditional action buttons on the update form; no preview | |
| Add a preview screen to the framework | cabana gains Winter's preview context with its own toolbar | ✓ |
| Actions always visible, no status notice | All buttons shown regardless of state | |
**User's choice:** Add a preview screen to the framework
**Notes:** Chosen over the recommended lighter option; PHP parity of the admin experience is the bar.
### How should the list show user state?
| Option | Description | Selected |
|--------|-------------|----------|
| Generic row state in the framework (Recommended) | Controller returns a state per row from a fixed set; SPA styles with tokens | ✓ |
| A status column | One computed Status column, no row styling | |
| Both | Row state and a status column | |
---
## Fields the Go model lacks
### Port the frontend Permissions tab (FrontendPermissionEditor)?
| Option | Description | Selected |
|--------|-------------|----------|
| Leave out, defer (Recommended) | No Permissions tab; its own later phase | |
| Port the editor | Registry table, `users.permissions`, editor on both forms | ✓ |
**User's choice:** Port the editor
### How far does the frontend-permissions port go?
| Option | Description | Selected |
|--------|-------------|----------|
| Storage, editor and resolver (Recommended) | Table, column, editor, and a Go `getMergedPermissions` equivalent | ✓ |
| Storage and editor only | No resolver until a project needs it | |
| Also a plugin-declared registry | Plugins declare frontend permissions in Go, synced at boot | |
### How should the editor be built?
| Option | Description | Selected |
|--------|-------------|----------|
| Built-in framework field type (Recommended) | `permissioneditor` in cabana and the SPA, reusable for backend roles later | ✓ |
| Extend the widget contract | `type: widget` carries a structured value; plugin ships a custom element | |
### Block mail (MailBlocker)
| Option | Description | Selected |
|--------|-------------|----------|
| Leave out, defer (Recommended) | No checkbox; a mail feature, not an admin screen | |
| Port MailBlocker now | Table, form flag, mailer check | |
**User's choice:** (free text) "Leave out, write in todos to implement together with mailing development (so together with mail settings, templates etc)"
**Notes:** Todo written: `.planning/todos/pending/mailblocker-with-mailing.md`.
### username and last_seen
| Option | Description | Selected |
|--------|-------------|----------|
| Drop both from the YAML (Recommended) | Only columns the Go model has | |
| Add last_seen, drop username | Additive `last_seen` updated by the auth path | ✓ |
| Add both columns | Full schema fidelity | |
### Create form: password, invite, avatar
| Option | Description | Selected |
|--------|-------------|----------|
| All of it (Recommended) | Password + confirmation, reset on update, `send_invite` mail, avatars on users and organisations | ✓ |
| Password and avatar, no invite | No invitation mail | |
| Password only | No invite, no avatar fields | |
---
## Release
| Option | Description | Selected |
|--------|-------------|----------|
| Framework first, tagged v0.1.2 (Recommended) | Framework work lands first and is tagged; plugin builds on the tag | ✓ (as v0.1.3) |
| One phase, no tag | Ship together through the local replace | |
| Split the framework work into its own phase | Insert 12.3 for the cabana features | |
**User's choice:** (free text) "Framework first, but i belive it's v0.1.3, v0.1.2 already exists"
**Notes:** Verified with `git tag`: v0.1.2 exists, so the tag is v0.1.3.
---
## Claude's Discretion
- The extra permission's code, label and tab; the privileged-list config key name.
- YAML keys and Go interface names for bulk actions, record actions, preview and row state.
- The row state set and styling; preview screen contents beyond hints, fields and actions.
- When `last_seen` is written; force-delete cleanup details.
- Plan count and split (subject to the plan-count checkpoint).
## Deferred Ideas
- Impersonation by minting a short-lived user JWT.
- MailBlocker with the mailing work (todo written).
- Guests and convert-guest; `username` and login by username.
- Plugin-declared frontend permission registry; `permissioneditor` for backend roles.
- The user plugin's Settings screen.