完善 readiness、发布追溯与敏感治理(07-15-production-trust-closeout-cleanup)

这个提交包含在:
2026-07-16 05:17:38 +08:00
父节点 abb6a22f5c
当前提交 28e8e746b7
共修改 29 个文件,包含 1849 行新增和 233 行删除
+13 -13
查看文件
@@ -104,8 +104,10 @@ function setStaticCacheHeaders(res, filePath) {
}
}
async function buildApp() {
async function buildApp(dependencies = {}) {
const config = getConfig();
const prismaPluginImpl = dependencies.prismaPlugin ?? prismaPlugin;
const startJobsImpl = dependencies.startJobs ?? startJobs;
const app = fastify({
logger: {
@@ -246,7 +248,7 @@ async function buildApp() {
});
});
await app.register(prismaPlugin);
await app.register(prismaPluginImpl);
await app.register(authPlugin);
if (config.nodeEnv !== "production" && config.openapiDocsEnabled) {
@@ -254,10 +256,6 @@ async function buildApp() {
app.log.info("OpenAPI docs enabled at /api/docs");
}
if (config.otelTracesEnabled) {
app.log.info("OTel tracing enabled");
}
app.get(
"/health",
{
@@ -267,16 +265,17 @@ async function buildApp() {
response: {
200: buildDataEnvelopeSchema({
type: "object",
required: ["ok"],
required: ["ok", "buildSha"],
properties: {
ok: { type: "boolean" },
buildSha: { type: "string" },
},
}),
},
},
},
async (request, reply) => {
return reply.send({ requestId: request.id, data: { ok: true } });
return reply.send({ requestId: request.id, data: { ok: true, buildSha: app.config.buildSha } });
},
);
@@ -289,16 +288,17 @@ async function buildApp() {
response: {
200: buildDataEnvelopeSchema({
type: "object",
required: ["ok"],
required: ["ok", "buildSha"],
properties: {
ok: { type: "boolean" },
buildSha: { type: "string" },
},
}),
503: buildErrorEnvelopeSchema({
description: "数据库不可用",
codeExample: "SYS_503",
messageExample: "Service Unavailable",
detailsExample: { db: "unreachable" },
detailsExample: { db: "unreachable", buildSha: "abcdef123456" },
}),
},
},
@@ -306,14 +306,14 @@ async function buildApp() {
async (request, reply) => {
try {
await app.prisma.$queryRaw`SELECT 1`;
return reply.send({ requestId: request.id, data: { ok: true } });
return reply.send({ requestId: request.id, data: { ok: true, buildSha: app.config.buildSha } });
} catch (error) {
app.log.error({ err: error, requestId: request.id }, "Readiness check failed");
throw new AppError({
code: "SYS_503",
message: "Service Unavailable",
statusCode: 503,
details: { db: "unreachable" },
details: { db: "unreachable", buildSha: app.config.buildSha },
});
}
},
@@ -399,7 +399,7 @@ async function buildApp() {
await app.register(aiRoutes, { prefix: "/api" });
await app.register(exportsRoutes, { prefix: "/api" });
await startJobs(app);
await startJobsImpl(app);
return app;
}