134 lines
6.5 KiB
JavaScript
134 lines
6.5 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { dbRun } from "../server/db.mjs";
|
|
|
|
const api = process.env.AI_DRAMA_API_BASE || "http://127.0.0.1:8787";
|
|
const scope = {
|
|
"x-organization-id": "org-studio-lab",
|
|
"x-workspace-id": "ws-local-aidrama",
|
|
"x-project-id": "thunder-mouth"
|
|
};
|
|
|
|
async function request(path, headers = {}, options = {}) {
|
|
const response = await fetch(`${api}${path}`, {
|
|
...options,
|
|
headers: { "content-type": "application/json", ...headers, ...(options.headers || {}) }
|
|
});
|
|
const payload = await response.json().catch(() => ({}));
|
|
return { response, payload };
|
|
}
|
|
|
|
function assertOk(result, label) {
|
|
assert.equal(result.response.ok, true, `${label}: ${result.response.status} ${result.payload.detail || result.payload.error || ""}`);
|
|
return result.payload;
|
|
}
|
|
|
|
async function login(email) {
|
|
const result = await request("/api/auth/login", {}, {
|
|
method: "POST",
|
|
body: JSON.stringify({ email, password: "Demo@123456" })
|
|
});
|
|
return { authorization: `Bearer ${assertOk(result, `${email} 登录`).session.token}` };
|
|
}
|
|
|
|
function findEntitlement(payload, key) {
|
|
const entitlement = payload.entitlements?.find((item) => item.key === key);
|
|
assert.ok(entitlement, `缺少权益 ${key}`);
|
|
return entitlement;
|
|
}
|
|
|
|
function entitlementSnapshot(entitlement) {
|
|
return {
|
|
limitValue: Number(entitlement.limitValue || 0),
|
|
enabled: Boolean(entitlement.enabled),
|
|
enforcement: entitlement.enforcement || "block",
|
|
source: entitlement.source || "plan",
|
|
overrideReason: entitlement.overrideReason || ""
|
|
};
|
|
}
|
|
|
|
const owner = { ...(await login("producer@local.test")), ...scope };
|
|
const writer = { ...(await login("writer@local.test")), ...scope };
|
|
const createdRequestIds = [];
|
|
let originalKnowledgeEntitlement = null;
|
|
|
|
try {
|
|
const commercial = assertOk(await request("/api/organizations/org-studio-lab/commercial", owner), "读取商业运营");
|
|
assert.ok(Array.isArray(commercial.commercialApprovalCatalog) && commercial.commercialApprovalCatalog.length >= 6, "商业审批类型目录缺失");
|
|
assert.ok(commercial.commercialApprovalSummary && Number.isFinite(commercial.commercialApprovalSummary.total), "商业审批摘要缺失");
|
|
|
|
const knowledgeEntitlement = findEntitlement(commercial, "limit.knowledge_documents");
|
|
originalKnowledgeEntitlement = entitlementSnapshot(knowledgeEntitlement);
|
|
const requestedLimit = Number(knowledgeEntitlement.limitValue || 0) + 13;
|
|
|
|
const crossTenant = await request("/api/organizations/org-studio-lab/commercial-approvals", writer, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
requestType: "entitlement_overage",
|
|
targetKey: "limit.knowledge_documents",
|
|
requestedValue: requestedLimit,
|
|
workspaceId: "ws-northstar-main",
|
|
businessReason: "验证商业审批不能把申请单挂到其他组织工作区。"
|
|
})
|
|
});
|
|
assert.equal(crossTenant.response.status, 403, "跨组织工作区绑定必须被拒绝");
|
|
assert.equal(crossTenant.payload.error, "approval_workspace_scope_mismatch", "跨组织审批错误码不稳定");
|
|
|
|
const submitted = assertOk(await request("/api/organizations/org-studio-lab/commercial-approvals", writer, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
requestType: "entitlement_overage",
|
|
targetKey: "limit.knowledge_documents",
|
|
requestedValue: requestedLimit,
|
|
priority: "high",
|
|
title: "Smoke 知识库素材额度扩容",
|
|
businessReason: "导入原创小说后需要更多知识库分块素材,仍限定本地 RAG 和原创商用证据。",
|
|
evidence: { evidenceRef: "smoke://commercial-approval/knowledge-entitlement" }
|
|
})
|
|
}), "提交商业审批");
|
|
createdRequestIds.push(submitted.request.id);
|
|
assert.equal(submitted.request.status, "submitted", "新申请应处于待审批状态");
|
|
|
|
const mine = assertOk(await request("/api/organizations/org-studio-lab/commercial-approvals?mine=1", writer), "读取我的申请");
|
|
assert.ok(mine.requests.some((item) => item.id === submitted.request.id), "申请人必须能看到自己的商业审批");
|
|
|
|
const decided = assertOk(await request(`/api/organizations/org-studio-lab/commercial-approvals/${encodeURIComponent(submitted.request.id)}/decision`, owner, {
|
|
method: "POST",
|
|
body: JSON.stringify({ decision: "approved", decisionNote: "smoke 自动审批扩容" })
|
|
}), "审批通过商业申请");
|
|
assert.equal(decided.request.status, "approved", "审批通过后状态应变为 approved");
|
|
assert.equal(decided.request.effect?.kind, "entitlement_overridden", "权益扩容审批应自动同步组织权益");
|
|
assert.equal(findEntitlement(decided.commercial, "limit.knowledge_documents").limitValue, requestedLimit, "知识库素材额度未按审批结果提升");
|
|
|
|
const cancelTarget = commercial.costCenters?.[0]?.code || "local-gpu";
|
|
const cancellable = assertOk(await request("/api/organizations/org-studio-lab/commercial-approvals", writer, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
requestType: "budget_increase",
|
|
targetKey: cancelTarget,
|
|
requestedValue: 999,
|
|
priority: "low",
|
|
title: "Smoke 可取消预算申请",
|
|
businessReason: "验证申请人可以取消尚未审批的商业治理申请。"
|
|
})
|
|
}), "提交可取消申请");
|
|
createdRequestIds.push(cancellable.request.id);
|
|
const cancelled = assertOk(await request(`/api/organizations/org-studio-lab/commercial-approvals/${encodeURIComponent(cancellable.request.id)}/decision`, writer, {
|
|
method: "POST",
|
|
body: JSON.stringify({ decision: "cancelled", decisionNote: "smoke 自助取消" })
|
|
}), "申请人取消申请");
|
|
assert.equal(cancelled.request.status, "cancelled", "申请人取消后状态应为 cancelled");
|
|
|
|
console.log(`commercial approvals smoke passed: ${api}`);
|
|
} finally {
|
|
if (originalKnowledgeEntitlement) {
|
|
dbRun(
|
|
"UPDATE organization_entitlements SET limit_value = ?, enabled = ?, enforcement = ?, source = ?, override_reason = ?, updated_at = ? WHERE organization_id = 'org-studio-lab' AND entitlement_key = 'limit.knowledge_documents'",
|
|
[originalKnowledgeEntitlement.limitValue, originalKnowledgeEntitlement.enabled ? 1 : 0, originalKnowledgeEntitlement.enforcement, originalKnowledgeEntitlement.source, originalKnowledgeEntitlement.overrideReason, new Date().toISOString()]
|
|
);
|
|
}
|
|
for (const requestId of createdRequestIds) {
|
|
dbRun("DELETE FROM audit_logs WHERE target_type = 'commercial_approval_request' AND target_id = ?", [requestId]);
|
|
dbRun("DELETE FROM commercial_approval_requests WHERE id = ?", [requestId]);
|
|
}
|
|
}
|