import type { FastifyInstance } from 'fastify'; import { z } from 'zod'; import { AmbiguousAppTenantError, type PlatformBootstrap } from '../tenancy/platform-config-repository.js'; const headerSchema = z.object({ 'x-wechat-appid': z.string().trim().min(6).max(64), 'tenant-id': z.string().regex(/^[1-9]\d{0,19}$/).optional() }); export interface PlatformConfigResolver { resolveBootstrap(appId: string, tenantId?: string): Promise; } export async function registerPlatformBootstrapRoutes( app: FastifyInstance, repository: PlatformConfigResolver ): Promise { app.get('/app-api/bootstrap', async (request, reply) => { const parsed = headerSchema.safeParse(request.headers); if (!parsed.success) { return reply.status(400).send({ code: 'INVALID_APP_CONTEXT', message: 'x-wechat-appid is required and tenant-id must be a positive integer.', traceId: request.traceId }); } try { const bootstrap = await repository.resolveBootstrap( parsed.data['x-wechat-appid'], parsed.data['tenant-id'] ); if (!bootstrap) { return reply.status(404).send({ code: 'APP_TENANT_NOT_FOUND', message: 'The application and tenant binding is not active.', traceId: request.traceId }); } return { code: 0, data: bootstrap, traceId: request.traceId }; } catch (error) { if (error instanceof AmbiguousAppTenantError) { return reply.status(409).send({ code: 'TENANT_SELECTION_REQUIRED', message: error.message, traceId: request.traceId }); } throw error; } }); }