From 7ce5b8321573e6628c4449382ab5507ac1ff5aae Mon Sep 17 00:00:00 2001 From: shaw Date: Wed, 29 Apr 2026 21:00:30 +0800 Subject: [PATCH] chore: remove superpowers docs --- ...-27-account-bulk-edit-scope-and-compact.md | 359 ------------------ ...ount-bulk-edit-scope-and-compact-design.md | 233 ------------ 2 files changed, 592 deletions(-) delete mode 100644 docs/superpowers/plans/2026-04-27-account-bulk-edit-scope-and-compact.md delete mode 100644 docs/superpowers/specs/2026-04-27-account-bulk-edit-scope-and-compact-design.md diff --git a/docs/superpowers/plans/2026-04-27-account-bulk-edit-scope-and-compact.md b/docs/superpowers/plans/2026-04-27-account-bulk-edit-scope-and-compact.md deleted file mode 100644 index 42b76664..00000000 --- a/docs/superpowers/plans/2026-04-27-account-bulk-edit-scope-and-compact.md +++ /dev/null @@ -1,359 +0,0 @@ -# Account Bulk Edit Scope And Compact Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Add filter-result bulk edit to admin accounts, unify the table-level bulk-edit entry, and align OpenAI bulk-edit controls with the existing compact-related single-account settings. - -**Architecture:** Extend the existing `/admin/accounts/bulk-update` flow to accept either explicit account IDs or a server-resolved filter target. Reuse the current account-list filter contract for scope resolution, then update the accounts view and bulk-edit modal so the UI can launch either selected-account edits or current-filter-result edits from one compact dropdown. Keep the existing bulk-edit form, but expand its target contract and OpenAI-specific field coverage. - -**Tech Stack:** Vue 3, TypeScript, Vitest, Gin, Go service/repository layer, existing admin accounts API. - ---- - -### Task 1: Add backend test coverage for filter-target bulk update - -**Files:** -- Modify: `backend/internal/handler/admin/account_handler_mixed_channel_test.go` -- Modify: `backend/internal/service/admin_service_bulk_update_test.go` -- Test: `backend/internal/handler/admin/account_handler_mixed_channel_test.go` -- Test: `backend/internal/service/admin_service_bulk_update_test.go` - -- [ ] **Step 1: Write the failing handler test for filter-target request acceptance** - -```go -func TestBulkUpdateAcceptsFilterTargetRequest(t *testing.T) { - // add a request body that omits account_ids and submits filters instead - // assert the route does not reject the request as malformed once service stubs are wired -} -``` - -- [ ] **Step 2: Run test to verify it fails** - -Run: `GOCACHE=/tmp/go-build GOMODCACHE=/tmp/go-mod go test ./backend/internal/handler/admin -run TestBulkUpdateAcceptsFilterTargetRequest -count=1` -Expected: FAIL because `BulkUpdateAccountsRequest` does not yet support `filters`. - -- [ ] **Step 3: Write the failing service test for resolving IDs from filters** - -```go -func TestAdminServiceBulkUpdateAccounts_ResolvesIDsFromFilters(t *testing.T) { - // construct BulkUpdateAccountsInput with Filters and no AccountIDs - // stub repository list/search path to return matching IDs - // assert BulkUpdate is called with all matching account IDs -} -``` - -- [ ] **Step 4: Run test to verify it fails** - -Run: `GOCACHE=/tmp/go-build GOMODCACHE=/tmp/go-mod go test ./backend/internal/service -run TestAdminServiceBulkUpdateAccounts_ResolvesIDsFromFilters -count=1` -Expected: FAIL because `BulkUpdateAccountsInput` and service logic only use explicit `AccountIDs`. - -- [ ] **Step 5: Commit** - -```bash -git add backend/internal/handler/admin/account_handler_mixed_channel_test.go backend/internal/service/admin_service_bulk_update_test.go -git commit -m "test: cover filter-target account bulk update" -``` - -### Task 2: Implement backend filter-target bulk update - -**Files:** -- Modify: `backend/internal/handler/admin/account_handler.go` -- Modify: `backend/internal/service/admin_service.go` -- Modify: `backend/internal/repository/account_repo.go` -- Modify: `backend/internal/service/account_service.go` -- Test: `backend/internal/handler/admin/account_handler_mixed_channel_test.go` -- Test: `backend/internal/service/admin_service_bulk_update_test.go` - -- [ ] **Step 1: Implement request structs and validation for filter targets** - -```go -type BulkUpdateAccountFilters struct { - Platform string `json:"platform"` - Type string `json:"type"` - Status string `json:"status"` - Group string `json:"group"` - Search string `json:"search"` - PrivacyMode string `json:"privacy_mode"` -} - -type BulkUpdateAccountsRequest struct { - AccountIDs []int64 `json:"account_ids"` - Filters *BulkUpdateAccountFilters `json:"filters"` - // existing fields remain unchanged -} -``` - -- [ ] **Step 2: Resolve filter targets in the service layer with one canonical path** - -```go -type BulkUpdateAccountsInput struct { - AccountIDs []int64 - Filters *BulkUpdateAccountFilters - // existing fields remain unchanged -} - -if len(input.AccountIDs) == 0 && input.Filters != nil { - ids, err := s.resolveBulkUpdateTargetIDs(ctx, input.Filters) - if err != nil { - return nil, err - } - input.AccountIDs = ids -} -``` - -- [ ] **Step 3: Reuse existing account-search/repository logic to resolve all matching IDs** - -```go -func (s *AdminService) resolveBulkUpdateTargetIDs(ctx context.Context, filters *BulkUpdateAccountFilters) ([]int64, error) { - // call the existing repository list/search path with the submitted filters - // page through all matching rows or use a dedicated ID-only query helper - // return unique IDs in stable order -} -``` - -- [ ] **Step 4: Run targeted backend tests** - -Run: `GOCACHE=/tmp/go-build GOMODCACHE=/tmp/go-mod go test ./backend/internal/handler/admin ./backend/internal/service -run 'TestBulkUpdateAcceptsFilterTargetRequest|TestAdminServiceBulkUpdateAccounts_ResolvesIDsFromFilters' -count=1` -Expected: PASS - -- [ ] **Step 5: Commit** - -```bash -git add backend/internal/handler/admin/account_handler.go backend/internal/service/admin_service.go backend/internal/repository/account_repo.go backend/internal/service/account_service.go backend/internal/handler/admin/account_handler_mixed_channel_test.go backend/internal/service/admin_service_bulk_update_test.go -git commit -m "feat: support filter-target account bulk update" -``` - -### Task 3: Add frontend API and modal tests for target scope - -**Files:** -- Modify: `frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts` -- Create: `frontend/src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts` -- Modify: `frontend/src/api/admin/accounts.ts` -- Test: `frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts` -- Test: `frontend/src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts` - -- [ ] **Step 1: Write the failing modal test for filter-target payload submission** - -```ts -it('submits bulk edit using current filters when target mode is filtered-results', async () => { - // mount BulkEditAccountModal with targetMode='filtered' - // submit a minimal change - // expect adminAPI.accounts.bulkUpdate to receive { filters: ... } rather than account_ids -}) -``` - -- [ ] **Step 2: Run test to verify it fails** - -Run: `pnpm -C frontend test:run src/components/account/__tests__/BulkEditAccountModal.spec.ts -t "filtered-results"` -Expected: FAIL because the modal only accepts `accountIds`. - -- [ ] **Step 3: Write the failing accounts-view test for dropdown launch actions** - -```ts -it('opens bulk edit for current filtered results from the table action dropdown', async () => { - // mount AccountsView with filters set - // click Bulk edit > current filtered results - // assert modal props contain filter target metadata -}) -``` - -- [ ] **Step 4: Run test to verify it fails** - -Run: `pnpm -C frontend test:run src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts` -Expected: FAIL because the dropdown action and target scope state do not exist yet. - -- [ ] **Step 5: Commit** - -```bash -git add frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts frontend/src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts frontend/src/api/admin/accounts.ts -git commit -m "test: cover account bulk edit target scopes" -``` - -### Task 4: Implement unified frontend bulk-edit target scope flow - -**Files:** -- Modify: `frontend/src/views/admin/AccountsView.vue` -- Modify: `frontend/src/components/admin/account/AccountBulkActionsBar.vue` -- Modify: `frontend/src/components/account/BulkEditAccountModal.vue` -- Modify: `frontend/src/api/admin/accounts.ts` -- Modify: `frontend/src/i18n/locales/zh.ts` -- Modify: `frontend/src/i18n/locales/en.ts` -- Test: `frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts` -- Test: `frontend/src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts` - -- [ ] **Step 1: Add a typed frontend target contract for bulk edit** - -```ts -export type AccountBulkEditTarget = - | { mode: 'selected'; accountIds: number[]; selectedPlatforms: AccountPlatform[]; selectedTypes: AccountType[] } - | { mode: 'filtered'; filters: AccountListFilters; previewCount: number; selectedPlatforms: AccountPlatform[]; selectedTypes: AccountType[] } -``` - -- [ ] **Step 2: Replace the single selected-row edit button with one dropdown** - -```vue - -``` - -- [ ] **Step 3: Snapshot current filters and preview count when launching filtered mode** - -```ts -const openBulkEditFiltered = async () => { - const filters = toBulkEditFilterSnapshot(params) - const preview = await adminAPI.accounts.list(1, 1, filters) - bulkEditTarget.value = { - mode: 'filtered', - filters, - previewCount: preview.pagination.total, - selectedPlatforms: collectPlatforms(preview.data), - selectedTypes: collectTypes(preview.data) - } - showBulkEdit.value = true -} -``` - -- [ ] **Step 4: Update modal submission to call `bulkUpdate` with either `account_ids` or `filters`** - -```ts -if (props.target.mode === 'selected') { - await adminAPI.accounts.bulkUpdate({ account_ids: props.target.accountIds, ...updates }) -} else { - await adminAPI.accounts.bulkUpdate({ filters: props.target.filters, ...updates }) -} -``` - -- [ ] **Step 5: Run targeted frontend tests** - -Run: `pnpm -C frontend test:run src/components/account/__tests__/BulkEditAccountModal.spec.ts src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts` -Expected: PASS - -- [ ] **Step 6: Commit** - -```bash -git add frontend/src/views/admin/AccountsView.vue frontend/src/components/admin/account/AccountBulkActionsBar.vue frontend/src/components/account/BulkEditAccountModal.vue frontend/src/api/admin/accounts.ts frontend/src/i18n/locales/zh.ts frontend/src/i18n/locales/en.ts frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts frontend/src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts -git commit -m "feat: add filtered-result account bulk edit" -``` - -### Task 5: Add failing tests for missing OpenAI bulk-edit fields - -**Files:** -- Modify: `frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts` -- Test: `frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts` - -- [ ] **Step 1: Write the failing OAuth test for `codex_cli_only`** - -```ts -it('OpenAI OAuth bulk edit can submit codex_cli_only', async () => { - // enable the toggle and submit - // expect extra.codex_cli_only to be sent -}) -``` - -- [ ] **Step 2: Run test to verify it fails** - -Run: `pnpm -C frontend test:run src/components/account/__tests__/BulkEditAccountModal.spec.ts -t "codex_cli_only"` -Expected: FAIL because the modal has no such control or payload mapping. - -- [ ] **Step 3: Write the failing API key test for API key WS mode** - -```ts -it('OpenAI API key bulk edit submits API key WS mode fields', async () => { - // enable the API key WS mode selector and submit - // expect openai_apikey_responses_websockets_v2_mode and enabled flag -}) -``` - -- [ ] **Step 4: Run test to verify it fails** - -Run: `pnpm -C frontend test:run src/components/account/__tests__/BulkEditAccountModal.spec.ts -t "API key WS mode"` -Expected: FAIL because the modal only submits OAuth WS mode. - -- [ ] **Step 5: Commit** - -```bash -git add frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts -git commit -m "test: cover missing OpenAI bulk edit fields" -``` - -### Task 6: Implement missing OpenAI bulk-edit controls and payload wiring - -**Files:** -- Modify: `frontend/src/components/account/BulkEditAccountModal.vue` -- Modify: `frontend/src/i18n/locales/zh.ts` -- Modify: `frontend/src/i18n/locales/en.ts` -- Test: `frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts` - -- [ ] **Step 1: Add UI controls for OAuth `codex_cli_only` and API key WS mode** - -```vue -
- - -
- -
- -
-``` - -- [ ] **Step 2: Mirror single-account payload semantics in the bulk-edit submit builder** - -```ts -if (enableCodexCLIOnly.value) { - const extra = ensureExtra() - extra.codex_cli_only = codexCLIOnlyEnabled.value -} - -if (enableOpenAIAPIKeyWSMode.value) { - const extra = ensureExtra() - extra.openai_apikey_responses_websockets_v2_mode = openaiAPIKeyResponsesWebSocketV2Mode.value - extra.openai_apikey_responses_websockets_v2_enabled = isOpenAIWSModeEnabled(openaiAPIKeyResponsesWebSocketV2Mode.value) -} -``` - -- [ ] **Step 3: Run focused modal tests** - -Run: `pnpm -C frontend test:run src/components/account/__tests__/BulkEditAccountModal.spec.ts` -Expected: PASS - -- [ ] **Step 4: Commit** - -```bash -git add frontend/src/components/account/BulkEditAccountModal.vue frontend/src/i18n/locales/zh.ts frontend/src/i18n/locales/en.ts frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts -git commit -m "feat: align OpenAI bulk edit compact settings" -``` - -### Task 7: Final regression verification - -**Files:** -- Modify: none expected -- Test: `frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts` -- Test: `frontend/src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts` -- Test: `backend/internal/handler/admin/account_handler_mixed_channel_test.go` -- Test: `backend/internal/service/admin_service_bulk_update_test.go` - -- [ ] **Step 1: Run frontend typecheck** - -Run: `pnpm -C frontend typecheck` -Expected: PASS - -- [ ] **Step 2: Run focused frontend test suite** - -Run: `pnpm -C frontend test:run src/components/account/__tests__/BulkEditAccountModal.spec.ts src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts` -Expected: PASS - -- [ ] **Step 3: Run focused backend test suite** - -Run: `GOCACHE=/tmp/go-build GOMODCACHE=/tmp/go-mod go test ./backend/internal/handler/admin ./backend/internal/service -run 'BulkUpdate|bulk update' -count=1` -Expected: PASS - -- [ ] **Step 4: Commit final integration fixes if needed** - -```bash -git add frontend/src/components/account/BulkEditAccountModal.vue frontend/src/views/admin/AccountsView.vue frontend/src/components/admin/account/AccountBulkActionsBar.vue frontend/src/api/admin/accounts.ts frontend/src/i18n/locales/zh.ts frontend/src/i18n/locales/en.ts backend/internal/handler/admin/account_handler.go backend/internal/service/admin_service.go backend/internal/repository/account_repo.go backend/internal/service/account_service.go frontend/src/components/account/__tests__/BulkEditAccountModal.spec.ts frontend/src/views/admin/__tests__/AccountsView.bulkEdit.spec.ts backend/internal/handler/admin/account_handler_mixed_channel_test.go backend/internal/service/admin_service_bulk_update_test.go -git commit -m "feat: finish account bulk edit scope and compact support" -``` diff --git a/docs/superpowers/specs/2026-04-27-account-bulk-edit-scope-and-compact-design.md b/docs/superpowers/specs/2026-04-27-account-bulk-edit-scope-and-compact-design.md deleted file mode 100644 index 3a1dc5ac..00000000 --- a/docs/superpowers/specs/2026-04-27-account-bulk-edit-scope-and-compact-design.md +++ /dev/null @@ -1,233 +0,0 @@ -# Account Bulk Edit Scope And Compact Design - -## Summary - -This change expands admin account bulk edit in two directions: - -1. Add a second bulk-edit target scope based on the current filter result set, so operators do not need to manually select every account. -2. Align OpenAI bulk-edit fields with single-account create/edit for the compact-related settings that are already supported elsewhere. - -The design keeps the existing selected-row workflow intact and adds a unified bulk-edit entry with two explicit actions: - -- `Bulk edit selected accounts` -- `Bulk edit current filtered results` - -`Current filtered results` reuses the existing account-list filters. That means: - -- with no filters, it targets the whole account inventory -- with a group filter, it targets all accounts in that group -- with combined filters, it targets all matching accounts - -## Goals - -- Preserve the current selected-account bulk edit flow. -- Let operators bulk edit the full current filtered result set without manual row selection. -- Show the user the exact target scope before applying changes. -- Reuse the current list filter semantics instead of inventing a separate "all accounts" or "by group" API. -- Add the missing OpenAI bulk-edit fields: - - OAuth `codex_cli_only` - - API key `openai_apikey_responses_websockets_v2_mode` - -## Non-Goals - -- No new standalone "edit all accounts" route that ignores filters. -- No new dedicated "edit group" route separate from list filters. -- No change to the backend merge semantics for other bulk-edit fields. -- No attempt in this change to refactor all account form components into a shared schema system. - -## Current State - -### Bulk edit entry - -The account list currently exposes bulk edit only through selected-row actions. `AccountsView.vue` passes `selIds`, `selPlatforms`, and `selTypes` into `BulkEditAccountModal.vue`. - -### Filter state - -The account page already keeps a central `params` object for current filters and reloads the table from that state. Group filtering already exists in `AccountTableFilters.vue`. - -### Bulk edit payload - -`BulkEditAccountModal.vue` builds a bulk update request around explicit account IDs. - -### OpenAI field gap - -Single-account create/edit already supports: - -- `openai_passthrough` -- OAuth WS mode -- API key WS mode -- OAuth `codex_cli_only` - -Bulk edit currently supports: - -- `openai_passthrough` -- OAuth WS mode only - -That leaves a real capability gap for operators managing large OpenAI account sets. - -## User Experience - -### Entry point - -Use one compact `Bulk edit` dropdown button in the table-level bulk actions area above the grid. - -The dropdown contains: - -- `Bulk edit selected accounts` -- `Bulk edit current filtered results` - -Behavior: - -- If there is no row selection, the `selected accounts` action is disabled. -- `Current filtered results` is always available. -- The existing separate immediate `Edit` action in the selected-row bar is replaced by this unified dropdown to avoid duplicate buttons that mean different scopes. - -### Modal scope messaging - -The bulk edit modal gets a required scope descriptor prop. - -For `selected accounts`: - -- show the existing count-based info banner -- keep using explicit selected account metadata for platform/type compatibility checks - -For `current filtered results`: - -- show a banner stating that edits apply to the current filtered result set -- show the matched account count from a preview query -- show a short summary of active filters when practical, especially group/search/platform/type/status filters - -### Safety - -For filtered-result mode: - -- disable submit if the preview count is `0` -- refresh the target count when the modal opens -- keep the final success toast count aligned with the backend result - -The modal should not silently fall back from filtered mode to selected mode. - -## Backend/API Design - -### Request model - -Extend bulk update to support two target modes: - -- explicit IDs -- filter-based query - -The request shape should keep backward compatibility for the selected-ID path while allowing a filter target. The backend handler can accept a payload that contains either: - -- `account_ids` -- or `filters` - -but not neither. - -The `filters` payload should reuse the existing account-list query semantics already used by `/admin/accounts` and `/admin/accounts/data`, including: - -- `search` -- `platform` -- `type` -- `status` -- `privacy_mode` -- `group` -- existing sort fields may be ignored for mutation targeting if not needed - -### Preview count - -The frontend needs an accurate target count before submit in filtered-result mode. The simplest compatible approach is: - -- call the existing account list endpoint with the current filters and a minimal page size strategy sufficient to obtain total count - -If the current API makes that awkward, add a narrow preview/count helper for bulk edit target resolution. Prefer reusing the existing listing contract first. - -### Target resolution - -For filtered-result mode, the backend must resolve matching account IDs server-side from the submitted filters rather than trusting only currently loaded page data. This is required so filtered-result mode can act on the full result set across pagination. - -### Compatibility metadata - -The frontend still needs platform/type compatibility to determine which fields to show. For filtered-result mode, derive this from the preview result set returned from the same query used to show count. If the preview spans mixed incompatible account types, show the same warnings/conditional UI that selected mode already uses. - -## Frontend Design - -### Accounts view - -`AccountsView.vue` will: - -- replace the direct selected-only bulk edit trigger with a dropdown action model -- keep a reactive description of the pending bulk edit scope -- pass either selected IDs or current filter params into the modal - -The "current filtered results" action uses the live `params` object snapshot at open time, not a mutable live subscription while the modal is already open. - -### Bulk edit modal - -`BulkEditAccountModal.vue` will accept a richer target contract, for example: - -- target mode -- selected IDs or filter snapshot -- preview count -- preview platform/type coverage if needed - -The modal remains one form; only the scope banner and submission target differ. - -### OpenAI field alignment - -Add the missing OpenAI controls to bulk edit: - -- OAuth `codex_cli_only` -- API key WS mode selector - -Rules: - -- OAuth accounts show OAuth WS mode and `codex_cli_only` -- API key accounts show API key WS mode -- mixed OpenAI OAuth/API key selections continue to show only fields that are safe for the entire target set - -The payload builder must write: - -- `extra.codex_cli_only` -- `extra.openai_apikey_responses_websockets_v2_mode` -- `extra.openai_apikey_responses_websockets_v2_enabled` - -with the same enable/disable semantics already used by single-account forms. - -## Testing Strategy - -### Frontend tests - -Add or extend tests for: - -- bulk edit dropdown actions in the accounts view -- selected-account mode still calling bulk update by IDs -- filtered-result mode calling bulk update with filter target -- filtered-result mode showing preview count and blocking submit on zero matches -- OAuth bulk edit supporting `codex_cli_only` -- API key bulk edit supporting API key WS mode -- no regression for existing passthrough and OAuth WS mode tests - -### Backend tests - -Add or extend tests for: - -- bulk update request validation for IDs vs filters -- filtered-result mode resolving all matching accounts across pagination semantics -- mixed-channel risk checks still running for filter-target updates if applicable -- backward compatibility for the existing selected-ID request path - -## Risks - -- Filter semantics can drift if bulk edit reimplements list-filter parsing differently from the listing endpoints. -- Filtered-result mode can surprise users if the active scope is not shown clearly enough. -- Large filtered updates may affect many rows; success/error messaging must stay explicit. - -## Recommendation - -Implement this as a targeted extension of the existing bulk edit flow: - -- unify the entry point in the table action area -- add filter-target bulk update support -- align the missing OpenAI compact-related fields - -This keeps the mental model simple and solves the large-account-management pain without introducing a second parallel batch-edit system.