NSIO Docs
NSIO Docs
首页

NSIO Next · 当前开发基线

统一 L3 + L4 架构
产品能力目录与实现闭环
功能闭环总账
产品闭环与功能实现
实施蓝图与交付契约
发行、升级与卸载
跨组件共享契约
控制资源生命周期
控制投影与 Runtime Protocol
数据面协议
Grant 与策略编译

组件实现规格

ns · 统一节点运行时
Client · App、CLI 与门户
NSD · 身份与控制面
NSGW · 增值数据面
身份、登录与会话
注册、准入与配额协议
商业模型与 Entitlement
采购、计费与发票
服务运营与 SLA
备份与灾难恢复
信任、合规与数据权利

Last Updated: 2026/8/9 11:10:38

Previous Page发行、升级与卸载
Next Page控制资源生命周期

#NSIO Next · 跨组件共享契约

本文是 ns、NS App、NSD、NSGW 和管理控制台并行实现时必须共同遵守的协议基线。产品含义以产品闭环为权威,身份与注册分别以身份登录和注册协议为权威;管理对象状态/API 见控制资源生命周期,建流与传输见数据面协议,逐功能完备性见功能闭环总账。本文只固定跨进程、跨仓库和跨版本的可观察契约。

#1. 契约所有权

契约权威生产者消费者禁止事项
Identity / SessionIdentity Authority + NSDClient、管理 APIApp 保存密码或自行判断 MFA 强度
Device / EnrollmentNSDClient、ns仅凭显示名认领 Device
Network / MembershipNSDns、Client客户端自行分配 Node IP
Grant / Policy ProjectionNSD compilerns、ClientDart、CLI 或 NSGW 重写授权算法
Local Service Manifest节点所有者或受管授权ns、NSDNSD 越过节点本地上限发布后端
Service Directory / DNSNSD projectionns、Client读取失败渲染为空目录
Route / Exit / Gateway LeaseNSDns、NSGW、Client候选列表替代数据面的最终校验
EntitlementEntitlement issuer → NSD resolverNSD、NSGW客户端自报套餐能力
Runtime Statusns runtimeClient、CLIClient 从日志文本猜运行状态
Local Runtime Ownershipns runtime + OS peer authenticationClient、CLI、installer/helper非 owner 读取租户状态,或 OS 管理员凭维护权限冒充 owner

共享类型放在 ns-shared-next。共享仓库只承载稳定 wire schema、标识符、签名与错误类型,不承载数据库 ORM、产品 UI 或平台路由实现。

#2. 标识符与作用域

所有外部对象使用不可枚举、全局唯一、类型明确的 ID。显示名可修改,绝不参与授权、幂等或引用完整性。

对象建议字段最小作用域
Accountaccount_idIdentity Authority
Human/Machine Principalprincipal_idOrganization
External Identity / Sessionexternal_identity_id / session_idAccount + issuer
Organizationorganization_idDeployment
Networknetwork_idOrganization
Organization Membership / Grouporg_membership_id / group_idOrganization
Admin Role Bindingrole_binding_idOrganization + resource scope
Devicedevice_idOrganization;不跨组织复用 Device Key
Node Membershipmembership_idNetwork + Device
Serviceservice_idNetwork
Endpointendpoint_idService + Membership
Grant Set / Rulegrant_set_id / rule_idNetwork
Access Request / Temporary Grantaccess_request_id / temporary_grant_idNetwork
Capability Policy / Activationcapability_policy_id / activation_idOrganization/Network
Routeroute_idNetwork
Gateway / Profilegateway_id / profile_refOrganization/Network
Public Application / Edge Policy / Bindingapplication_id / edge_policy_id / binding_lease_idOrganization/Network
Share Offer / Binding / Federationshare_id / share_binding_id / federation_binding_idprovider/consumer Organization
Machine Credentialoauth_client_id / credential_idMachinePrincipal
Posture Provider / Claimposture_provider_id / posture_claim_idOrganization/Device
Rotation / Reservationrotation_id / reservation_idtarget object / Entitlement subject
Request / Operationrequest_id / operation_idDeployment

每个 API、事件和审计记录都携带必要的 organization_id、network_id 与目标 ID。仓储层必须先按租户作用域过滤,再按对象 ID 查询;不能先查全局 ID 后在 handler 里补权限判断。

