feat: establish NekoNest Cloud control and relay
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
export const LAUNCH_GATE_SEEDS = [
|
||||
["sealed-e2e", "P0", "security", "sealed 命令与附件端到端实证"],
|
||||
["expiry-boundary", "P0", "entitlement", "到期后的操作边界与重放测试"],
|
||||
["tenant-isolation", "P0", "infrastructure", "租户隔离、备份与删除验证"],
|
||||
["billing-idempotency", "PAID", "billing", "订单到权益的幂等与对账"],
|
||||
["pairing-claim-security", "P0", "security", "主机配对认领、限速与尝试预算"],
|
||||
["public-auth", "P0", "identity", "国内个人用户登录、恢复与管理员身份"],
|
||||
["legal-entity", "P0", "compliance", "免费公测主体、域名与备案路径"],
|
||||
["payment-provider", "PAID", "billing", "支付商户准入、验签、退款与对账"],
|
||||
["tax-invoice", "PAID", "compliance", "税务、含税口径与数电发票"],
|
||||
["privacy-retention", "P0", "privacy", "数据清单、保存、删除与跨境路径"],
|
||||
["terms-consumer", "PAID", "compliance", "付费服务条款、取消、退款与消费者规则"],
|
||||
["backup-restore", "P1", "operations", "备份与恢复演练"],
|
||||
["capacity-economics", "P1", "operations", "容量、成本与支持工时实测"],
|
||||
["beta-policy", "P1", "product", "公测结束、通知、宽限与反滥用限制"],
|
||||
["build-toolchain-audit", "P1", "security", "构建工具链残余公告与上游替换"],
|
||||
["account-lifecycle", "P1", "privacy", "导出、注销、保留例外与备份擦除"],
|
||||
["host-lifecycle-recovery", "P1", "operations", "主机恢复、换绑、停用、重装与凭据轮换"],
|
||||
["incident-response", "P1", "security", "安全事件分级、值守、通知与服务流程"],
|
||||
["release-provenance", "P1", "security", "PWA 构建来源、CSP、依赖与回滚 provenance"],
|
||||
] as const;
|
||||
|
||||
export const REQUIRED_PUBLIC_BETA_P0_KEYS = LAUNCH_GATE_SEEDS
|
||||
.filter(([, priority]) => priority === "P0")
|
||||
.map(([key]) => key);
|
||||
|
||||
export type LaunchGateEvidence = {
|
||||
key: string;
|
||||
priority: string;
|
||||
status: string;
|
||||
owner: string | null;
|
||||
notes: string;
|
||||
evidence_url: string | null;
|
||||
};
|
||||
|
||||
export function hasPassingGateEvidence(gate: LaunchGateEvidence): boolean {
|
||||
if (
|
||||
gate.status !== "passed"
|
||||
|| !gate.owner?.trim()
|
||||
|| !gate.notes.trim()
|
||||
|| !gate.evidence_url
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return new URL(gate.evidence_url).protocol === "https:";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function countBlockedPublicBetaP0(gates: readonly LaunchGateEvidence[]): number {
|
||||
const required = new Set<string>(REQUIRED_PUBLIC_BETA_P0_KEYS);
|
||||
const presentRequired = new Set(
|
||||
gates
|
||||
.filter((gate) => gate.priority === "P0" && required.has(gate.key))
|
||||
.map((gate) => gate.key),
|
||||
);
|
||||
const missingRequired = REQUIRED_PUBLIC_BETA_P0_KEYS.length - presentRequired.size;
|
||||
const invalidP0 = gates.filter(
|
||||
(gate) => gate.priority === "P0" && !hasPassingGateEvidence(gate),
|
||||
).length;
|
||||
return missingRequired + invalidP0;
|
||||
}
|
||||
|
||||
const requiredP0SqlList = REQUIRED_PUBLIC_BETA_P0_KEYS
|
||||
.map((key) => `'${key.replaceAll("'", "''")}'`)
|
||||
.join(", ");
|
||||
|
||||
/**
|
||||
* Fail closed when a required P0 row is missing or any P0 row lacks complete
|
||||
* passing evidence. This fragment is embedded only in repository-owned SQL.
|
||||
*/
|
||||
export const PUBLIC_BETA_GATE_READY_SQL = `
|
||||
(SELECT COUNT(*) FROM launch_gates
|
||||
WHERE priority = 'P0' AND key IN (${requiredP0SqlList})) = ${REQUIRED_PUBLIC_BETA_P0_KEYS.length}
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM launch_gates
|
||||
WHERE priority = 'P0'
|
||||
AND (
|
||||
status != 'passed'
|
||||
OR trim(COALESCE(owner, '')) = ''
|
||||
OR trim(COALESCE(notes, '')) = ''
|
||||
OR evidence_url IS NULL
|
||||
OR lower(evidence_url) NOT LIKE 'https://%'
|
||||
)
|
||||
)`;
|
||||
Reference in New Issue
Block a user