Auth Module Architecture Violations Report
Date: 2025-11-05
Analyzed Module: src/lib/auth/
Architecture Document: .cursorrules/domain-architecture.md
Summary
Found 4 violations in the admin module operations that don't follow the domain architecture patterns:
- Missing Zod schemas for parameters
- Inline parameter types instead of schemas from models.ts
- Inconsistent parameter handling for functions with no parameters
Violations Detail
1. admin/operations.ts - getKeysWithMetadata function
Location: Lines 33-66
Severity: Medium
Issue: Uses inline optional parameter object instead of a properly typed params schema from models.ts
Current Code:
export async function getKeysWithMetadata(
client: PoolClient,
filters?: {
isActive?: boolean;
keyId?: string;
}
): Promise<KeyWithMetadata[]>
Required Fix:
- Add to
admin/models.ts:
export const GetKeysWithMetadataParamsSchema = z.object({
isActive: z.boolean().optional(),
keyId: z.string().optional(),
});
export type GetKeysWithMetadataParams = z.infer<typeof GetKeysWithMetadataParamsSchema>;
- Update function signature:
export async function getKeysWithMetadata(
client: PoolClient,
params: GetKeysWithMetadataParams = {}
): Promise<KeyWithMetadata[]>
2. admin/operations.ts - rotateBulkKeys function
Location: Lines 569-701
Severity: High
Issue: Complex operation with options parameter and return type not defined as Zod schemas in models.ts
Current Code:
export async function rotateBulkKeys(
client: PoolClient,
options: {
dryRun?: boolean;
force?: boolean;
jwksManager?: any;
} = {}
): Promise<{
dry_run: boolean;
forced: boolean;
summary: {
total: number;
rotated: number;
skipped: number;
failed: number;
};
results: Array<{
key_id: string;
status: 'rotated' | 'unchanged' | 'skipped' | 'failed';
message: string;
old_kid?: string;
new_kid?: string;
}>;
}>
Required Fix:
- Add to
admin/models.ts:
export const RotateBulkKeysParamsSchema = z.object({
dryRun: z.boolean().optional(),
force: z.boolean().optional(),
jwksManager: z.unknown().optional(), // For dependency injection
});
export const RotateBulkKeySummarySchema = z.object({
total: z.number().int().nonnegative(),
rotated: z.number().int().nonnegative(),
skipped: z.number().int().nonnegative(),
failed: z.number().int().nonnegative(),
});
export const RotateBulkKeyResultEntrySchema = z.object({
key_id: z.string(),
status: z.enum(['rotated', 'unchanged', 'skipped', 'failed']),
message: z.string(),
old_kid: z.string().optional(),
new_kid: z.string().optional(),
});
export const RotateBulkKeysResultSchema = z.object({
dry_run: z.boolean(),
forced: z.boolean(),
summary: RotateBulkKeySummarySchema,
results: z.array(RotateBulkKeyResultEntrySchema),
});
export type RotateBulkKeysParams = z.infer<typeof RotateBulkKeysParamsSchema>;
export type RotateBulkKeysSummary = z.infer<typeof RotateBulkKeySummarySchema>;
export type RotateBulkKeyResultEntry = z.infer<typeof RotateBulkKeyResultEntrySchema>;
export type RotateBulkKeysResult = z.infer<typeof RotateBulkKeysResultSchema>;
- Update function signature:
export async function rotateBulkKeys(
client: PoolClient,
params: RotateBulkKeysParams = {}
): Promise<RotateBulkKeysResult>
3. admin/operations.ts - Missing EmptyParams usage
Location: Multiple functions
Severity: Low
Issue: Functions that take no parameters should use EmptyParams pattern for consistency
Affected Functions:
getSystemHealth(line 121)getRevocationStats(line 135)getRotationStatus(line 145)
Current Code:
export async function getSystemHealth(
client: PoolClient
): Promise<SystemHealth>
Required Fix:
export async function getSystemHealth(
client: PoolClient,
params: EmptyParams = {}
): Promise<SystemHealth>
Note: EmptyParamsSchema already exists in admin/models.ts, just need to use it consistently.
4. admin/operations.ts - logAdminAction function
Location: Lines 520-542
Severity: Medium
Issue: Uses inline action parameter object instead of a params schema
Current Code:
export async function logAdminAction(
client: PoolClient,
action: {
keyId: string;
action: string;
details: Record<string, any>;
message?: string;
}
): Promise<void>
Required Fix:
- Add to
admin/models.ts:
export const LogAdminActionParamsSchema = z.object({
keyId: z.string().min(1),
action: z.string().min(1),
details: z.record(z.string(), z.unknown()),
message: z.string().optional(),
});
export type LogAdminActionParams = z.infer<typeof LogAdminActionParamsSchema>;
- Update function signature:
export async function logAdminAction(
client: PoolClient,
params: LogAdminActionParams
): Promise<void>
Implementation Plan
Phase 1: Update admin/models.ts ✅ COMPLETE
- Add
GetKeysWithMetadataParamsSchema - Add
RotateBulkKeysParamsSchema,RotateBulkKeysResultSchema, and related schemas - Add
LogAdminActionParamsSchema - Export all inferred types
Phase 2: Update admin/operations.ts ✅ COMPLETE
- Fix
getKeysWithMetadatasignature - Fix
rotateBulkKeyssignature - Fix
logAdminActionsignature - Add
params: EmptyParams = {}to functions with no parameters - Update all function calls to use new signatures
Phase 3: Update admin/types.ts ✅ COMPLETE
- Types automatically re-exported via
export type * from './models'
Phase 4: Verification ✅ COMPLETE
- Verify all operations follow
(client, params) => Promise<Result>pattern - Check that no
Promise<any>exists - Ensure all operations have Zod schemas
- TypeScript compilation successful
Architecture Compliance Checklist
Per .cursorrules/domain-architecture.md, all operations must:
- ✅ Use Zod schemas for all serializable types
- ✅ All params must be defined as Zod schemas in models.ts
- ✅ Operations use
(PoolClient, params) => Promise<Result>signature - ✅ Never use
Promise<any>- all functions have typed returns - ✅ Functions with no params use
EmptyParamsfor consistency
Notes
- The admin module is generally well-structured and follows most patterns correctly
- Most violations were minor and involved parameter typing rather than architecture issues
- The secrets and jwt modules appear to be compliant with the architecture
- API layer classes correctly delegate to operations functions
Changes Made (2025-11-05)
admin/models.ts
- Added
GetKeysWithMetadataParamsSchemafor filtering keys - Added
LogAdminActionParamsSchemafor admin action logging - Added
RotateBulkKeysParamsSchemafor bulk rotation options - Added complete schemas for bulk rotation results:
RotateBulkKeySummarySchemaRotateBulkKeyResultEntrySchemaRotateBulkKeysResultSchema
- Exported all inferred types
admin/operations.ts
- Updated
getKeysWithMetadatato useGetKeysWithMetadataParams - Updated
logAdminActionto useLogAdminActionParams - Updated
rotateBulkKeysto useRotateBulkKeysParamsandRotateBulkKeysResult - Added
params: EmptyParams = {}to:getSystemHealthgetRevocationStatsgetRotationStatus
- Fixed TypeScript errors with proper type handling for injected dependencies
Verification
All functions in admin/operations.ts now follow the required pattern:
export async function operationName(
client: PoolClient,
params: OperationNameParams
): Promise<OperationNameResult>
✅ All violations have been fixed and the auth module is now fully compliant with the domain architecture.