Files
suaveplan/openspec/archive/2026-05-18-add-api-plugin-user/tasks.md
2026-05-27 23:29:53 +01:00

3.6 KiB

Tasks — add-api-plugin-user

1. Scaffold

  • 1.1 Create packages/api/api-plugin-user/ with src/{plugin,routes,services,schemas,schema,error-codes,otel,types}/ + tests/{setup,integration}/
  • 1.2 package.json v0.1.0. Deps: @suaveplan/api-plugin @suaveplan/api-openapi @suaveplan/api-migrations @suaveplan/api-plugin-auth @suaveplan/error @suaveplan/types tslib, hono @hono/zod-openapi (catalog:server), zod (catalog:forms), @opentelemetry/api
  • 1.3 10 subpath exports per the proposal
  • 1.4 tsconfigs + vite + vitest (100/100/100/100, testTimeout 60000 for integration)
  • 1.5 tests/setup/polyfills.ts

2. Implementation

  • 2.1 src/error-codes.{ts,test.ts,md,index.ts} — 7 USER.* codes + UserError
  • 2.2 src/types/types.{ts,md,index.ts} — UserProfile, UserPluginOptions, UserPluginConfig
  • 2.3 src/schemas/options.{ts,test.ts,md,index.ts} — UserPluginOptionsSchema
  • 2.4 src/schemas/user-profile.{ts,test.ts,md,index.ts} — UserProfileSchema (extends PrincipalSchema from @suaveplan/api-plugin-auth/schemas/principal), UserProfileResponseSchema, UpdateUserProfileBodySchema (strict mode)
  • 2.5 src/otel/instruments.{ts,test.ts,md,index.ts} — 3 counters
  • 2.6 src/schema/schema.{ts,test.ts,md,index.ts} — USER_PROFILE_SCHEMA template + applyUserProfileSchema(adapter, profileFields) helper. Genesis-original DDL using DEFINE FIELD OVERWRITE on the user table.
  • 2.7 src/services/user-service.{ts,test.ts,md,index.ts} — UserService interface + impl; ServiceRegistry augmentation
  • 2.8 src/routes/build-routes.{ts,test.ts,md,index.ts} — buildUserRoutes(authService) returning 3 PluginRouteEntry via RouteBuilder; all use requireAuth() upstream
  • 2.9 src/plugin/plugin.{ts,test.ts,md,index.ts} — createUserPlugin(options) factory; dependencies: ["auth"]; onInit applies schema → registers userService → registers routes
  • 2.10 src/index.ts — named re-exports only

3. Tests

  • 3.1 Co-located *.test.ts per spec scenario
  • 3.2 src/api-plugin-user.spec-conformance.test.ts — every USER.* code thrown; expectTypeOf on UserService; UpdateUserProfileBodySchema strict-mode pinned
  • 3.3 tests/integration/full-boot.test.ts — real PluginRegistry + api-plugin-auth + this plugin + SurrealDB testcontainer; sign-up → GET /users/me → PATCH → DELETE roundtrip
  • 3.4 tests/integration/openapi-doc.test.ts — served /openapi.json includes 3 /users/me routes with Zod-typed schemas
  • 3.5 tests/property.test.ts — fast-check 200 runs on UpdateUserProfileBodySchema: arbitrary keysets including extras → strict-mode rejects when extras present
  • 3.6 tests/dep-graph.test.ts
  • 3.7 All tests via @suaveplan/testing/runner, { timeout: 5000 } (60000 for integration)

4. Documentation

  • 4.1 Sibling .md per impl (≥200 words)
  • 4.2 README.md — install + defineApp().use(createAuthPlugin(...)).use(createUserPlugin(...)) example; userService.getById usage from downstream plugins; profileFields customisation; schema apply notes

5. Gates

  • 5.1 bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-user --force
  • 5.2 Coverage 100/100/100/100
  • 5.3 bun scripts/openspec-conformance.ts @suaveplan/api-plugin-user exit 0
  • 5.4 Build green
  • 5.5 Banned-pattern + no export * + no direct runner imports

6. Archive

  • 6.1 Fold spec → openspec/specs/api-plugin-user/spec.md
  • 6.2 mv change → openspec/archive/<date>-add-api-plugin-user/
  • 6.3 DO NOT refresh MANIFEST or STATUS — orchestrator consolidates