# Tasks: enterprise-api-plugin-admin **Change ID**: enterprise-api-plugin-admin **Package**: `@suaveplan/api-plugin-admin` **Target path**: `api/auth/api-plugin-admin` **Prerequisite packages on Verdaccio**: `@suaveplan/api`, `@suaveplan/api-shared`, `@suaveplan/api-plugin-auth`, `@suaveplan/api-plugin-database`, `@suaveplan/audit-logging`, `@suaveplan/events`, `@suaveplan/rate-limiter`, `@suaveplan/error`, `@suaveplan/logger` --- ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] Create `api/auth/api-plugin-admin/` with all subdirs. - [ ] `package.json` v0.0.0, `"sideEffects": ["src/events.ts"]`, subpath exports. - [ ] `tsconfig.json` + `vitest.config.ts`. - [ ] Scripts: `lint`, `typecheck`, `test`, `test:coverage`, `test:with-db`, `build`, `docs:check`. --- ## 2. Types and errors - [ ] `src/types/` — `AdminConfig`, `AdminConfigSchema` (Zod), `SiteMetadata`, `AdminStats`, `AuditQuery`, `AuditEntry`. - [ ] `src/errors/admin-errors.ts` — 4-code `AdminErrorCode` union, metadata, registration. - [ ] `admin-errors.test.ts` + `admin-errors.md`. --- ## 3. Events - [ ] `src/events.ts` — module augmentation declaring `AdminEventMap` (`admin:action:performed`) on global event bus. Export `AdminActionPerformedEvent` interface. - [ ] No `as any` casts, no `@ts-expect-error`. --- ## 4. SurrealQL migrations - [ ] `surql/admin_action.surql`, `surql/admin_ban.surql` — DEFINE TABLE + DEFINE FIELD + tenantId indexes. --- ## 5. AdminService - [ ] Implement all methods listed in proposal: suspendUser, banUser, promoteUser, demoteUser, approvePost, removePost, getSiteMetadata, getStats, queryAuditLog. - [ ] Each state-changing method: emit `admin:action:performed` via `ctx.eventBus.emit(...)` (typed, no cast); write audit entry via `@suaveplan/audit-logging`. - [ ] OTel span per method. - [ ] `admin.service.test.ts` (≤500 lines): each method happy path + not-found throws + forbidden throws. - [ ] `admin.service.md`. --- ## 6. Routes (each with `.test.ts` + `.md`) - [ ] `/admin/users` — list, get, suspend, ban, promote, demote (all behind `requireAuth()` + `requireRole("ADMIN")`). - [ ] `/admin/sites` — list, get, update site metadata. - [ ] `/admin/stats` — GET dashboard stats. - [ ] `/admin/posts` — list moderation queue, approve, remove. - [ ] `/admin/audit` — paginated audit log query. - [ ] Rate limiting on all destructive endpoints. - [ ] OpenAPI tags + descriptions on every route. - [ ] Import specific types from `@suaveplan/api-schemas`; no `export *` pass-through. --- ## 7. Plugin factory - [ ] `createAdminPlugin(config?)`: `definePlugin` with `dependencies: ["database", "auth"]`, `migrationsPath: "./surql"`. - [ ] `onInit`: instantiate `AdminService`, register via `ctx.registerService("admin", adminService)`. - [ ] `onClose`: no-op (no listeners to detach for this plugin). - [ ] `onTenantCreate` / `onTenantDelete`: bootstrap/teardown admin namespace in SurrealDB. --- ## 8. Integration tests (`tests/integration.test.ts`) - [ ] Suspend user → user cannot login → reinstate → login succeeds (against real SurrealDB via `test:with-db`). - [ ] Admin action emits event on bus. - [ ] Non-admin role → 403. --- ## 9. Verify and publish - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-admin` — green. - [ ] `bunx turbo test:coverage --filter=@suaveplan/api-plugin-admin` — 100%. - [ ] No `@ts-expect-error`, `export *` of external deps, method rebinding, or `.skip`. - [ ] `bun scripts/publish.ts --package @suaveplan/api-plugin-admin`. - [ ] Archive → `openspec/archive/2026-04-24-enterprise-api-plugin-admin/`.