Add customer contract clearance console

This commit is contained in:
xz
2026-09-01 14:38:42 +08:00
parent 1d4154dd20
commit 5849705d1e
19 changed files with 2431 additions and 25 deletions
+20
View File
@@ -3,6 +3,7 @@ import { createHash, randomBytes } from "node:crypto";
import { basename, dirname, relative, resolve } from "node:path";
import { dbAll, dbGet, dbRun } from "./db.mjs";
import { addAudit, hasPermission, httpError, requireEntitlement, requirePermission } from "./tenant.mjs";
import { evaluateProjectContractClearance, recordContractLicenseEvent } from "./contracts.mjs";
const projectRoot = resolve(import.meta.dirname, "..");
const defaultExpiryDays = 7;
@@ -287,6 +288,25 @@ export function createDeliveryAccessLink(context, releaseId, body = {}, options
if (release.status !== "published" || !release.output_path) {
throw httpError(409, "delivery_access_release_not_published", "只有已发布且存在发布产物的版本可以创建客户访问链接", { releaseId, status: release.status });
}
const contractClearance = evaluateProjectContractClearance(context, context.project.id, {
channelKind: "private-delivery-portal",
deliverables: ["vertical-video", "delivery-manifest"],
territory: body.territory || "CN"
});
recordContractLicenseEvent(context, {
projectId: context.project.id,
eventType: "contract.delivery_access.preflight",
status: contractClearance.status,
metadata: {
releaseId,
channelKind: "private-delivery-portal",
blockers: contractClearance.blockers.length,
reviewItems: contractClearance.reviewItems.length
}
});
if (contractClearance.status === "blocked") {
throw httpError(409, "delivery_access_contract_blocked", "客户访问链接未通过合同授权清算", { clearance: contractClearance, blockers: contractClearance.blockers });
}
const releaseFile = safeStoragePath(release.output_path);
if (!releaseFile || basename(releaseFile.relative) !== "release.json") {
throw httpError(409, "delivery_access_release_file_invalid", "发布产物路径不满足交付门户安全约束");