Files
2026-05-27 23:29:53 +01:00

3.9 KiB

OpenSpec Change: enterprise-api-plugin-admin

  • Change ID: enterprise-api-plugin-admin
  • Package: @suaveplan/api-plugin-admin
  • Category: api/auth
  • Target path: api/auth/api-plugin-admin
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/api-plugin-admin.md

Summary

Deliver @suaveplan/api-plugin-admin on the genesis branch from scratch at enterprise quality. The plugin mounts an admin-panel API under five route groups (/admin/users, /admin/sites, /admin/stats, /admin/posts, /admin/audit) behind requireAuth() + requireRole("ADMIN") from @suaveplan/api-plugin-auth. Backing AdminService owns user moderation (suspend/ban/promote/demote), post moderation, site metadata, stats, and audit queries against SurrealDB. Domain events (admin:action:performed) emitted via proper AdminEventMap declaration — no method rebinding, no export * from "@suaveplan/api-schemas", no @ts-expect-error.


Current-state audit (genesis)

Package does not exist on genesis — fresh build. Reference: /mnt/s/web/suaveplan/enterprise/api-plugin-admin.md.


Available workspace deps on genesis

Package Role
@suaveplan/api (workspace:^) definePlugin
@suaveplan/api-shared (workspace:^) Response helpers, middleware
@suaveplan/api-plugin-auth (workspace:^) requireAuth, requireRole
@suaveplan/api-plugin-database (workspace:^) SurrealDB access
@suaveplan/api-schemas (workspace:^) Imported types (never re-exported)
@suaveplan/audit-logging (workspace:^) Audit-log queries + writes
@suaveplan/events (workspace:^) Typed event bus
@suaveplan/logger (workspace:^) Structured logging
@suaveplan/rate-limiter (workspace:^) Rate limits on destructive actions
@suaveplan/error (workspace:^) AdminError hierarchy
hono + @hono/zod-openapi (catalog:server) Routes
zod (catalog:forms) Schemas
@opentelemetry/api (catalog:observability) OTel

Public API surface

function createAdminPlugin(config?: AdminConfig): PluginDescriptor<AdminConfig>
class AdminService {
  suspendUser(userId: string, reason: string): Promise<void>
  banUser(userId: string, reason: string): Promise<void>
  promoteUser(userId: string, role: string): Promise<void>
  demoteUser(userId: string, role: string): Promise<void>
  approvePost(postId: string): Promise<void>
  removePost(postId: string, reason: string): Promise<void>
  getSiteMetadata(siteId: string): Promise<SiteMetadata>
  getStats(): Promise<AdminStats>
  queryAuditLog(query: AuditQuery): Promise<AuditEntry[]>
}
interface AdminConfig { basePath?: string; requireRole?: string }
interface AdminActionPerformedEvent { action: string; targetId: string; performedBy: string; reason?: string }

Error codes

type AdminErrorCode =
  | "ADMIN_USER_NOT_FOUND"
  | "ADMIN_ACTION_FORBIDDEN"
  | "ADMIN_INVALID_ROLE"
  | "ADMIN_SITE_NOT_FOUND"

Genesis additions vs main-branch

  1. Proper AdminEventMap declared in src/events.ts (module augmentation) — no @ts-expect-error, no method rebinding.
  2. Remove export * from "@suaveplan/api-schemas" — import specific types only.
  3. Rate limiting on all destructive admin endpoints.
  4. Integration tests against real SurrealDB.
  5. OTel spans on every AdminService method.

File layout

api/auth/api-plugin-admin/
  package.json  tsconfig.json  vitest.config.ts
  surql/  (admin tables)
  src/
    index.ts  events.ts
    types/  errors/
    services/admin/
    routes/users/ routes/sites/ routes/stats/ routes/posts/ routes/audit/
    middleware/
  tests/integration.test.ts

Impact

Prerequisites: @suaveplan/api, @suaveplan/api-shared, @suaveplan/api-plugin-auth, @suaveplan/api-plugin-database, @suaveplan/audit-logging, @suaveplan/events.