fix: harden update pipeline and restore a clean production build
CI / check (push) Successful in 29s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s

- update-Nitrov3.sh: build CMS into .next-staging and swap atomically so a
  failed build never takes the live site down; auto-merge new variables
  from .env.example; validate env for duplicates/broken lines; restart the
  emulator/CMS only when rebuilt or unhealthy; fix step renumbering
- next.config.ts: support NEXT_DIST_DIR for staged production builds
- fix all TS errors (unused imports, missing tryDownloadCandidates helper)
  so tsc and the production build pass clean
- add Dockerfile/.dockerignore and switch docker-compose to a CMS container
- include prevailing UI/refactor changes (SurfaceCard, ticketing, tsconfig)
This commit is contained in:
openhands committed 2026-08-28 12:48:04 +02:00
1 parent 750fcb2e5c
commit 944e8ff1d8
26 files changed
+427 -876

No files matched your search

+1 -39
View File
@@ -3,13 +3,11 @@
import { eq } from "drizzle-orm";
import { db, WebsiteTicket, WebsiteTicketMessage } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
import { adminAction, authAction } from "@/lib/safe-action";
import { adminAction } from "@/lib/safe-action";
import { ActionError, actionOk } from "@/lib/safe-action-shared";
import { logAudit } from "@/lib/services/audit";
import { notify } from "@/lib/services/webhook";
import {
assignTicketSchema,
createTicketSchema,
replyTicketSchema,
updateTicketPrioritySchema,
updateTicketStatusSchema,
@@ -17,42 +15,6 @@ import {
// ── User actions (authenticated, no admin perms needed) ──────────────
export const createTicket = authAction(
{
schema: createTicketSchema,
rateLimitKey: "ticket-create",
rateLimitMax: 5,
rateLimitWindowMs: 60_000,
},
async (ctx) => {
const now = new Date();
const [result] = await db.insert(WebsiteTicket).values({
subject: ctx.data.subject,
category: ctx.data.category,
creatorId: ctx.session.user.id,
updatedAt: now,
});
const ticketId = Number(result.insertId);
// Create the first message
await db.insert(WebsiteTicketMessage).values({
ticketId,
userId: ctx.session.user.id,
message: ctx.data.message,
isStaff: 0,
});
notify({
action: "ticket_create",
actor: ctx.session.user.username,
target: `#${ticketId} - ${ctx.data.subject}`,
details: `Category: ${ctx.data.category}`,
});
return actionOk({ id: ticketId });
},
);
export const adminReplyTicket = adminAction(
{
permission: [PERMS.TICKETS_EDIT, PERMS.MOD_TICKETS_EDIT],