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
- Proper
AdminEventMapdeclared insrc/events.ts(module augmentation) — no@ts-expect-error, no method rebinding. - Remove
export * from "@suaveplan/api-schemas"— import specific types only. - Rate limiting on all destructive admin endpoints.
- Integration tests against real SurrealDB.
- OTel spans on every
AdminServicemethod.
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.