feat: establish NekoNest Cloud control and relay
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
export type DataInventoryGroup = {
|
||||
id: string;
|
||||
title: string;
|
||||
status: "active" | "security" | "operational" | "dormant";
|
||||
summary: string;
|
||||
examples: readonly string[];
|
||||
purpose: string;
|
||||
retention: string;
|
||||
userControl: string;
|
||||
tables: readonly string[];
|
||||
};
|
||||
|
||||
export const DATA_INVENTORY: readonly DataInventoryGroup[] = [
|
||||
{
|
||||
id: "account",
|
||||
title: "账户与登录身份",
|
||||
status: "active",
|
||||
summary: "识别登录用户,并把 Cloud 资源隔离到正确账户。",
|
||||
examples: ["账户 ID", "登录提供方主体标识", "邮箱", "显示名称", "账户状态与时间"],
|
||||
purpose: "登录、账户隔离、管理员核对和用户数据导出。",
|
||||
retention: "最终保存期尚未确定;当前随账户保留,注销申请进入人工核对队列。",
|
||||
userControl: "控制台可下载账户范围导出,并提交或撤回注销申请。",
|
||||
tables: ["accounts"],
|
||||
},
|
||||
{
|
||||
id: "host-security",
|
||||
title: "主机、设备与配对安全",
|
||||
status: "security",
|
||||
summary: "把用户主机安全地认领到所属账户,并支持撤销和恢复。",
|
||||
examples: ["主机名称与 OS", "daemon 版本", "公钥与身份指纹", "配对状态", "令牌摘要", "限速来源摘要"],
|
||||
purpose: "配对认领、设备认证、槽位管理、重放拒绝、限速和安全恢复。",
|
||||
retention: "明文配对码十分钟失效且不写入 D1;成功认领立即烧毁原摘要,其他过期摘要在维护时转为 tombstone。丢失响应恢复只保存由 daemon 一次性 retry key 加密的响应,十分钟后删除。来源限速窗口保留 24 小时,配对尝试保留 30 天。主机历史与凭据摘要的最终保存期尚未确定。",
|
||||
userControl: "可取消未认领配对、撤销主机令牌;账户导出不包含令牌、配对码、摘要或内部密钥。",
|
||||
tables: [
|
||||
"hosts",
|
||||
"pairing_requests",
|
||||
"device_credentials",
|
||||
"pairing_claim_rate_limits",
|
||||
"pairing_claim_attempts",
|
||||
"device_registration_replays",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "tenant-runtime",
|
||||
title: "租户、区域与授权状态",
|
||||
status: "operational",
|
||||
summary: "记录租户所属主区域、唯一 Relay placement generation 与当前授权 revision。",
|
||||
examples: ["租户 ID 与 slug", "home region", "placement generation", "迁移阶段与备份摘要", "authorization revision"],
|
||||
purpose: "稳定端点路由、唯一写入节点 fencing、可回滚迁移、租户暂停和设备撤销传播。",
|
||||
retention: "管理员只能针对已确认的注销申请启动永久逻辑删除;Relay 会先关闭 Engine,再删除实时 SQLite、附件和该租户全部备份,并回传摘要证据。云存储物理块擦除、法定保留和最终账户身份清除仍须按上线政策核定。",
|
||||
userControl: "用户可先提交并在处理前撤回注销申请;删除启动后访问立即暂停且不可撤回。账户导出不包含内部节点地址或删除账本。",
|
||||
tables: ["tenant_instances", "tenant_placements", "tenant_authorization_state", "relay_migrations", "relay_purge_jobs"],
|
||||
},
|
||||
{
|
||||
id: "relay-infrastructure",
|
||||
title: "Relay 区域、节点与内部身份",
|
||||
status: "security",
|
||||
summary: "维护共享 Relay 池的区域、节点、签名公钥和经 mTLS 绑定的节点凭据摘要。",
|
||||
examples: ["区域代码", "节点状态", "证书指纹", "SPIFFE ID", "签名 kid 与公钥"],
|
||||
purpose: "节点认证、授权快照签名、容量调度、故障隔离和密钥轮换。",
|
||||
retention: "当前作为安全与运维状态保留;D1 不保存签名私钥或明文节点 bearer,轮换和退役记录的最终期限尚未确定。",
|
||||
userControl: "属于内部基础设施元数据,不进入账户自助导出;用户数据导出不暴露节点地址、凭据摘要或密钥引用。",
|
||||
tables: ["relay_regions", "relay_nodes", "relay_signing_keys", "relay_node_credentials"],
|
||||
},
|
||||
{
|
||||
id: "phone-relay-access",
|
||||
title: "手机 handoff 与 Relay 路由凭据",
|
||||
status: "security",
|
||||
summary: "把 Cloud 登录会话一次性交给目标 Relay,并验证后续手机路由和手机凭据属于同一租户。",
|
||||
examples: ["handoff ticket 摘要", "预期 PWA origin", "route handle 摘要", "phone token 摘要", "手机 E2E 公钥"],
|
||||
purpose: "单次 handoff、防重放、租户路由、可撤销手机身份和 sealed E2E 配对。",
|
||||
retention: "D1 从不保存明文 ticket、route handle 或 phone token;已消费或过期 ticket 在 24 小时后由维护任务删除,route 与 phone principal 随撤销和租户删除策略处理。",
|
||||
userControl: "Cloud 登录不自动授予任何设备访问;手机仍须逐设备配对,撤销 phone principal 会同时使对应 route handle 失效。",
|
||||
tables: ["phone_handoff_tickets", "phone_route_handles", "relay_phone_principals"],
|
||||
},
|
||||
{
|
||||
id: "beta-entitlement",
|
||||
title: "免费公测资格",
|
||||
status: "active",
|
||||
summary: "决定当前账户可以接入多少台主机,不用于积分或余额。",
|
||||
examples: ["公测开关", "容量上限", "闭测申请场景", "闭测邀请", "起止时间", "处理状态与说明"],
|
||||
purpose: "公开测试容量控制、闭测申请审核、邀请签发和到期边界。",
|
||||
retention: "申请、政策和权益记录当前作为状态及审计证据随账户保留;最终保存期尚未确定。",
|
||||
userControl: "控制台可提交或撤回一条待处理申请,查看审核说明、当前资格、容量和下一次变化;不会据此自动创建订单或扣款。",
|
||||
tables: ["beta_programs", "entitlement_grants", "beta_access_requests"],
|
||||
},
|
||||
{
|
||||
id: "support-lifecycle",
|
||||
title: "反馈与账户退出",
|
||||
status: "active",
|
||||
summary: "接收公测问题、管理员回复,以及记录可撤回的注销意愿。",
|
||||
examples: ["反馈分类与正文", "管理员回复", "处理状态", "注销原因", "申请与撤回时间"],
|
||||
purpose: "解决公测问题,并让账户退出流程可追踪而不是只隐藏界面。",
|
||||
retention: "最终保存期和注销完成时限尚未确定;真实租户卷与备份擦除闭环完成前不会伪装成已删除。",
|
||||
userControl: "反馈和注销记录进入账户导出;注销申请在处理前可以撤回。",
|
||||
tables: ["beta_feedback", "account_deletion_requests"],
|
||||
},
|
||||
{
|
||||
id: "operations",
|
||||
title: "服务状态、审计与幂等记录",
|
||||
status: "operational",
|
||||
summary: "证明管理员做过什么、故障何时发生,并阻止重复写操作。",
|
||||
examples: ["上线门禁", "故障公告", "动作与对象 ID", "变更前后摘要", "幂等请求摘要", "自动清理状态", "schema 版本"],
|
||||
purpose: "服务公告、故障恢复、管理动作追溯、重复请求防护、到期数据最小化和数据库安全升级。",
|
||||
retention: "幂等记录带技术到期时间;每日自动清理与管理员手工回退处理既有技术记录及已消费或过期 24 小时的 handoff ticket。自动任务只覆盖一条最近状态和累计计数,不保存逐次运行历史;审计及其他记录的最终保存期仍是公测门禁。",
|
||||
userControl: "公开状态和门禁可直接查看;内部审计、请求摘要和迁移账本不进入自助账户导出。",
|
||||
tables: [
|
||||
"launch_gates",
|
||||
"service_incidents",
|
||||
"audit_events",
|
||||
"idempotency_records",
|
||||
"maintenance_jobs",
|
||||
"cloud_schema_migrations",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "dormant-billing",
|
||||
title: "休眠的收费表结构",
|
||||
status: "dormant",
|
||||
summary: "为未来可能的收费保留结构,但免费公测期间禁止创建业务记录。",
|
||||
examples: ["价格版本", "订单", "付款尝试", "发票", "退款"],
|
||||
purpose: "当前没有用户用途;相关 API 服务端拒绝写入,未来启用前必须重新决策和审查。",
|
||||
retention: "免费公测期间不应产生这类记录;若未来启用,须先另行确定保存、退款和财税规则。",
|
||||
userControl: "没有报价、支付或余额入口,也不会在公测结束时自动扣款。",
|
||||
tables: ["price_versions", "orders", "payment_attempts", "invoices", "refunds"],
|
||||
},
|
||||
] as const;
|
||||
|
||||
export const INVENTORIED_TABLES = DATA_INVENTORY.flatMap((group) => group.tables);
|
||||
|
||||
export const CONTROL_PLANE_EXCLUSIONS = [
|
||||
{
|
||||
item: "项目文件和任意磁盘目录内容",
|
||||
boundary: "不应上传到 Cloud 控制面。",
|
||||
},
|
||||
{
|
||||
item: "coding-agent 原生会话库与 transcript",
|
||||
boundary: "由本地主机的原生 store 管理,不进入控制平面 D1。",
|
||||
},
|
||||
{
|
||||
item: "Agent CLI、模型账户和 API Key",
|
||||
boundary: "只留在用户主机,Cloud 不需要这些凭据。",
|
||||
},
|
||||
{
|
||||
item: "明文配对码、明文设备/手机/节点令牌和签名私钥",
|
||||
boundary: "仅在必要的签发或请求中短暂处理,不持久化到 D1;D1 只保存摘要。",
|
||||
},
|
||||
] as const;
|
||||
@@ -0,0 +1,92 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { PublicShell, StatusPill } from "../components/Shells";
|
||||
import { CONTROL_PLANE_EXCLUSIONS, DATA_INVENTORY } from "./data-inventory";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "公测数据说明",
|
||||
description: "NekoNest Cloud 免费公测当前保存的数据、用途、退出方式和尚未完成的保存与删除边界。",
|
||||
};
|
||||
|
||||
const statusCopy = {
|
||||
active: { label: "公测使用", tone: "good" },
|
||||
security: { label: "安全必需", tone: "info" },
|
||||
operational: { label: "运维必需", tone: "neutral" },
|
||||
dormant: { label: "未启用", tone: "warn" },
|
||||
} as const;
|
||||
|
||||
export default function PrivacyPage() {
|
||||
return (
|
||||
<PublicShell>
|
||||
<section className="subpage-hero privacy-hero">
|
||||
<div className="subpage-hero-inner">
|
||||
<span className="eyebrow">BETA DATA MAP / 公测数据说明</span>
|
||||
<h1>先把实际保存的数据说清楚。</h1>
|
||||
<p>这不是一份拿模板拼出的最终隐私政策,而是与当前控制平面代码对齐的数据清单:保存什么、为什么需要、用户能做什么,以及哪些保存与删除问题仍没有完成。</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="section data-map-section">
|
||||
<div className="section-heading split-heading">
|
||||
<div><span className="eyebrow">CURRENT INVENTORY</span><h2>当前控制平面的完整记录类型。</h2></div>
|
||||
<p>收费表结构被单独标为休眠;它们存在不等于公测期间会生成订单或付款记录。</p>
|
||||
</div>
|
||||
<div className="data-map-grid">
|
||||
{DATA_INVENTORY.map((group) => {
|
||||
const status = statusCopy[group.status];
|
||||
return (
|
||||
<article className={`data-map-card data-map-${group.status}`} key={group.id}>
|
||||
<div className="data-map-card-heading">
|
||||
<span>{group.id.toUpperCase()}</span>
|
||||
<StatusPill tone={status.tone}>{status.label}</StatusPill>
|
||||
</div>
|
||||
<h3>{group.title}</h3>
|
||||
<p>{group.summary}</p>
|
||||
<ul className="data-example-list">
|
||||
{group.examples.map((example) => <li key={example}>{example}</li>)}
|
||||
</ul>
|
||||
<dl className="data-map-details">
|
||||
<div><dt>用途</dt><dd>{group.purpose}</dd></div>
|
||||
<div><dt>保存</dt><dd>{group.retention}</dd></div>
|
||||
<div><dt>用户控制</dt><dd>{group.userControl}</dd></div>
|
||||
</dl>
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="section not-collected-section">
|
||||
<div className="policy-grid">
|
||||
<div><span className="eyebrow">CONTROL-PLANE BOUNDARY</span><h2>不上传,或不持久化。</h2></div>
|
||||
<div>
|
||||
<ul className="not-collected-list">
|
||||
{CONTROL_PLANE_EXCLUSIONS.map((entry) => <li key={entry.item}><strong>{entry.item}</strong><span>{entry.boundary}</span></li>)}
|
||||
</ul>
|
||||
<p className="privacy-boundary-note">sealed 中继和附件尚未完成真实端到端实证,因此这里描述的是控制平面设计与当前持久化边界,不是“运营方绝对无法看到明文”的承诺。</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="section privacy-actions-section">
|
||||
<div className="section-heading split-heading">
|
||||
<div><span className="eyebrow">YOUR CONTROLS</span><h2>已经可以使用的数据出口。</h2></div>
|
||||
<p>登录后可以下载账户范围 JSON、撤销主机令牌,以及提交或撤回注销申请。原生会话和项目文件仍由用户在自己的主机管理。</p>
|
||||
</div>
|
||||
<div className="privacy-action-grid">
|
||||
<article><span>01</span><h3>下载 Cloud 数据</h3><p>导出账户、主机、配对、免费权益、租户运行态、反馈和注销申请。</p><Link href="/dashboard/security">前往安全与设备 →</Link></article>
|
||||
<article><span>02</span><h3>立即撤销主机</h3><p>设备令牌立即失效并释放槽位,不受现在或未来的收费状态阻止。</p><Link href="/dashboard/hosts">管理主机 →</Link></article>
|
||||
<article><span>03</span><h3>申请账户注销</h3><p>申请可以撤回;租户卷、备份和保留例外核对完成前不会误报为已经删除。</p><Link href="/dashboard/security">查看账户动作 →</Link></article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="privacy-open-items" aria-labelledby="privacy-open-heading">
|
||||
<div>
|
||||
<span className="eyebrow">STILL BLOCKING PUBLIC BETA</span>
|
||||
<h2 id="privacy-open-heading">这份清单完成了,但隐私门禁还没有通过。</h2>
|
||||
</div>
|
||||
<p>仍需确定每类数据的最终保存期、租户卷与备份擦除流程、必要保留例外、受托服务方、部署与跨境事实,以及公开登录方案。证据完成前,本站不会宣称“已经合规”。</p>
|
||||
</section>
|
||||
</PublicShell>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user