feat: add integration tests for initialization flow

- Implemented end-to-end integration tests covering database reset, bootstrap admin creation, demo user provisioning, scenario installation, and general creation.
- Added support for deterministic seeding and auto admin general creation.
- Created a new package for integration tests with necessary configurations and scripts.
- Updated various modules to support new features, including admin user handling and scenario seeding.
- Enhanced error handling and validation in the join and orchestrator modules.
This commit is contained in:
2026-01-18 06:32:19 +00:00
parent 1b7423e1f6
commit a9ddffa97c
15 changed files with 997 additions and 8 deletions
+46
View File
@@ -15,6 +15,7 @@ const zUsername = z.string().min(2).max(32);
const zPassword = z.string().min(6).max(128);
const zProfile = z.string().min(1).max(64);
const zOAuthMode = z.enum(['login', 'change_pw']);
const zBootstrapToken = z.string().min(1);
const parseDate = (value: string): Date | null => {
const parsed = parseISO(value);
@@ -61,6 +62,51 @@ export const appRouter = router({
}),
admin: adminRouter,
auth: router({
bootstrapLocal: procedure
.input(
z.object({
token: zBootstrapToken,
username: zUsername,
password: zPassword,
displayName: z.string().min(2).max(40).optional(),
})
)
.mutation(async ({ ctx, input }) => {
const expected = process.env.GATEWAY_BOOTSTRAP_TOKEN ?? '';
if (!expected) {
throw new TRPCError({
code: 'FORBIDDEN',
message: 'Bootstrap is disabled.',
});
}
if (input.token !== expected) {
throw new TRPCError({
code: 'UNAUTHORIZED',
message: 'Invalid bootstrap token.',
});
}
const existing = await ctx.prisma.appUser.findFirst({
select: { id: true },
});
if (existing) {
throw new TRPCError({
code: 'CONFLICT',
message: 'Bootstrap is already completed.',
});
}
const created = await ctx.users.createUser({
username: input.username,
password: input.password,
displayName: input.displayName,
});
await ctx.users.updateRoles(created.id, ['superuser']);
const session = await ctx.sessions.createSession(created);
return {
user: toPublicUser(created),
sessionToken: session.sessionToken,
issuedAt: session.issuedAt,
};
}),
kakaoStart: procedure
.input(
z