feat: 完成P13治理收尾并创建P14执行合同(Issue: P13-1,P13-2,P13-3,P13-4,P13-5,P13-6,P13-7,P13-8,P14-0)

这个提交包含在:
2026-02-13 00:25:04 +08:00
父节点 3b221a2202
当前提交 1412fead5d
共修改 30 个文件,包含 3988 行新增和 105 行删除
+54 -5
查看文件
@@ -14,6 +14,7 @@ const staticPlugin = require("@fastify/static");
const { getConfig } = require("./config");
const authPlugin = require("./plugins/auth");
const prismaPlugin = require("./plugins/prisma");
const swaggerDocsPlugin = require("./plugins/swagger");
const authRoutes = require("./routes/auth");
const meRoutes = require("./routes/me");
const reimbursementRoutes = require("./routes/reimbursements");
@@ -38,6 +39,7 @@ const travelOrdersRoutes = require("./routes/travelOrders");
const { startJobs } = require("./jobs/jobSystem");
const { initMetrics } = require("./observability");
const { AppError } = require("./utils/AppError");
const { buildDataEnvelopeSchema, buildErrorEnvelopeSchema } = require("./utils/openapi");
async function buildApp() {
const config = getConfig();
@@ -180,11 +182,57 @@ async function buildApp() {
await app.register(prismaPlugin);
await app.register(authPlugin);
app.get("/health", async (request, reply) => {
return reply.send({ requestId: request.id, data: { ok: true } });
});
if (config.nodeEnv !== "production" && config.openapiDocsEnabled) {
await app.register(swaggerDocsPlugin);
app.log.info("OpenAPI docs enabled at /api/docs");
}
app.get("/ready", async (request, reply) => {
app.get(
"/health",
{
schema: {
summary: "Health check",
tags: ["system"],
response: {
200: buildDataEnvelopeSchema({
type: "object",
required: ["ok"],
properties: {
ok: { type: "boolean" },
},
}),
},
},
},
async (request, reply) => {
return reply.send({ requestId: request.id, data: { ok: true } });
},
);
app.get(
"/ready",
{
schema: {
summary: "Readiness check",
tags: ["system"],
response: {
200: buildDataEnvelopeSchema({
type: "object",
required: ["ok"],
properties: {
ok: { type: "boolean" },
},
}),
503: buildErrorEnvelopeSchema({
description: "数据库不可用",
codeExample: "SYS_503",
messageExample: "Service Unavailable",
detailsExample: { db: "unreachable" },
}),
},
},
},
async (request, reply) => {
try {
await app.prisma.$queryRaw`SELECT 1`;
return reply.send({ requestId: request.id, data: { ok: true } });
@@ -197,7 +245,8 @@ async function buildApp() {
details: { db: "unreachable" },
});
}
});
},
);
if (config.metricsEnabled) {
initMetrics(app);