#3. 命令契约

所有会改变状态的 API 使用统一命令语义:

{
  "api_version": 1,
  "request_id": "req_...",
  "idempotency_key": "client-generated-stable-key",
  "expected_revision": 41,
  "command": "service.declare",
  "subject": {
    "organization_id": "org_...",
    "network_id": "net_..."
  },
  "payload": {}
}
  • request_id 用于端到端诊断,不作为幂等键;
  • idempotency_key 在同一命令与租户作用域内唯一,重复请求必须返回同一业务结果;
  • 修改已有对象时必须带 expected_revision,版本不符返回 revision_conflict 并附当前 revision;
  • 危险操作还要带 NSD 生成的 impact_digest,提交时重新计算,不一致返回 impact_changed;
  • 命令成功只表示权威状态已提交,不表示所有终端已投影完成;响应必须分别给出 committed_revision 和投影跟踪 ID。

命令名称进入共享 registry,首版至少覆盖:identity/session、Organization/Network/Group/Role、Enrollment/Device/Membership、AccessGrant/AccessRequest、CapabilityPolicy/Activation、Service/Publication、Route、Gateway/Selection/PublicApplication、Share/Federation、MachinePrincipal/OAuth client、Posture、Entitlement/Reservation、Audit/Export/Delete/Hold。每项 create/update/approve/suspend/revoke/rotate/delete 使用独立 action;完整状态和 API 以控制资源生命周期及专项文档为准。

#4. 下行事件信封

每种事件独立版本,不存在一个可以推断全部能力的“产品版本”。

{
  "event_type": "services.snapshot",
  "schema_version": 1,
  "event_id": "evt_...",
  "deployment_id": "dep_...",
  "organization_id": "org_...",
  "network_id": "net_...",
  "target": {"type": "membership", "id": "nm_..."},
  "epoch": 7,
  "revision": 184,
  "generated_at": "2026-08-08T12:00:00Z",
  "not_before": "2026-08-08T11:59:55Z",
  "expires_at": "2026-08-08T12:10:00Z",
  "payload_digest": "sha256:...",
  "payload": {},
  "signature": "..."
}

事件目标使用 device、membership、gateway 或 client_session 类型化引用,必须与认证身份和 payload 作用域一致。客户端处理顺序固定为:验证版本可理解 → 验签 → 校验目标与作用域 → 校验 epoch/revision/有效期 → 解析 payload → 构建候选状态 → 原子替换 → 回执。任何一步失败都不能覆盖最后有效状态。具体 stream 与 payload 见Runtime Protocol v1。

#5. Snapshot、Delta 与恢复

每个投影流独立维护 (deployment_id, target, event_type, epoch, revision) 水位。本地 profile_id 只用于 Client 选择保存的控制端,不进入 NSD 签名事件:

  1. 初次连接或本地无状态时请求 snapshot;
  2. delta 的 base_revision 必须等于本地 revision;
  3. 断档、epoch 改变、digest 不符或本地状态损坏时停止应用 delta 并请求 snapshot;
  4. snapshot 在临时空间完成解析、授权交叉校验和平台计划构建后再原子切换;
  5. 新 snapshot 失败时继续使用未过期的最后有效 snapshot,并上报 projection_outdated,状态为 outdated_applied;
  6. 过期后按资源安全语义 fail-closed,不将其变成空列表或默认允许。

事件回执区分 received、applied、rejected。applied 必须包含实际生效 revision;rejected 包含稳定错误码和可重试性,但不得回传私钥或完整敏感 payload。

#6. 状态模型

跨层功能状态不得压成布尔值。所有功能至少分成四个正交轴:

轴回答的问题示例
intent用户/管理员想要什么enabled / disabled / required
authority权威是否允许authorized / denied / unknown
projection控制面是否给出可执行配置waiting / matched / mismatch / expired
runtime本机或网关是否实际生效starting / ready / degraded / blocked / failed

Client 展示由这些结构化轴推导,不得用“连接成功”覆盖部分失败,也不得用“无资源”覆盖读取故障。

#7. 错误信封

{
  "result": "error",
  "error": {
    "code": "service_projection_read_failed",
    "message_key": "service.projection_read_failed",
    "retryable": true,
    "scope": "network",
    "request_id": "req_...",
    "details": {
      "network_id": "net_..."
    }
  }
}

