4.2 KiB
4.2 KiB
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 statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin 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.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create
api/auth/api-plugin-admin/with all subdirs. package.jsonv0.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-codeAdminErrorCodeunion, metadata, registration.admin-errors.test.ts+admin-errors.md.
3. Events
src/events.ts— module augmentation declaringAdminEventMap(admin:action:performed) on global event bus. ExportAdminActionPerformedEventinterface.- No
as anycasts, 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:performedviactx.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 behindrequireAuth()+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; noexport *pass-through.
7. Plugin factory
createAdminPlugin(config?):definePluginwithdependencies: ["database", "auth"],migrationsPath: "./surql".onInit: instantiateAdminService, register viactx.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/.