@sixthsummit/ship-api 0.0.0-stage → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +605 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +58 -2
- package/cli/commands/add.js +537 -0
- package/cli/commands/contract.js +2 -0
- package/cli/commands/create.js +250 -0
- package/cli/commands/dev.js +227 -0
- package/cli/commands/doctor.js +286 -0
- package/cli/commands/generate.js +937 -0
- package/cli/commands/graph.js +2 -0
- package/cli/commands/migrate-orm.js +1171 -0
- package/cli/commands/update.js +37 -0
- package/cli/ship-api.js +285 -0
- package/lib/app/auth/AuthProvider.d.ts +91 -0
- package/lib/app/auth/AuthProvider.d.ts.map +1 -0
- package/lib/app/auth/AuthProvider.js +13 -0
- package/lib/app/auth/AuthProvider.js.map +1 -0
- package/lib/app/auth/adapters/firebase.d.ts +79 -0
- package/lib/app/auth/adapters/firebase.d.ts.map +1 -0
- package/lib/app/auth/adapters/firebase.js +122 -0
- package/lib/app/auth/adapters/firebase.js.map +1 -0
- package/lib/app/auth/adapters/jwtCookie.d.ts +55 -0
- package/lib/app/auth/adapters/jwtCookie.d.ts.map +1 -0
- package/lib/app/auth/adapters/jwtCookie.js +120 -0
- package/lib/app/auth/adapters/jwtCookie.js.map +1 -0
- package/lib/app/auth/index.d.ts +8 -0
- package/lib/app/auth/index.d.ts.map +1 -0
- package/lib/app/auth/index.js +7 -0
- package/lib/app/auth/index.js.map +1 -0
- package/lib/app/auth/jwt/AuthFlow.d.ts +94 -0
- package/lib/app/auth/jwt/AuthFlow.d.ts.map +1 -0
- package/lib/app/auth/jwt/AuthFlow.js +127 -0
- package/lib/app/auth/jwt/AuthFlow.js.map +1 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts +80 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts.map +1 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js +134 -0
- package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js.map +1 -0
- package/lib/app/auth/jwt/JwtSigner.d.ts +123 -0
- package/lib/app/auth/jwt/JwtSigner.d.ts.map +1 -0
- package/lib/app/auth/jwt/JwtSigner.js +118 -0
- package/lib/app/auth/jwt/JwtSigner.js.map +1 -0
- package/lib/app/auth/jwt/RefreshTokenStore.d.ts +97 -0
- package/lib/app/auth/jwt/RefreshTokenStore.d.ts.map +1 -0
- package/lib/app/auth/jwt/RefreshTokenStore.js +122 -0
- package/lib/app/auth/jwt/RefreshTokenStore.js.map +1 -0
- package/lib/app/auth/permissionDefinition.d.ts +20 -0
- package/lib/app/auth/permissionDefinition.d.ts.map +1 -0
- package/lib/app/auth/permissionDefinition.js +2 -0
- package/lib/app/auth/permissionDefinition.js.map +1 -0
- package/lib/app/context/RequestContext.d.ts +59 -0
- package/lib/app/context/RequestContext.d.ts.map +1 -0
- package/lib/app/context/RequestContext.js +25 -0
- package/lib/app/context/RequestContext.js.map +1 -0
- package/lib/app/db/QueryOptions.d.ts +82 -0
- package/lib/app/db/QueryOptions.d.ts.map +1 -0
- package/lib/app/db/QueryOptions.js +37 -0
- package/lib/app/db/QueryOptions.js.map +1 -0
- package/lib/app/db/baseFields.d.ts +60 -0
- package/lib/app/db/baseFields.d.ts.map +1 -0
- package/lib/app/db/baseFields.js +54 -0
- package/lib/app/db/baseFields.js.map +1 -0
- package/lib/app/db/buildWhere.d.ts +22 -0
- package/lib/app/db/buildWhere.d.ts.map +1 -0
- package/lib/app/db/buildWhere.js +75 -0
- package/lib/app/db/buildWhere.js.map +1 -0
- package/lib/app/db/client.d.ts +111 -0
- package/lib/app/db/client.d.ts.map +1 -0
- package/lib/app/db/client.js +99 -0
- package/lib/app/db/client.js.map +1 -0
- package/lib/app/db/tenantScoped.d.ts +59 -0
- package/lib/app/db/tenantScoped.d.ts.map +1 -0
- package/lib/app/db/tenantScoped.js +54 -0
- package/lib/app/db/tenantScoped.js.map +1 -0
- package/lib/app/db/transaction.d.ts +58 -0
- package/lib/app/db/transaction.d.ts.map +1 -0
- package/lib/app/db/transaction.js +106 -0
- package/lib/app/db/transaction.js.map +1 -0
- package/lib/app/health/HealthCheck.d.ts +121 -0
- package/lib/app/health/HealthCheck.d.ts.map +1 -0
- package/lib/app/health/HealthCheck.js +151 -0
- package/lib/app/health/HealthCheck.js.map +1 -0
- package/lib/app/health/redisHealthCheck.d.ts +14 -0
- package/lib/app/health/redisHealthCheck.d.ts.map +1 -0
- package/lib/app/health/redisHealthCheck.js +21 -0
- package/lib/app/health/redisHealthCheck.js.map +1 -0
- package/lib/app/lifecycle/Bootstrapper.d.ts +92 -0
- package/lib/app/lifecycle/Bootstrapper.d.ts.map +1 -0
- package/lib/app/lifecycle/Bootstrapper.js +99 -0
- package/lib/app/lifecycle/Bootstrapper.js.map +1 -0
- package/lib/app/registry/routes.d.ts +89 -0
- package/lib/app/registry/routes.d.ts.map +1 -0
- package/lib/app/registry/routes.js +72 -0
- package/lib/app/registry/routes.js.map +1 -0
- package/lib/app/services/DrizzleEntityService.d.ts +123 -0
- package/lib/app/services/DrizzleEntityService.d.ts.map +1 -0
- package/lib/app/services/DrizzleEntityService.js +342 -0
- package/lib/app/services/DrizzleEntityService.js.map +1 -0
- package/lib/app/services/RedisProvider.d.ts +52 -0
- package/lib/app/services/RedisProvider.d.ts.map +1 -0
- package/lib/app/services/RedisProvider.js +75 -0
- package/lib/app/services/RedisProvider.js.map +1 -0
- package/lib/app/services/cache/Cache.d.ts +70 -0
- package/lib/app/services/cache/Cache.d.ts.map +1 -0
- package/lib/app/services/cache/Cache.js +18 -0
- package/lib/app/services/cache/Cache.js.map +1 -0
- package/lib/app/services/cache/InMemoryCache.d.ts +35 -0
- package/lib/app/services/cache/InMemoryCache.d.ts.map +1 -0
- package/lib/app/services/cache/InMemoryCache.js +76 -0
- package/lib/app/services/cache/InMemoryCache.js.map +1 -0
- package/lib/app/services/cache/RedisCache.d.ts +99 -0
- package/lib/app/services/cache/RedisCache.d.ts.map +1 -0
- package/lib/app/services/cache/RedisCache.js +150 -0
- package/lib/app/services/cache/RedisCache.js.map +1 -0
- package/lib/app/services/cache/cached.d.ts +30 -0
- package/lib/app/services/cache/cached.d.ts.map +1 -0
- package/lib/app/services/cache/cached.js +38 -0
- package/lib/app/services/cache/cached.js.map +1 -0
- package/lib/app/services/cache/index.d.ts +5 -0
- package/lib/app/services/cache/index.d.ts.map +1 -0
- package/lib/app/services/cache/index.js +4 -0
- package/lib/app/services/cache/index.js.map +1 -0
- package/lib/app/services/cron/defineCron.d.ts +57 -0
- package/lib/app/services/cron/defineCron.d.ts.map +1 -0
- package/lib/app/services/cron/defineCron.js +15 -0
- package/lib/app/services/cron/defineCron.js.map +1 -0
- package/lib/app/services/cron/index.d.ts +2 -0
- package/lib/app/services/cron/index.d.ts.map +1 -0
- package/lib/app/services/cron/index.js +2 -0
- package/lib/app/services/cron/index.js.map +1 -0
- package/lib/app/services/hooks/LifecycleHooks.d.ts +61 -0
- package/lib/app/services/hooks/LifecycleHooks.d.ts.map +1 -0
- package/lib/app/services/hooks/LifecycleHooks.js +85 -0
- package/lib/app/services/hooks/LifecycleHooks.js.map +1 -0
- package/lib/app/services/jobs/JobsManager.d.ts +67 -0
- package/lib/app/services/jobs/JobsManager.d.ts.map +1 -0
- package/lib/app/services/jobs/JobsManager.js +121 -0
- package/lib/app/services/jobs/JobsManager.js.map +1 -0
- package/lib/app/services/jobs/bullBoard.d.ts +72 -0
- package/lib/app/services/jobs/bullBoard.d.ts.map +1 -0
- package/lib/app/services/jobs/bullBoard.js +96 -0
- package/lib/app/services/jobs/bullBoard.js.map +1 -0
- package/lib/app/services/jobs/defineJob.d.ts +81 -0
- package/lib/app/services/jobs/defineJob.d.ts.map +1 -0
- package/lib/app/services/jobs/defineJob.js +49 -0
- package/lib/app/services/jobs/defineJob.js.map +1 -0
- package/lib/app/services/jobs/index.d.ts +4 -0
- package/lib/app/services/jobs/index.d.ts.map +1 -0
- package/lib/app/services/jobs/index.js +4 -0
- package/lib/app/services/jobs/index.js.map +1 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts +23 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js +51 -0
- package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js.map +1 -0
- package/lib/app/services/rateLimit/RateLimitBackend.d.ts +41 -0
- package/lib/app/services/rateLimit/RateLimitBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/RateLimitBackend.js +19 -0
- package/lib/app/services/rateLimit/RateLimitBackend.js.map +1 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts +16 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts.map +1 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js +80 -0
- package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js.map +1 -0
- package/lib/app/services/rateLimit/index.d.ts +4 -0
- package/lib/app/services/rateLimit/index.d.ts.map +1 -0
- package/lib/app/services/rateLimit/index.js +3 -0
- package/lib/app/services/rateLimit/index.js.map +1 -0
- package/lib/app/services/storage/DiskStorageAdapter.d.ts +62 -0
- package/lib/app/services/storage/DiskStorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/DiskStorageAdapter.js +295 -0
- package/lib/app/services/storage/DiskStorageAdapter.js.map +1 -0
- package/lib/app/services/storage/GCSStorageAdapter.d.ts +44 -0
- package/lib/app/services/storage/GCSStorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/GCSStorageAdapter.js +133 -0
- package/lib/app/services/storage/GCSStorageAdapter.js.map +1 -0
- package/lib/app/services/storage/S3StorageAdapter.d.ts +57 -0
- package/lib/app/services/storage/S3StorageAdapter.d.ts.map +1 -0
- package/lib/app/services/storage/S3StorageAdapter.js +162 -0
- package/lib/app/services/storage/S3StorageAdapter.js.map +1 -0
- package/lib/app/services/storage/StorageService.d.ts +88 -0
- package/lib/app/services/storage/StorageService.d.ts.map +1 -0
- package/lib/app/services/storage/StorageService.js +18 -0
- package/lib/app/services/storage/StorageService.js.map +1 -0
- package/lib/app/services/storage/index.d.ts +5 -0
- package/lib/app/services/storage/index.d.ts.map +1 -0
- package/lib/app/services/storage/index.js +4 -0
- package/lib/app/services/storage/index.js.map +1 -0
- package/lib/app/utils/ContextValidators.d.ts +46 -0
- package/lib/app/utils/ContextValidators.d.ts.map +1 -0
- package/lib/app/utils/ContextValidators.js +81 -0
- package/lib/app/utils/ContextValidators.js.map +1 -0
- package/lib/app/utils/defineEnv.d.ts +80 -0
- package/lib/app/utils/defineEnv.d.ts.map +1 -0
- package/lib/app/utils/defineEnv.js +95 -0
- package/lib/app/utils/defineEnv.js.map +1 -0
- package/lib/client.d.ts +139 -0
- package/lib/client.d.ts.map +1 -0
- package/lib/client.js +98 -0
- package/lib/client.js.map +1 -0
- package/lib/contract/application.d.ts +3 -0
- package/lib/contract/application.d.ts.map +1 -0
- package/lib/contract/application.js +2 -0
- package/lib/contract/application.js.map +1 -0
- package/lib/contract/client.d.ts +3 -0
- package/lib/contract/client.d.ts.map +1 -0
- package/lib/contract/client.js +3 -0
- package/lib/contract/client.js.map +1 -0
- package/lib/contract/index.d.ts +3 -0
- package/lib/contract/index.d.ts.map +1 -0
- package/lib/contract/index.js +3 -0
- package/lib/contract/index.js.map +1 -0
- package/lib/contract/manifest.d.ts +3 -0
- package/lib/contract/manifest.d.ts.map +1 -0
- package/lib/contract/manifest.js +2 -0
- package/lib/contract/manifest.js.map +1 -0
- package/lib/contract/openapi.d.ts +3 -0
- package/lib/contract/openapi.d.ts.map +1 -0
- package/lib/contract/openapi.js +3 -0
- package/lib/contract/openapi.js.map +1 -0
- package/lib/contract/project.d.ts +3 -0
- package/lib/contract/project.d.ts.map +1 -0
- package/lib/contract/project.js +3 -0
- package/lib/contract/project.js.map +1 -0
- package/lib/contract/schema.d.ts +3 -0
- package/lib/contract/schema.d.ts.map +1 -0
- package/lib/contract/schema.js +3 -0
- package/lib/contract/schema.js.map +1 -0
- package/lib/drizzle/index.d.ts +3 -0
- package/lib/drizzle/index.d.ts.map +1 -0
- package/lib/drizzle/index.js +3 -0
- package/lib/drizzle/index.js.map +1 -0
- package/lib/hono/auth.d.ts +6 -0
- package/lib/hono/auth.d.ts.map +1 -0
- package/lib/hono/auth.js +54 -0
- package/lib/hono/auth.js.map +1 -0
- package/lib/hono/index.d.ts +4 -0
- package/lib/hono/index.d.ts.map +1 -0
- package/lib/hono/index.js +4 -0
- package/lib/hono/index.js.map +1 -0
- package/lib/http/app/createApp.d.ts +132 -0
- package/lib/http/app/createApp.d.ts.map +1 -0
- package/lib/http/app/createApp.js +215 -0
- package/lib/http/app/createApp.js.map +1 -0
- package/lib/http/app/devRoutes.d.ts +31 -0
- package/lib/http/app/devRoutes.d.ts.map +1 -0
- package/lib/http/app/devRoutes.js +145 -0
- package/lib/http/app/devRoutes.js.map +1 -0
- package/lib/http/app/errors.d.ts +45 -0
- package/lib/http/app/errors.d.ts.map +1 -0
- package/lib/http/app/errors.js +93 -0
- package/lib/http/app/errors.js.map +1 -0
- package/lib/http/app/health.d.ts +66 -0
- package/lib/http/app/health.d.ts.map +1 -0
- package/lib/http/app/health.js +104 -0
- package/lib/http/app/health.js.map +1 -0
- package/lib/http/errors/AppError.d.ts +10 -0
- package/lib/http/errors/AppError.d.ts.map +1 -0
- package/lib/http/errors/AppError.js +19 -0
- package/lib/http/errors/AppError.js.map +1 -0
- package/lib/http/errors/AuthenticationError.d.ts +8 -0
- package/lib/http/errors/AuthenticationError.d.ts.map +1 -0
- package/lib/http/errors/AuthenticationError.js +10 -0
- package/lib/http/errors/AuthenticationError.js.map +1 -0
- package/lib/http/errors/AuthorizationError.d.ts +8 -0
- package/lib/http/errors/AuthorizationError.d.ts.map +1 -0
- package/lib/http/errors/AuthorizationError.js +10 -0
- package/lib/http/errors/AuthorizationError.js.map +1 -0
- package/lib/http/errors/BadRequestError.d.ts +8 -0
- package/lib/http/errors/BadRequestError.d.ts.map +1 -0
- package/lib/http/errors/BadRequestError.js +10 -0
- package/lib/http/errors/BadRequestError.js.map +1 -0
- package/lib/http/errors/ConflictError.d.ts +8 -0
- package/lib/http/errors/ConflictError.d.ts.map +1 -0
- package/lib/http/errors/ConflictError.js +10 -0
- package/lib/http/errors/ConflictError.js.map +1 -0
- package/lib/http/errors/InternalServerError.d.ts +8 -0
- package/lib/http/errors/InternalServerError.d.ts.map +1 -0
- package/lib/http/errors/InternalServerError.js +10 -0
- package/lib/http/errors/InternalServerError.js.map +1 -0
- package/lib/http/errors/NotFoundError.d.ts +8 -0
- package/lib/http/errors/NotFoundError.d.ts.map +1 -0
- package/lib/http/errors/NotFoundError.js +10 -0
- package/lib/http/errors/NotFoundError.js.map +1 -0
- package/lib/http/errors/RateLimitError.d.ts +13 -0
- package/lib/http/errors/RateLimitError.d.ts.map +1 -0
- package/lib/http/errors/RateLimitError.js +16 -0
- package/lib/http/errors/RateLimitError.js.map +1 -0
- package/lib/http/errors/ServiceUnavailableError.d.ts +8 -0
- package/lib/http/errors/ServiceUnavailableError.d.ts.map +1 -0
- package/lib/http/errors/ServiceUnavailableError.js +10 -0
- package/lib/http/errors/ServiceUnavailableError.js.map +1 -0
- package/lib/http/errors/ValidationError.d.ts +9 -0
- package/lib/http/errors/ValidationError.d.ts.map +1 -0
- package/lib/http/errors/ValidationError.js +12 -0
- package/lib/http/errors/ValidationError.js.map +1 -0
- package/lib/http/errors/index.d.ts +11 -0
- package/lib/http/errors/index.d.ts.map +1 -0
- package/lib/http/errors/index.js +12 -0
- package/lib/http/errors/index.js.map +1 -0
- package/lib/http/middleware/apiKey.d.ts +9 -0
- package/lib/http/middleware/apiKey.d.ts.map +1 -0
- package/lib/http/middleware/apiKey.js +71 -0
- package/lib/http/middleware/apiKey.js.map +1 -0
- package/lib/http/middleware/csrf.d.ts +63 -0
- package/lib/http/middleware/csrf.d.ts.map +1 -0
- package/lib/http/middleware/csrf.js +169 -0
- package/lib/http/middleware/csrf.js.map +1 -0
- package/lib/http/middleware/httpLogger.d.ts +39 -0
- package/lib/http/middleware/httpLogger.d.ts.map +1 -0
- package/lib/http/middleware/httpLogger.js +118 -0
- package/lib/http/middleware/httpLogger.js.map +1 -0
- package/lib/http/middleware/idempotency.d.ts +48 -0
- package/lib/http/middleware/idempotency.d.ts.map +1 -0
- package/lib/http/middleware/idempotency.js +180 -0
- package/lib/http/middleware/idempotency.js.map +1 -0
- package/lib/http/middleware/rateLimit.d.ts +105 -0
- package/lib/http/middleware/rateLimit.d.ts.map +1 -0
- package/lib/http/middleware/rateLimit.js +84 -0
- package/lib/http/middleware/rateLimit.js.map +1 -0
- package/lib/http/middleware/requireAuth.d.ts +58 -0
- package/lib/http/middleware/requireAuth.d.ts.map +1 -0
- package/lib/http/middleware/requireAuth.js +63 -0
- package/lib/http/middleware/requireAuth.js.map +1 -0
- package/lib/http/middleware/requirePermission.d.ts +23 -0
- package/lib/http/middleware/requirePermission.d.ts.map +1 -0
- package/lib/http/middleware/requirePermission.js +50 -0
- package/lib/http/middleware/requirePermission.js.map +1 -0
- package/lib/http/middleware/resolveTenant.d.ts +41 -0
- package/lib/http/middleware/resolveTenant.d.ts.map +1 -0
- package/lib/http/middleware/resolveTenant.js +17 -0
- package/lib/http/middleware/resolveTenant.js.map +1 -0
- package/lib/http/streaming/sse.d.ts +31 -0
- package/lib/http/streaming/sse.d.ts.map +1 -0
- package/lib/http/streaming/sse.js +11 -0
- package/lib/http/streaming/sse.js.map +1 -0
- package/lib/http/streaming/streamLLM.d.ts +94 -0
- package/lib/http/streaming/streamLLM.d.ts.map +1 -0
- package/lib/http/streaming/streamLLM.js +94 -0
- package/lib/http/streaming/streamLLM.js.map +1 -0
- package/lib/http/utils/authCookies.d.ts +74 -0
- package/lib/http/utils/authCookies.d.ts.map +1 -0
- package/lib/http/utils/authCookies.js +102 -0
- package/lib/http/utils/authCookies.js.map +1 -0
- package/lib/http/utils/clientIp.d.ts +85 -0
- package/lib/http/utils/clientIp.d.ts.map +1 -0
- package/lib/http/utils/clientIp.js +249 -0
- package/lib/http/utils/clientIp.js.map +1 -0
- package/lib/http/utils/index.d.ts +4 -0
- package/lib/http/utils/index.d.ts.map +1 -0
- package/lib/http/utils/index.js +5 -0
- package/lib/http/utils/index.js.map +1 -0
- package/lib/http/utils/metaTags.d.ts +49 -0
- package/lib/http/utils/metaTags.d.ts.map +1 -0
- package/lib/http/utils/metaTags.js +32 -0
- package/lib/http/utils/metaTags.js.map +1 -0
- package/lib/http/utils/publicSuffix.d.ts +34 -0
- package/lib/http/utils/publicSuffix.d.ts.map +1 -0
- package/lib/http/utils/publicSuffix.js +276 -0
- package/lib/http/utils/publicSuffix.js.map +1 -0
- package/lib/http/utils/uploads.d.ts +92 -0
- package/lib/http/utils/uploads.d.ts.map +1 -0
- package/lib/http/utils/uploads.js +126 -0
- package/lib/http/utils/uploads.js.map +1 -0
- package/lib/http/utils/validate.d.ts +41 -0
- package/lib/http/utils/validate.d.ts.map +1 -0
- package/lib/http/utils/validate.js +55 -0
- package/lib/http/utils/validate.js.map +1 -0
- package/lib/http/utils/webhooks.d.ts +63 -0
- package/lib/http/utils/webhooks.d.ts.map +1 -0
- package/lib/http/utils/webhooks.js +133 -0
- package/lib/http/utils/webhooks.js.map +1 -0
- package/lib/http/ws/auth.d.ts +46 -0
- package/lib/http/ws/auth.d.ts.map +1 -0
- package/lib/http/ws/auth.js +123 -0
- package/lib/http/ws/auth.js.map +1 -0
- package/lib/index.d.ts +80 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +61 -0
- package/lib/index.js.map +1 -0
- package/lib/kernel/index.d.ts +3 -0
- package/lib/kernel/index.d.ts.map +1 -0
- package/lib/kernel/index.js +3 -0
- package/lib/kernel/index.js.map +1 -0
- package/lib/libraries/.gitkeep +0 -0
- package/lib/libraries/ai/CHANGELOG.md +17 -0
- package/lib/libraries/ai/README.md +164 -0
- package/lib/libraries/ai/adapters/AnthropicAdapter.ts +382 -0
- package/lib/libraries/ai/adapters/LLMProvider.ts +76 -0
- package/lib/libraries/ai/adapters/OpenAIAdapter.ts +466 -0
- package/lib/libraries/ai/experimental/index.ts +20 -0
- package/lib/libraries/ai/index.ts +128 -0
- package/lib/libraries/ai/library.json +19 -0
- package/lib/libraries/ai/loop/agentLoop.ts +377 -0
- package/lib/libraries/ai/prompts/definePrompt.ts +0 -0
- package/lib/libraries/ai/rag/retrieveAndAnswer.ts +177 -0
- package/lib/libraries/ai/streaming/streamLLM.ts +94 -0
- package/lib/libraries/ai/structured/completeStructured.ts +143 -0
- package/lib/libraries/ai/tokens/Tokenizer.ts +216 -0
- package/lib/libraries/ai/tools/defineTool.ts +208 -0
- package/lib/libraries/ai/types.ts +260 -0
- package/lib/libraries/chunking/ChunkingService.ts +103 -0
- package/lib/libraries/chunking/README.md +104 -0
- package/lib/libraries/chunking/docs/api-reference.md +549 -0
- package/lib/libraries/chunking/docs/best-practices.md +321 -0
- package/lib/libraries/chunking/docs/code-organization.md +538 -0
- package/lib/libraries/chunking/docs/configuration.md +418 -0
- package/lib/libraries/chunking/docs/index.md +236 -0
- package/lib/libraries/chunking/docs/quick-start.md +298 -0
- package/lib/libraries/chunking/docs/strategies.md +407 -0
- package/lib/libraries/chunking/docs/summary.md +258 -0
- package/lib/libraries/chunking/docs/troubleshooting.md +527 -0
- package/lib/libraries/chunking/index.ts +17 -0
- package/lib/libraries/chunking/library.json +16 -0
- package/lib/libraries/chunking/strategies/ChunkingStrategy.ts +13 -0
- package/lib/libraries/chunking/strategies/FixedLengthChunkingStrategy.ts +88 -0
- package/lib/libraries/chunking/strategies/SemanticChunkingStrategy.ts +389 -0
- package/lib/libraries/chunking/strategies/SlidingWindowChunkingStrategy.ts +258 -0
- package/lib/libraries/chunking/types/index.ts +63 -0
- package/lib/libraries/email/EmailService.ts +591 -0
- package/lib/libraries/email/README.md +777 -0
- package/lib/libraries/email/TemplateRegistry.ts +148 -0
- package/lib/libraries/email/TemplateRenderer.ts +273 -0
- package/lib/libraries/email/index.ts +4 -0
- package/lib/libraries/email/initializeEmailService.ts +60 -0
- package/lib/libraries/email/library.json +12 -0
- package/lib/libraries/email/types/EmailAddress.ts +4 -0
- package/lib/libraries/email/types/EmailAttachment.ts +11 -0
- package/lib/libraries/email/types/EmailTag.ts +9 -0
- package/lib/libraries/email/types/EmailTemplate.ts +124 -0
- package/lib/libraries/email/types/SendBatchEmailsOptions.ts +9 -0
- package/lib/libraries/email/types/SendBatchEmailsResult.ts +9 -0
- package/lib/libraries/email/types/SendEmailOptions.ts +33 -0
- package/lib/libraries/email/types/SendEmailResult.ts +9 -0
- package/lib/libraries/email/types/index.ts +8 -0
- package/lib/libraries/weaviate/QueryBuilder.ts +292 -0
- package/lib/libraries/weaviate/README.md +284 -0
- package/lib/libraries/weaviate/Weaviate.ts +1419 -0
- package/lib/libraries/weaviate/WeaviateConfig.ts +268 -0
- package/lib/libraries/weaviate/docs/.gitkeep +1 -0
- package/lib/libraries/weaviate/docs/API_REFERENCE.md +1067 -0
- package/lib/libraries/weaviate/docs/CONFIGURATION.md +320 -0
- package/lib/libraries/weaviate/docs/ERROR_HANDLING.md +271 -0
- package/lib/libraries/weaviate/docs/MULTI_TENANCY.md +348 -0
- package/lib/libraries/weaviate/docs/PERFORMANCE.md +602 -0
- package/lib/libraries/weaviate/docs/PLUGIN_DEVELOPMENT.md +547 -0
- package/lib/libraries/weaviate/docs/QUICK_START.md +443 -0
- package/lib/libraries/weaviate/docs/README.md +269 -0
- package/lib/libraries/weaviate/docs/SCHEMA_GUIDE.md +630 -0
- package/lib/libraries/weaviate/docs/WEAVIATE_README.md +520 -0
- package/lib/libraries/weaviate/errors/WeaviateError.ts +92 -0
- package/lib/libraries/weaviate/errors/index.ts +1 -0
- package/lib/libraries/weaviate/index.ts +35 -0
- package/lib/libraries/weaviate/library.json +26 -0
- package/lib/libraries/weaviate/plugins/index.ts +2 -0
- package/lib/libraries/weaviate/schemas/SchemaRegistry.ts +284 -0
- package/lib/libraries/weaviate/schemas/index.ts +2 -0
- package/lib/libraries/weaviate/types/BM25SearchOptions.ts +9 -0
- package/lib/libraries/weaviate/types/ExtendedWeaviateClient.ts +7 -0
- package/lib/libraries/weaviate/types/HybridSearchOptions.ts +11 -0
- package/lib/libraries/weaviate/types/MultiTenancy.ts +81 -0
- package/lib/libraries/weaviate/types/Plugin.ts +17 -0
- package/lib/libraries/weaviate/types/SchemaConfig.ts +25 -0
- package/lib/libraries/weaviate/types/SearchMethod.ts +8 -0
- package/lib/libraries/weaviate/types/SearchOptions.ts +16 -0
- package/lib/libraries/weaviate/types/SearchRequest.ts +19 -0
- package/lib/libraries/weaviate/types/SearchResult.ts +16 -0
- package/lib/libraries/weaviate/types/SearchableField.ts +87 -0
- package/lib/libraries/weaviate/types/VectorIndexConfig.ts +19 -0
- package/lib/libraries/weaviate/types/VectorSearchOptions.ts +18 -0
- package/lib/libraries/weaviate/types/VectorizerConfig.ts +8 -0
- package/lib/libraries/weaviate/types/index.ts +29 -0
- package/lib/libraries/weaviate/utils/TenantContextManager.ts +94 -0
- package/lib/modules/accounts/index.ts +47 -0
- package/lib/modules/accounts/module.json +15 -0
- package/lib/modules/accounts/permissions.ts +33 -0
- package/lib/modules/accounts/routes.ts +200 -0
- package/lib/modules/accounts/schema.ts +219 -0
- package/lib/modules/accounts/services/AccountService.ts +44 -0
- package/lib/modules/accounts/validation/schemas.ts +70 -0
- package/lib/modules/oauth/adapters/GmailOAuthAdapter.ts +35 -0
- package/lib/modules/oauth/adapters/GoogleOAuthAdapter.ts +278 -0
- package/lib/modules/oauth/adapters/MicrosoftOAuthAdapter.ts +269 -0
- package/lib/modules/oauth/adapters/MockOAuthAdapter.ts +138 -0
- package/lib/modules/oauth/adapters/OAuthAdapter.ts +211 -0
- package/lib/modules/oauth/adapters/OAuthAdapterRegistry.ts +77 -0
- package/lib/modules/oauth/adapters/OutlookOAuthAdapter.ts +38 -0
- package/lib/modules/oauth/index.ts +79 -0
- package/lib/modules/oauth/module.json +23 -0
- package/lib/modules/oauth/permissions.ts +39 -0
- package/lib/modules/oauth/routes.ts +497 -0
- package/lib/modules/oauth/schema.ts +127 -0
- package/lib/modules/oauth/services/OAuthConnectionService.ts +147 -0
- package/lib/modules/oauth/state.ts +234 -0
- package/lib/modules/oauth/stateJtiCache.ts +85 -0
- package/lib/modules/oauth/verifyIdToken.ts +178 -0
- package/lib/modules/outbox/EventEmitter.ts +106 -0
- package/lib/modules/outbox/OutboxDrainer.ts +163 -0
- package/lib/modules/outbox/handlers/EventHandler.ts +115 -0
- package/lib/modules/outbox/index.ts +43 -0
- package/lib/modules/outbox/module.json +15 -0
- package/lib/modules/outbox/permissions.ts +36 -0
- package/lib/modules/outbox/routes.ts +219 -0
- package/lib/modules/outbox/schema.ts +207 -0
- package/lib/modules/outbox/services/OutboxEventService.ts +223 -0
- package/lib/observability/logger.d.ts +30 -0
- package/lib/observability/logger.d.ts.map +1 -0
- package/lib/observability/logger.js +110 -0
- package/lib/observability/logger.js.map +1 -0
- package/lib/observability/metrics.d.ts +3 -0
- package/lib/observability/metrics.d.ts.map +1 -0
- package/lib/observability/metrics.js +3 -0
- package/lib/observability/metrics.js.map +1 -0
- package/lib/observability/otel.d.ts +3 -0
- package/lib/observability/otel.d.ts.map +1 -0
- package/lib/observability/otel.js +3 -0
- package/lib/observability/otel.js.map +1 -0
- package/lib/observability/safeErrorFields.d.ts +14 -0
- package/lib/observability/safeErrorFields.d.ts.map +1 -0
- package/lib/observability/safeErrorFields.js +14 -0
- package/lib/observability/safeErrorFields.js.map +1 -0
- package/lib/observability/tracing.d.ts +3 -0
- package/lib/observability/tracing.d.ts.map +1 -0
- package/lib/observability/tracing.js +3 -0
- package/lib/observability/tracing.js.map +1 -0
- package/lib/package.json +4 -0
- package/lib/testing.d.ts +3 -0
- package/lib/testing.d.ts.map +1 -0
- package/lib/testing.js +3 -0
- package/lib/testing.js.map +1 -0
- package/package.json +193 -3
- package/templates/default/.claude/agents/qa-brief.md +106 -0
- package/templates/default/.claude/commands/sherpa-brief.md +23 -0
- package/templates/default/.cursor/rules/api.mdc +80 -0
- package/templates/default/.cursor/rules/commits.mdc +88 -0
- package/templates/default/.cursor/rules/security.mdc +92 -0
- package/templates/default/.cursor/rules/testing.mdc +123 -0
- package/templates/default/.cursor/rules/typescript.mdc +86 -0
- package/templates/default/.env.example +79 -0
- package/templates/default/.github/workflows/sherpa-brief.yml +180 -0
- package/templates/default/AGENTS.md +166 -0
- package/templates/default/CLAUDE.md +17 -0
- package/templates/default/README.md +97 -0
- package/templates/default/_gitignore +27 -0
- package/templates/default/docker-compose.yml +83 -0
- package/templates/default/drizzle.config.ts +34 -0
- package/templates/default/eslint.config.mjs +106 -0
- package/templates/default/package.json +57 -0
- package/templates/default/ship-api.config.ts +21 -0
- package/templates/default/src/client.ts +34 -0
- package/templates/default/src/config/modules.ts +23 -0
- package/templates/default/src/db/schema.ts +26 -0
- package/templates/default/src/environment.ts +81 -0
- package/templates/default/src/index.test.ts +53 -0
- package/templates/default/src/index.ts +11 -0
- package/templates/default/src/instrumentation.ts +13 -0
- package/templates/default/src/server.ts +90 -0
- package/templates/default/tsconfig.json +24 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { and, eq, isNull, or, sql } from "drizzle-orm";
|
|
2
|
+
import { withTransaction } from "../../db/transaction.js";
|
|
3
|
+
export class DrizzleRefreshTokenStore {
|
|
4
|
+
db;
|
|
5
|
+
table;
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
this.db = opts.db;
|
|
8
|
+
this.table = opts.table;
|
|
9
|
+
}
|
|
10
|
+
async issue(input) {
|
|
11
|
+
const [row] = await this.db
|
|
12
|
+
.insert(this.table)
|
|
13
|
+
.values({
|
|
14
|
+
accountId: input.accountId,
|
|
15
|
+
tokenHash: input.tokenHash,
|
|
16
|
+
expiresAt: input.expiresAt,
|
|
17
|
+
userAgent: input.userAgent ?? null,
|
|
18
|
+
issuedFromIp: input.issuedFromIp ?? null,
|
|
19
|
+
})
|
|
20
|
+
.returning();
|
|
21
|
+
return rowToRecord(row);
|
|
22
|
+
}
|
|
23
|
+
async findByHash(tokenHash) {
|
|
24
|
+
const rows = await this.db
|
|
25
|
+
.select()
|
|
26
|
+
.from(this.table)
|
|
27
|
+
.where(eq(this.table.tokenHash, tokenHash))
|
|
28
|
+
.limit(1);
|
|
29
|
+
if (!rows.length)
|
|
30
|
+
return null;
|
|
31
|
+
return rowToRecord(rows[0]);
|
|
32
|
+
}
|
|
33
|
+
async rotate(oldId, newToken) {
|
|
34
|
+
return withTransaction(this.db, async (tx) => {
|
|
35
|
+
const [inserted] = await tx
|
|
36
|
+
.insert(this.table)
|
|
37
|
+
.values({
|
|
38
|
+
accountId: newToken.accountId,
|
|
39
|
+
tokenHash: newToken.tokenHash,
|
|
40
|
+
expiresAt: newToken.expiresAt,
|
|
41
|
+
userAgent: newToken.userAgent ?? null,
|
|
42
|
+
issuedFromIp: newToken.issuedFromIp ?? null,
|
|
43
|
+
})
|
|
44
|
+
.returning();
|
|
45
|
+
const row = inserted;
|
|
46
|
+
await tx
|
|
47
|
+
.update(this.table)
|
|
48
|
+
.set({ replacedById: row.id })
|
|
49
|
+
.where(eq(this.table.id, oldId));
|
|
50
|
+
return rowToRecord(row);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async revoke(id) {
|
|
54
|
+
await this.db
|
|
55
|
+
.update(this.table)
|
|
56
|
+
.set({ revokedAt: new Date() })
|
|
57
|
+
.where(and(eq(this.table.id, id), isNull(this.table.revokedAt)));
|
|
58
|
+
}
|
|
59
|
+
async revokeChain(id) {
|
|
60
|
+
// Single-shot: a recursive CTE collects every ancestor + descendant
|
|
61
|
+
// reachable from `id`, then a single UPDATE flips them all to revoked.
|
|
62
|
+
// Stable across Postgres ≥12.
|
|
63
|
+
const tableName = sql.identifier(getTableName(this.table));
|
|
64
|
+
const result = await this.db.execute(sql `
|
|
65
|
+
WITH RECURSIVE forward AS (
|
|
66
|
+
SELECT id, replaced_by_id FROM ${tableName} WHERE id = ${id}
|
|
67
|
+
UNION ALL
|
|
68
|
+
SELECT t.id, t.replaced_by_id
|
|
69
|
+
FROM ${tableName} t
|
|
70
|
+
JOIN forward f ON t.id = f.replaced_by_id
|
|
71
|
+
),
|
|
72
|
+
backward AS (
|
|
73
|
+
SELECT id, replaced_by_id FROM ${tableName} WHERE id = ${id}
|
|
74
|
+
UNION ALL
|
|
75
|
+
SELECT t.id, t.replaced_by_id
|
|
76
|
+
FROM ${tableName} t
|
|
77
|
+
JOIN backward b ON t.replaced_by_id = b.id
|
|
78
|
+
),
|
|
79
|
+
chain AS (
|
|
80
|
+
SELECT id FROM forward UNION SELECT id FROM backward
|
|
81
|
+
)
|
|
82
|
+
UPDATE ${tableName} SET revoked_at = NOW()
|
|
83
|
+
WHERE id IN (SELECT id FROM chain) AND revoked_at IS NULL
|
|
84
|
+
RETURNING id
|
|
85
|
+
`);
|
|
86
|
+
return readRowCount(result);
|
|
87
|
+
}
|
|
88
|
+
async revokeAllForAccount(accountId) {
|
|
89
|
+
const result = await this.db
|
|
90
|
+
.update(this.table)
|
|
91
|
+
.set({ revokedAt: new Date() })
|
|
92
|
+
.where(and(eq(this.table.accountId, accountId), or(isNull(this.table.revokedAt),
|
|
93
|
+
// No-op clause keeps the predicate non-empty if `or` collapses.
|
|
94
|
+
sql `false`)))
|
|
95
|
+
.returning({ id: this.table.id });
|
|
96
|
+
return result.length;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function rowToRecord(row) {
|
|
100
|
+
return {
|
|
101
|
+
id: row.id,
|
|
102
|
+
accountId: row.accountId,
|
|
103
|
+
tokenHash: row.tokenHash,
|
|
104
|
+
expiresAt: row.expiresAt,
|
|
105
|
+
revokedAt: row.revokedAt,
|
|
106
|
+
replacedById: row.replacedById,
|
|
107
|
+
userAgent: row.userAgent,
|
|
108
|
+
issuedFromIp: row.issuedFromIp,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function getTableName(table) {
|
|
112
|
+
// Drizzle exposes table metadata via the `Symbol.for('drizzle:Name')` slot.
|
|
113
|
+
// Falls back to the inline name for forward-compat with future Drizzle
|
|
114
|
+
// versions that may shift the symbol.
|
|
115
|
+
const sym = Object.getOwnPropertySymbols(table).find((s) => s.description?.includes("drizzle") || s.description?.includes("Name"));
|
|
116
|
+
if (sym) {
|
|
117
|
+
const value = table[sym];
|
|
118
|
+
if (typeof value === "string")
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
// Last resort — every PgTable carries a stringifiable identifier.
|
|
122
|
+
return String(table._?.name ?? "refresh_tokens");
|
|
123
|
+
}
|
|
124
|
+
function readRowCount(result) {
|
|
125
|
+
// node-postgres returns `{ rows, rowCount, ... }`; Drizzle's `execute`
|
|
126
|
+
// forwards that shape. Guard for shape drift across drivers.
|
|
127
|
+
const r = result;
|
|
128
|
+
if (typeof r.rowCount === "number")
|
|
129
|
+
return r.rowCount;
|
|
130
|
+
if (Array.isArray(r.rows))
|
|
131
|
+
return r.rows.length;
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=DrizzleRefreshTokenStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DrizzleRefreshTokenStore.js","sourceRoot":"","sources":["../../../../src/app/auth/jwt/DrizzleRefreshTokenStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { type CryptoKey, type JWTPayload } from "jose";
|
|
2
|
+
/**
|
|
3
|
+
* `JwtSigner` — ES256 JWT signing/verification with `kid`-based key rotation.
|
|
4
|
+
*
|
|
5
|
+
* Wraps `jose@^6` for the framework's stateless cookie-auth flow. Owned by
|
|
6
|
+
* `AuthFlow` (which combines this with `RefreshTokenStore` to handle issue /
|
|
7
|
+
* rotate / revoke). Lives at this level because:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Key rotation is a load-bearing security primitive.** A signer that
|
|
10
|
+
* can verify with multiple public keys lets operators add a new key,
|
|
11
|
+
* cut signing over to it, wait for max-token-lifetime, then retire the
|
|
12
|
+
* old key — without forcing every active session to re-authenticate.
|
|
13
|
+
* The rotation procedure is documented in `.cursor/rules/security.mdc`.
|
|
14
|
+
*
|
|
15
|
+
* 2. **Edge-runtime parity.** `CryptoKey` (Web Crypto) is portable between
|
|
16
|
+
* Node, Cloudflare Workers, and Bun, so v4.x edge adapters reuse this
|
|
17
|
+
* class without a runtime fork.
|
|
18
|
+
*
|
|
19
|
+
* 3. **Pluggable adapter boundary.** `AuthFlow` owns persistence (refresh
|
|
20
|
+
* token store) and HTTP (cookies); `JwtSigner` owns *only* the JWS step.
|
|
21
|
+
* Easier to test, easier to swap (e.g., HSM-backed signer in v4.x).
|
|
22
|
+
*
|
|
23
|
+
* The single signing key (`signingKey.kid`) is the active key; tokens carry
|
|
24
|
+
* the `kid` in their protected header. Verification looks the `kid` up in the
|
|
25
|
+
* `verificationKeys` map, which always includes the active signing key plus
|
|
26
|
+
* any retiring keys still inside their max-lifetime grace window.
|
|
27
|
+
*/
|
|
28
|
+
export interface JwtSigningKey {
|
|
29
|
+
/** Key identifier — propagated into the token's `kid` header. */
|
|
30
|
+
kid: string;
|
|
31
|
+
/** Web Crypto private key for ES256. Use jose's `importPKCS8(pem, 'ES256')`. */
|
|
32
|
+
privateKey: CryptoKey;
|
|
33
|
+
}
|
|
34
|
+
export interface JwtVerificationKey {
|
|
35
|
+
kid: string;
|
|
36
|
+
/** Web Crypto public key for ES256. Use jose's `importSPKI(pem, 'ES256')`. */
|
|
37
|
+
publicKey: CryptoKey;
|
|
38
|
+
}
|
|
39
|
+
export interface JwtSignerOptions {
|
|
40
|
+
/** Active signing key. Tokens are issued with `protectedHeader.kid = signingKey.kid`. */
|
|
41
|
+
signingKey: JwtSigningKey;
|
|
42
|
+
/**
|
|
43
|
+
* All public keys currently accepted at verification time. MUST include
|
|
44
|
+
* `signingKey`'s public counterpart and any retiring keys within their
|
|
45
|
+
* grace window. Empty arrays are rejected at construction.
|
|
46
|
+
*/
|
|
47
|
+
verificationKeys: JwtVerificationKey[];
|
|
48
|
+
/** Default `iss` claim on signed tokens; verified at decode time. */
|
|
49
|
+
issuer?: string;
|
|
50
|
+
/** Default `aud` claim on signed tokens; verified at decode time. */
|
|
51
|
+
audience?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Clock-skew tolerance for `exp`/`nbf`/`iat` validation in seconds.
|
|
54
|
+
*
|
|
55
|
+
* **Default 30** — the industry-standard tolerance per NIST SP
|
|
56
|
+
* 800-63B §5.1.1.2. Tight enough to defend against meaningful
|
|
57
|
+
* replay (the access-token TTL is the dominant window) and broad
|
|
58
|
+
* enough to survive the ~1–5 s NTP drift typical between hosts
|
|
59
|
+
* with healthy clock-sync. A 0 default produced flaky 401s in
|
|
60
|
+
* mixed environments and pushed adopters toward minutes-long
|
|
61
|
+
* tolerances that weakened the contract further than necessary.
|
|
62
|
+
*
|
|
63
|
+
* Explicit `clockToleranceSec: 0` reproduces the prior strict
|
|
64
|
+
* behavior for callers who genuinely want zero slack.
|
|
65
|
+
*/
|
|
66
|
+
clockToleranceSec?: number;
|
|
67
|
+
}
|
|
68
|
+
export interface SignTokenOptions {
|
|
69
|
+
/** Subject (`sub`) — typically the Account ID. */
|
|
70
|
+
subject: string;
|
|
71
|
+
/** TTL in seconds. Required to force callers to make an explicit decision. */
|
|
72
|
+
ttlSec: number;
|
|
73
|
+
/** Optional explicit `jti`. Auto-generated as a UUIDv4 when omitted. */
|
|
74
|
+
jti?: string;
|
|
75
|
+
/** Optional override of the construction-time `iss`. */
|
|
76
|
+
issuer?: string;
|
|
77
|
+
/** Optional override of the construction-time `aud`. */
|
|
78
|
+
audience?: string;
|
|
79
|
+
/** Custom claims merged into the JWT payload. Avoid colliding with reserved names. */
|
|
80
|
+
claims?: Record<string, unknown>;
|
|
81
|
+
}
|
|
82
|
+
export interface SignedToken {
|
|
83
|
+
/** Compact JWS string (`xxxx.yyyy.zzzz`). */
|
|
84
|
+
token: string;
|
|
85
|
+
/** UUID issued for this token; persisted by `AuthFlow` for refresh-token revocation. */
|
|
86
|
+
jti: string;
|
|
87
|
+
/** Epoch seconds at issue time. */
|
|
88
|
+
issuedAt: number;
|
|
89
|
+
/** Epoch seconds at expiry. */
|
|
90
|
+
expiresAt: number;
|
|
91
|
+
/** Key id used to sign — useful for log correlation during rotation. */
|
|
92
|
+
kid: string;
|
|
93
|
+
}
|
|
94
|
+
export interface VerifiedToken<TClaims extends JWTPayload = JWTPayload> {
|
|
95
|
+
payload: TClaims;
|
|
96
|
+
kid: string;
|
|
97
|
+
}
|
|
98
|
+
export declare class JwtSigner {
|
|
99
|
+
private readonly signingKey;
|
|
100
|
+
private readonly verificationKeysByKid;
|
|
101
|
+
private readonly issuer?;
|
|
102
|
+
private readonly audience?;
|
|
103
|
+
private readonly clockToleranceSec;
|
|
104
|
+
constructor(opts: JwtSignerOptions);
|
|
105
|
+
/**
|
|
106
|
+
* Sign a token. The caller is responsible for choosing `ttlSec` (e.g., 15m
|
|
107
|
+
* for access tokens, 30d for refresh tokens). Returns the compact JWS plus
|
|
108
|
+
* metadata `AuthFlow` needs to persist a `refresh_tokens` row.
|
|
109
|
+
*/
|
|
110
|
+
sign(opts: SignTokenOptions): Promise<SignedToken>;
|
|
111
|
+
/**
|
|
112
|
+
* Verify a token. Throws `AuthenticationError` on any failure — caller
|
|
113
|
+
* surfaces this through the framework's standard error path. Signature,
|
|
114
|
+
* expiry, and (when configured) issuer/audience are all enforced.
|
|
115
|
+
*/
|
|
116
|
+
verify<TClaims extends JWTPayload = JWTPayload>(token: string): Promise<VerifiedToken<TClaims>>;
|
|
117
|
+
/** Expose the active signing kid for log/metric correlation. */
|
|
118
|
+
getSigningKid(): string;
|
|
119
|
+
/** Expose the kids currently accepted at verification — useful for `/dev/routes`-style introspection. */
|
|
120
|
+
getVerificationKids(): string[];
|
|
121
|
+
private resolveKey;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=JwtSigner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JwtSigner.d.ts","sourceRoot":"","sources":["../../../../src/app/auth/jwt/JwtSigner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAA4C,MAAM,MAAM,CAAC;AAGjG;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,UAAU,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,UAAU,EAAE,aAAa,CAAC;IAC1B;;;;OAIG;IACH,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,aAAa,CAAC,OAAO,SAAS,UAAU,GAAG,UAAU;IACpE,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAID,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAyB;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;gBAE/B,IAAI,EAAE,gBAAgB;IAsBlC;;;;OAIG;IACG,IAAI,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAsBxD;;;;OAIG;IACG,MAAM,CAAC,OAAO,SAAS,UAAU,GAAG,UAAU,EAClD,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAelC,gEAAgE;IAChE,aAAa,IAAI,MAAM;IAIvB,yGAAyG;IACzG,mBAAmB,IAAI,MAAM,EAAE;IAI/B,OAAO,CAAC,UAAU;CAYnB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { errors as joseErrors, jwtVerify, SignJWT } from "jose";
|
|
3
|
+
import { AuthenticationError } from "../../../http/errors/AuthenticationError.js";
|
|
4
|
+
const ALG = "ES256";
|
|
5
|
+
export class JwtSigner {
|
|
6
|
+
signingKey;
|
|
7
|
+
verificationKeysByKid;
|
|
8
|
+
issuer;
|
|
9
|
+
audience;
|
|
10
|
+
clockToleranceSec;
|
|
11
|
+
constructor(opts) {
|
|
12
|
+
if (!opts.verificationKeys.length) {
|
|
13
|
+
throw new Error("JwtSigner: verificationKeys must contain at least one key");
|
|
14
|
+
}
|
|
15
|
+
this.signingKey = opts.signingKey;
|
|
16
|
+
this.verificationKeysByKid = new Map();
|
|
17
|
+
for (const key of opts.verificationKeys) {
|
|
18
|
+
if (this.verificationKeysByKid.has(key.kid)) {
|
|
19
|
+
throw new Error(`JwtSigner: duplicate verification key kid "${key.kid}"`);
|
|
20
|
+
}
|
|
21
|
+
this.verificationKeysByKid.set(key.kid, key.publicKey);
|
|
22
|
+
}
|
|
23
|
+
if (!this.verificationKeysByKid.has(opts.signingKey.kid)) {
|
|
24
|
+
throw new Error(`JwtSigner: signing key kid "${opts.signingKey.kid}" missing from verificationKeys`);
|
|
25
|
+
}
|
|
26
|
+
this.issuer = opts.issuer;
|
|
27
|
+
this.audience = opts.audience;
|
|
28
|
+
this.clockToleranceSec = opts.clockToleranceSec ?? 30;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sign a token. The caller is responsible for choosing `ttlSec` (e.g., 15m
|
|
32
|
+
* for access tokens, 30d for refresh tokens). Returns the compact JWS plus
|
|
33
|
+
* metadata `AuthFlow` needs to persist a `refresh_tokens` row.
|
|
34
|
+
*/
|
|
35
|
+
async sign(opts) {
|
|
36
|
+
const jti = opts.jti ?? randomUUID();
|
|
37
|
+
const issuedAt = Math.floor(Date.now() / 1000);
|
|
38
|
+
const expiresAt = issuedAt + opts.ttlSec;
|
|
39
|
+
const builder = new SignJWT({ ...(opts.claims ?? {}) })
|
|
40
|
+
.setProtectedHeader({ alg: ALG, kid: this.signingKey.kid })
|
|
41
|
+
.setSubject(opts.subject)
|
|
42
|
+
.setJti(jti)
|
|
43
|
+
.setIssuedAt(issuedAt)
|
|
44
|
+
.setExpirationTime(expiresAt);
|
|
45
|
+
const issuer = opts.issuer ?? this.issuer;
|
|
46
|
+
if (issuer)
|
|
47
|
+
builder.setIssuer(issuer);
|
|
48
|
+
const audience = opts.audience ?? this.audience;
|
|
49
|
+
if (audience)
|
|
50
|
+
builder.setAudience(audience);
|
|
51
|
+
const token = await builder.sign(this.signingKey.privateKey);
|
|
52
|
+
return { token, jti, issuedAt, expiresAt, kid: this.signingKey.kid };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Verify a token. Throws `AuthenticationError` on any failure — caller
|
|
56
|
+
* surfaces this through the framework's standard error path. Signature,
|
|
57
|
+
* expiry, and (when configured) issuer/audience are all enforced.
|
|
58
|
+
*/
|
|
59
|
+
async verify(token) {
|
|
60
|
+
try {
|
|
61
|
+
const result = await jwtVerify(token, (header) => this.resolveKey(header.kid), {
|
|
62
|
+
algorithms: [ALG],
|
|
63
|
+
issuer: this.issuer,
|
|
64
|
+
audience: this.audience,
|
|
65
|
+
clockTolerance: this.clockToleranceSec,
|
|
66
|
+
});
|
|
67
|
+
const kid = result.protectedHeader.kid ?? this.signingKey.kid;
|
|
68
|
+
return { payload: result.payload, kid };
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
throw classifyVerificationError(err);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Expose the active signing kid for log/metric correlation. */
|
|
75
|
+
getSigningKid() {
|
|
76
|
+
return this.signingKey.kid;
|
|
77
|
+
}
|
|
78
|
+
/** Expose the kids currently accepted at verification — useful for `/dev/routes`-style introspection. */
|
|
79
|
+
getVerificationKids() {
|
|
80
|
+
return [...this.verificationKeysByKid.keys()];
|
|
81
|
+
}
|
|
82
|
+
resolveKey(kid) {
|
|
83
|
+
if (!kid) {
|
|
84
|
+
// We always sign with a `kid` header, so an unsigned token is a forgery
|
|
85
|
+
// attempt against this verifier.
|
|
86
|
+
throw new joseErrors.JWSInvalid("Token missing kid header");
|
|
87
|
+
}
|
|
88
|
+
const key = this.verificationKeysByKid.get(kid);
|
|
89
|
+
if (!key) {
|
|
90
|
+
throw new joseErrors.JWKSNoMatchingKey();
|
|
91
|
+
}
|
|
92
|
+
return key;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function classifyVerificationError(err) {
|
|
96
|
+
if (err instanceof joseErrors.JWTExpired) {
|
|
97
|
+
return new AuthenticationError("Token expired");
|
|
98
|
+
}
|
|
99
|
+
if (err instanceof joseErrors.JWTClaimValidationFailed) {
|
|
100
|
+
return new AuthenticationError(`Token claim invalid: ${err.claim}`);
|
|
101
|
+
}
|
|
102
|
+
if (err instanceof joseErrors.JWKSNoMatchingKey) {
|
|
103
|
+
return new AuthenticationError("Token signing key not recognized");
|
|
104
|
+
}
|
|
105
|
+
if (err instanceof joseErrors.JWSInvalid) {
|
|
106
|
+
// Forwards messages like "Token missing kid header" set in `resolveKey`.
|
|
107
|
+
return new AuthenticationError(err.message || "Token signature invalid");
|
|
108
|
+
}
|
|
109
|
+
if (err instanceof joseErrors.JOSEError) {
|
|
110
|
+
return new AuthenticationError("Token verification failed");
|
|
111
|
+
}
|
|
112
|
+
// Unknown/unexpected — surface as generic auth failure but preserve cause
|
|
113
|
+
// so OTel/pino can capture the stack.
|
|
114
|
+
const auth = new AuthenticationError("Token verification failed");
|
|
115
|
+
auth.cause = err;
|
|
116
|
+
return auth;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=JwtSigner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JwtSigner.js","sourceRoot":"","sources":["../../../../src/app/auth/jwt/JwtSigner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `RefreshTokenStore` — abstract persistence for refresh-token rotation.
|
|
3
|
+
*
|
|
4
|
+
* The auth flow stores a SHA-256 *hash* of every issued refresh token. The
|
|
5
|
+
* raw token leaves the server only once (in the response cookie); subsequent
|
|
6
|
+
* requests recompute the hash and look up the row. This means even a full
|
|
7
|
+
* database compromise does not let an attacker mint or replay refresh tokens
|
|
8
|
+
* — they would still need the raw cookie value.
|
|
9
|
+
*
|
|
10
|
+
* Reuse detection is the load-bearing security property: when a refresh
|
|
11
|
+
* token is consumed (`consume()`), the row's `replacedById` is set to the
|
|
12
|
+
* successor's ID. If a token is presented whose row already has
|
|
13
|
+
* `replacedById` set, it has been used before — a strong signal of theft.
|
|
14
|
+
* The auth flow's response is to revoke the entire chain (`revokeChain()`)
|
|
15
|
+
* so neither the legitimate user nor the attacker can keep refreshing.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Stored representation of a refresh token. Implementations may add fields,
|
|
19
|
+
* but the framework only depends on these.
|
|
20
|
+
*/
|
|
21
|
+
export interface RefreshTokenRecord {
|
|
22
|
+
id: string;
|
|
23
|
+
accountId: string;
|
|
24
|
+
/** SHA-256 hex digest of the raw token. Never stores the raw token itself. */
|
|
25
|
+
tokenHash: string;
|
|
26
|
+
expiresAt: Date;
|
|
27
|
+
revokedAt: Date | null;
|
|
28
|
+
/** Successor's ID when this token has been rotated; null otherwise. */
|
|
29
|
+
replacedById: string | null;
|
|
30
|
+
userAgent?: string | null;
|
|
31
|
+
issuedFromIp?: string | null;
|
|
32
|
+
}
|
|
33
|
+
export interface IssueRefreshTokenInput {
|
|
34
|
+
accountId: string;
|
|
35
|
+
/** Pre-computed SHA-256 hex digest. Computed by the auth flow. */
|
|
36
|
+
tokenHash: string;
|
|
37
|
+
expiresAt: Date;
|
|
38
|
+
userAgent?: string;
|
|
39
|
+
issuedFromIp?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface RefreshTokenStore {
|
|
42
|
+
/** Persist a newly minted refresh token. Returns the stored record's ID. */
|
|
43
|
+
issue(input: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
|
|
44
|
+
/** Look up a token by its hash. Returns `null` if absent. */
|
|
45
|
+
findByHash(tokenHash: string): Promise<RefreshTokenRecord | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Atomically rotate: mark the old row's `replacedById` and persist the
|
|
48
|
+
* new row. Implementations MUST do this in a single transaction so a
|
|
49
|
+
* crash between the two writes can't lose the link.
|
|
50
|
+
*/
|
|
51
|
+
rotate(oldId: string, newToken: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
|
|
52
|
+
/** Mark a single token revoked (e.g., on logout). */
|
|
53
|
+
revoke(id: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Revoke an entire rotation chain — every ancestor and every descendant.
|
|
56
|
+
* Triggered on reuse detection (a strong signal of stolen tokens).
|
|
57
|
+
*/
|
|
58
|
+
revokeChain(id: string): Promise<number>;
|
|
59
|
+
/**
|
|
60
|
+
* Revoke every active token for an account — e.g., on password reset or
|
|
61
|
+
* "sign out everywhere". Returns the number of rows revoked.
|
|
62
|
+
*/
|
|
63
|
+
revokeAllForAccount(accountId: string): Promise<number>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Compute the SHA-256 digest of a raw refresh token. Hex-encoded so it fits
|
|
67
|
+
* the `varchar(128)` column on `refresh_tokens.token_hash` exactly.
|
|
68
|
+
*/
|
|
69
|
+
export declare function hashRefreshToken(rawToken: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* Generate a cryptographically random refresh-token string. 32 random bytes
|
|
72
|
+
* (256 bits) base64url-encoded — opaque to clients, indistinguishable from
|
|
73
|
+
* a UUID. Not a JWT: refresh tokens have no payload of their own; the row
|
|
74
|
+
* in `refresh_tokens` carries all the metadata.
|
|
75
|
+
*/
|
|
76
|
+
export declare function generateRefreshTokenValue(): string;
|
|
77
|
+
/**
|
|
78
|
+
* In-memory implementation for tests and dev. Implementations MUST keep the
|
|
79
|
+
* full chain reachable so `revokeChain` can walk both directions.
|
|
80
|
+
*/
|
|
81
|
+
export declare class InMemoryRefreshTokenStore implements RefreshTokenStore {
|
|
82
|
+
private byId;
|
|
83
|
+
private byHash;
|
|
84
|
+
private idCounter;
|
|
85
|
+
issue(input: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
|
|
86
|
+
findByHash(tokenHash: string): Promise<RefreshTokenRecord | null>;
|
|
87
|
+
rotate(oldId: string, newToken: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
|
|
88
|
+
revoke(id: string): Promise<void>;
|
|
89
|
+
revokeChain(id: string): Promise<number>;
|
|
90
|
+
revokeAllForAccount(accountId: string): Promise<number>;
|
|
91
|
+
/** Test helper. */
|
|
92
|
+
size(): number;
|
|
93
|
+
/** Test helper. */
|
|
94
|
+
clear(): void;
|
|
95
|
+
private nextId;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=RefreshTokenStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RefreshTokenStore.d.ts","sourceRoot":"","sources":["../../../../src/app/auth/jwt/RefreshTokenStore.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AAEH;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,uEAAuE;IACvE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAElE,6DAA6D;IAC7D,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAElE;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAErF,qDAAqD;IACrD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzC;;;OAGG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,iBAAiB;IACjE,OAAO,CAAC,IAAI,CAAyC;IACrD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,SAAS,CAAK;IAEhB,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAiBjE,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAMjE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAQpF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqCxC,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7D,mBAAmB;IACnB,IAAI,IAAI,MAAM;IAId,mBAAmB;IACnB,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,MAAM;CAIf"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Compute the SHA-256 digest of a raw refresh token. Hex-encoded so it fits
|
|
4
|
+
* the `varchar(128)` column on `refresh_tokens.token_hash` exactly.
|
|
5
|
+
*/
|
|
6
|
+
export function hashRefreshToken(rawToken) {
|
|
7
|
+
return createHash("sha256").update(rawToken).digest("hex");
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate a cryptographically random refresh-token string. 32 random bytes
|
|
11
|
+
* (256 bits) base64url-encoded — opaque to clients, indistinguishable from
|
|
12
|
+
* a UUID. Not a JWT: refresh tokens have no payload of their own; the row
|
|
13
|
+
* in `refresh_tokens` carries all the metadata.
|
|
14
|
+
*/
|
|
15
|
+
export function generateRefreshTokenValue() {
|
|
16
|
+
return randomBytes(32).toString("base64url");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* In-memory implementation for tests and dev. Implementations MUST keep the
|
|
20
|
+
* full chain reachable so `revokeChain` can walk both directions.
|
|
21
|
+
*/
|
|
22
|
+
export class InMemoryRefreshTokenStore {
|
|
23
|
+
byId = new Map();
|
|
24
|
+
byHash = new Map();
|
|
25
|
+
idCounter = 0;
|
|
26
|
+
async issue(input) {
|
|
27
|
+
const id = this.nextId();
|
|
28
|
+
const record = {
|
|
29
|
+
id,
|
|
30
|
+
accountId: input.accountId,
|
|
31
|
+
tokenHash: input.tokenHash,
|
|
32
|
+
expiresAt: input.expiresAt,
|
|
33
|
+
revokedAt: null,
|
|
34
|
+
replacedById: null,
|
|
35
|
+
userAgent: input.userAgent ?? null,
|
|
36
|
+
issuedFromIp: input.issuedFromIp ?? null,
|
|
37
|
+
};
|
|
38
|
+
this.byId.set(id, record);
|
|
39
|
+
this.byHash.set(input.tokenHash, id);
|
|
40
|
+
return record;
|
|
41
|
+
}
|
|
42
|
+
async findByHash(tokenHash) {
|
|
43
|
+
const id = this.byHash.get(tokenHash);
|
|
44
|
+
if (!id)
|
|
45
|
+
return null;
|
|
46
|
+
return this.byId.get(id) ?? null;
|
|
47
|
+
}
|
|
48
|
+
async rotate(oldId, newToken) {
|
|
49
|
+
const old = this.byId.get(oldId);
|
|
50
|
+
if (!old)
|
|
51
|
+
throw new Error(`RefreshTokenStore: cannot rotate unknown id ${oldId}`);
|
|
52
|
+
const newRecord = await this.issue(newToken);
|
|
53
|
+
old.replacedById = newRecord.id;
|
|
54
|
+
return newRecord;
|
|
55
|
+
}
|
|
56
|
+
async revoke(id) {
|
|
57
|
+
const row = this.byId.get(id);
|
|
58
|
+
if (!row)
|
|
59
|
+
return;
|
|
60
|
+
if (!row.revokedAt)
|
|
61
|
+
row.revokedAt = new Date();
|
|
62
|
+
}
|
|
63
|
+
async revokeChain(id) {
|
|
64
|
+
const visited = new Set();
|
|
65
|
+
let count = 0;
|
|
66
|
+
// Walk forward via replacedById.
|
|
67
|
+
let cursor = id;
|
|
68
|
+
while (cursor && !visited.has(cursor)) {
|
|
69
|
+
visited.add(cursor);
|
|
70
|
+
const row = this.byId.get(cursor);
|
|
71
|
+
if (!row)
|
|
72
|
+
break;
|
|
73
|
+
if (!row.revokedAt) {
|
|
74
|
+
row.revokedAt = new Date();
|
|
75
|
+
count += 1;
|
|
76
|
+
}
|
|
77
|
+
cursor = row.replacedById;
|
|
78
|
+
}
|
|
79
|
+
// Walk backward by scanning for predecessors. Cheap on small in-memory
|
|
80
|
+
// sets; the Drizzle implementation does it with a recursive CTE.
|
|
81
|
+
let changed = true;
|
|
82
|
+
while (changed) {
|
|
83
|
+
changed = false;
|
|
84
|
+
for (const row of this.byId.values()) {
|
|
85
|
+
if (row.replacedById && visited.has(row.replacedById) && !visited.has(row.id)) {
|
|
86
|
+
visited.add(row.id);
|
|
87
|
+
if (!row.revokedAt) {
|
|
88
|
+
row.revokedAt = new Date();
|
|
89
|
+
count += 1;
|
|
90
|
+
}
|
|
91
|
+
changed = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return count;
|
|
96
|
+
}
|
|
97
|
+
async revokeAllForAccount(accountId) {
|
|
98
|
+
let count = 0;
|
|
99
|
+
for (const row of this.byId.values()) {
|
|
100
|
+
if (row.accountId === accountId && !row.revokedAt) {
|
|
101
|
+
row.revokedAt = new Date();
|
|
102
|
+
count += 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return count;
|
|
106
|
+
}
|
|
107
|
+
/** Test helper. */
|
|
108
|
+
size() {
|
|
109
|
+
return this.byId.size;
|
|
110
|
+
}
|
|
111
|
+
/** Test helper. */
|
|
112
|
+
clear() {
|
|
113
|
+
this.byId.clear();
|
|
114
|
+
this.byHash.clear();
|
|
115
|
+
this.idCounter = 0;
|
|
116
|
+
}
|
|
117
|
+
nextId() {
|
|
118
|
+
this.idCounter += 1;
|
|
119
|
+
return `mem-${this.idCounter}`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=RefreshTokenStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RefreshTokenStore.js","sourceRoot":"","sources":["../../../../src/app/auth/jwt/RefreshTokenStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2EtD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB;IACvC,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,yBAAyB;IAC5B,IAAI,GAAG,IAAI,GAAG,EAA8B,CAAC;IAC7C,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnC,SAAS,GAAG,CAAC,CAAC;IAEtB,KAAK,CAAC,KAAK,CAAC,KAA6B;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,MAAM,GAAuB;YACjC,EAAE;YACF,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;YAClC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;SACzC,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,QAAgC;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,KAAK,EAAE,CAAC,CAAC;QAClF,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7C,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU;QAC1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,iCAAiC;QACjC,IAAI,MAAM,GAAkB,EAAE,CAAC;QAC/B,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,GAAG;gBAAE,MAAM;YAChB,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;gBACnB,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;gBAC3B,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;YACD,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC;QAC5B,CAAC;QAED,uEAAuE;QACvE,iEAAiE;QACjE,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,OAAO,OAAO,EAAE,CAAC;YACf,OAAO,GAAG,KAAK,CAAC;YAChB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBACrC,IAAI,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC9E,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACpB,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;wBACnB,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;wBAC3B,KAAK,IAAI,CAAC,CAAC;oBACb,CAAC;oBACD,OAAO,GAAG,IAAI,CAAC;gBACjB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,SAAiB;QACzC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACrC,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;gBAClD,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;gBAC3B,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mBAAmB;IACnB,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,mBAAmB;IACnB,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACrB,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;QACpB,OAAO,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical shape of a permission definition.
|
|
3
|
+
*
|
|
4
|
+
* Each module exports a `<MODULE>_PERMISSION_DEFINITIONS: readonly
|
|
5
|
+
* PermissionDefinition[]` array that the consuming app's bootstrapper / seed
|
|
6
|
+
* upserts into the Permission table. `slug` is the forward-compatible
|
|
7
|
+
* identifier (`module[:resource]:action` — lowercase, colon-separated;
|
|
8
|
+
* hyphenate multi-word actions, e.g. `oauth:connections:read-self`); `label`
|
|
9
|
+
* is the human-facing string shown in admin UIs.
|
|
10
|
+
*
|
|
11
|
+
* Contract: once an app deploys against a slug it is frozen — changing or
|
|
12
|
+
* removing a slug is a breaking change. `label` may change freely.
|
|
13
|
+
*/
|
|
14
|
+
export interface PermissionDefinition {
|
|
15
|
+
/** Stable `module[:resource]:action` identifier checked by `requirePermission`. */
|
|
16
|
+
slug: string;
|
|
17
|
+
/** Human-facing name surfaced in admin UIs when assigning permissions to roles. */
|
|
18
|
+
label: string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=permissionDefinition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionDefinition.d.ts","sourceRoot":"","sources":["../../../src/app/auth/permissionDefinition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,oBAAoB;IACnC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;CACf"}
|