Phase1: Schema + skill event tracking
Some checks failed
Build and Push / build (push) Failing after 38s
Some checks failed
Build and Push / build (push) Failing after 38s
This commit is contained in:
@@ -3,6 +3,7 @@ import { z } from "zod";
|
||||
import { getSessionUser, canMutate } from "@/lib/session";
|
||||
import { getTenant, patchTenantSpec, setTenantAnnotation } from "@/lib/k8s";
|
||||
import { canUserSeeTenant } from "@/lib/visibility";
|
||||
import { recordSuspensionEvent } from "@/lib/db";
|
||||
import { safeError } from "@/lib/errors";
|
||||
|
||||
const patchSchema = z.object({
|
||||
@@ -101,6 +102,33 @@ export async function PATCH(
|
||||
try {
|
||||
await patchTenantSpec(name, { suspend });
|
||||
|
||||
// Billing — Phase 1: record the transition so monthly proration
|
||||
// can exclude suspended days from the fixed fee. The portal
|
||||
// commands this transition; the operator's status.suspendedAt
|
||||
// lags by a reconcile cycle (seconds), which is irrelevant for
|
||||
// monthly billing. Best-effort: a logging failure never blocks
|
||||
// the suspend/resume itself.
|
||||
try {
|
||||
const orgId =
|
||||
tenant.metadata.labels?.["pieced.ch/zitadel-org-id"] ?? null;
|
||||
if (orgId) {
|
||||
await recordSuspensionEvent(
|
||||
name,
|
||||
orgId,
|
||||
suspend ? "suspended" : "resumed"
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
`billing: tenant ${name} has no zitadel-org-id label; suspension event not recorded`
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`billing: failed to record suspension event for ${name}:`,
|
||||
e
|
||||
);
|
||||
}
|
||||
|
||||
// On admin-side resume, also clear the pending-resume-request
|
||||
// annotation if it exists. Belt-and-suspenders: the admin-approve
|
||||
// endpoint already clears it on its happy path, but a platform
|
||||
|
||||
Reference in New Issue
Block a user