错误码按原因而不是页面命名。固定分类如下:

类别示例默认动作
authenticationsession_expired重新登录,不撤 Membership
authorizationnot_authorized不重试,联系管理员或修改 Grant
admissionquota_limit_reached显示真实资源与限制
conflictrevision_conflict, route_conflict刷新权威状态并让用户决定
unavailablecandidates_not_ready保持意图,等待或重试
read_failureprojection_read_failed保留缓存,显示故障
incompatibleschema_version_unsupported更新对应组件
local_policylocal_manifest_denied在节点本地处理
safetycapture_blocked, signature_invalid保持 fail-closed,禁止自动降级
local_ownershipruntime_owned_by_another_local_user, runtime_owner_inactive不泄露 owner/tenant;等待、释放或明确 reset

错误结构允许新增可选 details,但不能改变既有 code 的含义。用户文案由 Client 本地化,服务端 message 仅用于诊断。

#8. Capability Manifest

能力发现分两层:

  • /.well-known/nsio-capabilities 用于匿名预检,短缓存、带 ETag,不作为安全权威;
  • 已认证握手交换各组件的能力集合和协议版本区间,协商结果进入认证 transcript。

Manifest 只能关闭双方不共同支持的可选功能,不能降低签名、Device Key 绑定、确认页防钓鱼、租户隔离、授权或 fail-closed 基线。客户端自报“不支持安全能力”时,服务端拒绝对应流程,不切到更宽松路径。

#9. 密钥与签名

  • Device Key、Node Key、WireGuard 私钥和 Staging Key 只在节点生成并保存;
  • NSD 只保存公钥、摘要、状态和轮换关系;
  • Device Key 证明设备与注册请求,Node/WG Key 用于 Network Membership 数据面;
  • 不同 Organization 使用独立 Device Key,不能从同一安装主密钥确定性派生;
  • 控制事件由部署级签名键签名,签名键轮换必须提供带交叉签名的信任链;
  • Secret、Token、Enrollment Key 只以哈希或密文形式持久化,日志和审计禁止明文。

首版共享 credential registry 至少包含:EnrollmentGrant、control credential、PeerPathLease、RelayRouteLease、ServiceFlowCredential、RouteAccessCredential、Capability Lease、EgressOriginLease、ExitTunnelLease、IngressBackendCredential、FederatedAccessLease、OAuth Access Token、EdgeSessionCredential 和 signed EdgeIdentityContext。每类 credential 有独立 audience/claims/schema/TTL/revoke key,不能用一个通用 bearer token 跨数据面。

#10. 时间与租约

服务端时间是 Grant、Lease、Session 与事件有效期的权威。客户端时钟只用于提示,并保留有限偏差窗口。所有短期授权包含 not_before、expires_at 和签发 revision;续租失败时保持最后有效状态直到过期,过期后执行对应资源的 fail-closed 行为。

撤销不依赖“立即收到一条删除事件”这一单点。Peer、Route、Gateway 和跨组织分享都使用短租约,使丢失撤销事件时也能在 SLA 内自然失效。

#11. 审计与可观测性

所有跨组件操作共享 request_id,关键状态变化另有稳定 operation_id。日志字段至少包含 component、deployment、organization、network、resource、revision、result 和 error code。指标只记录必要元数据,不记录业务内容。

必须可回答:

  • 谁在何时请求了什么;
  • 哪个权威 revision 批准或拒绝;
  • 哪个组件收到并应用了哪个 revision;
  • 当前失败是身份、权限、投影、平台执行还是网络路径;
  • 最后一次有效配置何时到期。

#12. 契约测试门

每个共享 schema 都必须具备:

  1. 真实生产类型序列化后对发布 schema 校验;
  2. 新增可选字段时旧消费者仍可解析;
  3. 缺少必需字段、未知 major、错误签名和回滚 revision 明确失败;
  4. snapshot/delta 断档触发 snapshot 恢复;
  5. 把读取失败注入为空结果时测试必须失败;
  6. 把授权过滤放宽或作用域移除时测试必须失败;
  7. 跨仓库 fixture 只从共享类型生成,不手工复制 JSON。

共享契约未通过这些门,任何组件都不能宣布对应功能完成。