mindspace: guard split-service contract drift
This commit is contained in:
@@ -156,6 +156,37 @@ scoped 模式下 `generate_docx` / `generate_long_image` 也不得在 RPC
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 1.5 Split-service 契约:版本、构建与生产闸门必须成套
|
||||||
|
|
||||||
|
### 必须保留
|
||||||
|
|
||||||
|
| 位置 | 行为 |
|
||||||
|
|------|------|
|
||||||
|
| `mindspace-server-adapter-contract.mjs` | `MINDSPACE_SERVER_ADAPTER_CONTRACT_VERSION`、required capabilities 与 required bindings 是 remote/local/RPC 的共享契约 |
|
||||||
|
| `mindspace-remote-server-adapter.mjs` | `assertReady()` 必须拉取 `/mindspace/v1/contract` 并校验版本、capability 与关键 method,失败时 Portal 启动 fail-fast |
|
||||||
|
| `server/portal-domain-services-bootstrap.mjs` | bootstrap 必须 `await mindSpaceRuntimeAdapter.assertReady?.()`,禁止把 contract mismatch 延迟到用户交付链路 |
|
||||||
|
| `mindspace-service/server.mjs` + `scripts/build-mindspace-service-runtime.mjs` | standalone runtime 必须写入并读取 `build-info.json`,让 `/health` 与 `/contract` 暴露 `buildId/gitSha/builtAt` |
|
||||||
|
| `scripts/release-mindspace-service-prod.sh` | 生产启动后必须校验 `/mindspace/v1/contract` 的版本、capability、关键 method 与 runtime manifest 的 `git_head` |
|
||||||
|
| `mindspace-storage-adapter.mjs` + `mindspace-service.mjs` | storage adapter 必须先通过版本化接口契约,后续 NAS/S3 adapter 不得绕过 facade |
|
||||||
|
| `scripts/audit-conversation-packages.mjs` + `scripts/trace-mindspace-artifact.mjs` | package/artifact 诊断必须保留 read-only 默认行为;`--repair` 只能补 `public_html` artifact 记录,不得改物理文件 |
|
||||||
|
|
||||||
|
这条边界保证 split-service 不会出现“Portal 已升级、MindSpace service
|
||||||
|
还是旧 runtime”的隐性半成功状态。旧契约必须在启动时被拒绝;生产
|
||||||
|
runtime 也必须和发布 manifest 的 git commit 对齐。
|
||||||
|
|
||||||
|
### 守卫
|
||||||
|
|
||||||
|
- 单测:`mindspace-remote-server-adapter.test.mjs`、
|
||||||
|
`mindspace-service/mindspace-rpc-server.test.mjs`、
|
||||||
|
`mindspace-storage-adapter.test.mjs`、
|
||||||
|
`mindspace-conversation-package-audit.test.mjs`
|
||||||
|
- split smoke:`npm run smoke:mindspace-split-service`
|
||||||
|
- 源码 + runtime 门禁:`npm run verify:mindspace-authority-boundary`、
|
||||||
|
`npm run verify:mindspace-authority-boundary:full`
|
||||||
|
- 综合验证:`npm run verify:mindspace-publish-guards`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2. 聊天 Finish:禁止清空对话 / 禁止暴露内部前缀
|
## 2. 聊天 Finish:禁止清空对话 / 禁止暴露内部前缀
|
||||||
|
|
||||||
### 症状
|
### 症状
|
||||||
|
|||||||
@@ -83,6 +83,25 @@ const userAuthSource = read('user-auth.mjs');
|
|||||||
const mindSpaceRpcServerSource = read(
|
const mindSpaceRpcServerSource = read(
|
||||||
'mindspace-service/mindspace-rpc-server.mjs',
|
'mindspace-service/mindspace-rpc-server.mjs',
|
||||||
);
|
);
|
||||||
|
const mindSpaceServiceServerSource = read(
|
||||||
|
'mindspace-service/server.mjs',
|
||||||
|
);
|
||||||
|
const remoteAdapterSource = read(
|
||||||
|
'mindspace-remote-server-adapter.mjs',
|
||||||
|
);
|
||||||
|
const storageAdapterSource = read(
|
||||||
|
'mindspace-storage-adapter.mjs',
|
||||||
|
);
|
||||||
|
const mindSpaceServiceSource = read(
|
||||||
|
'mindspace-service.mjs',
|
||||||
|
);
|
||||||
|
const buildMindSpaceRuntimeSource = read(
|
||||||
|
'scripts/build-mindspace-service-runtime.mjs',
|
||||||
|
);
|
||||||
|
const releaseMindSpaceServiceSource = read(
|
||||||
|
'scripts/release-mindspace-service-prod.sh',
|
||||||
|
);
|
||||||
|
const packageJsonSource = read('package.json');
|
||||||
const publicationServiceSource = read(
|
const publicationServiceSource = read(
|
||||||
'mindspace-publications.mjs',
|
'mindspace-publications.mjs',
|
||||||
);
|
);
|
||||||
@@ -220,6 +239,116 @@ requireSource(
|
|||||||
/'readWorkspaceHtml'/,
|
/'readWorkspaceHtml'/,
|
||||||
'chat save contract includes workspace HTML read authority',
|
'chat save contract includes workspace HTML read authority',
|
||||||
);
|
);
|
||||||
|
requireSource(
|
||||||
|
contractSource,
|
||||||
|
/MINDSPACE_SERVER_ADAPTER_CONTRACT_VERSION\s*=\s*2/,
|
||||||
|
'MindSpace remote contract is explicitly versioned',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
contractSource,
|
||||||
|
/MINDSPACE_SERVER_ADAPTER_REQUIRED_CAPABILITIES[\s\S]{0,240}'chat-save-authority'[\s\S]{0,240}'scoped-workspace-tools'/,
|
||||||
|
'MindSpace remote contract advertises required authority capabilities',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
contractSource,
|
||||||
|
/MINDSPACE_SERVER_ADAPTER_REQUIRED_BINDINGS[\s\S]*workspaceToolService[\s\S]{0,240}'writeBinaryFile'/,
|
||||||
|
'MindSpace remote contract declares required method-level bindings',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
contractSource,
|
||||||
|
/createMindSpaceServerAdapterContractPayload\(\{/,
|
||||||
|
'MindSpace contract payload is generated from the shared contract module',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
remoteAdapterSource,
|
||||||
|
/validateMindSpaceRemoteContract\(/,
|
||||||
|
'remote adapter validates MindSpace service contract compatibility',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
remoteAdapterSource,
|
||||||
|
/fetchRemoteContract\(\{[\s\S]{0,240}contractPath/,
|
||||||
|
'remote adapter fetches /mindspace/v1/contract before startup succeeds',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
remoteAdapterSource,
|
||||||
|
/async assertReady\(\)[\s\S]{0,700}validateMindSpaceRemoteContract\(/,
|
||||||
|
'remote adapter assertReady fails fast on incompatible contracts',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
portalDomainBootstrapSource,
|
||||||
|
/await mindSpaceRuntimeAdapter\.assertReady\?\.\(\)/,
|
||||||
|
'Portal awaits MindSpace remote contract readiness during bootstrap',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
mindSpaceRpcServerSource,
|
||||||
|
/createMindSpaceServerAdapterContractPayload\(\{/,
|
||||||
|
'MindSpace RPC /contract uses the shared contract payload',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
mindSpaceRpcServerSource,
|
||||||
|
/contractVersion:\s*[\s\S]{0,120}MINDSPACE_SERVER_ADAPTER_CONTRACT_VERSION/,
|
||||||
|
'MindSpace RPC /health exposes the contract version',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
mindSpaceServiceServerSource,
|
||||||
|
/readBuildInfo\(\)[\s\S]{0,320}build-info\.json/,
|
||||||
|
'standalone MindSpace service reads runtime build-info.json',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
mindSpaceServiceServerSource,
|
||||||
|
/serviceMeta:[\s\S]{0,160}buildInfo/,
|
||||||
|
'standalone MindSpace service passes build metadata to RPC contract',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
buildMindSpaceRuntimeSource,
|
||||||
|
/build-info\.json/,
|
||||||
|
'MindSpace runtime artifact writes build-info.json',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
releaseMindSpaceServiceSource,
|
||||||
|
/build-info\.json/,
|
||||||
|
'MindSpace production release requires build-info.json',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
releaseMindSpaceServiceSource,
|
||||||
|
/contract\.contractVersion !== 2/,
|
||||||
|
'MindSpace production release rejects stale contract versions',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
releaseMindSpaceServiceSource,
|
||||||
|
/missingCapabilities[\s\S]{0,240}missingBindings[\s\S]{0,240}expectedGitSha/,
|
||||||
|
'MindSpace production release checks capabilities, methods, and gitSha',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
storageAdapterSource,
|
||||||
|
/MINDSPACE_STORAGE_ADAPTER_CONTRACT_VERSION\s*=\s*1/,
|
||||||
|
'MindSpace storage adapter contract is versioned for future backends',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
storageAdapterSource,
|
||||||
|
/assertMindSpaceStorageAdapterContract\(/,
|
||||||
|
'MindSpace storage adapter contract is executable',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
mindSpaceServiceSource,
|
||||||
|
/assertMindSpaceStorageAdapterContract\(storageAdapter\)/,
|
||||||
|
'MindSpace service facade validates injected storage adapters',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
packageJsonSource,
|
||||||
|
/"audit:conversation-packages":\s*"node scripts\/audit-conversation-packages\.mjs"/,
|
||||||
|
'conversation package audit is exposed as an npm script',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
packageJsonSource,
|
||||||
|
/"trace:mindspace-artifact":\s*"node scripts\/trace-mindspace-artifact\.mjs"/,
|
||||||
|
'MindSpace artifact trace is exposed as an npm script',
|
||||||
|
);
|
||||||
|
requireSource(
|
||||||
|
packageJsonSource,
|
||||||
|
/mindspace-conversation-package-audit\.test\.mjs/,
|
||||||
|
'conversation package audit is included in the default test suite',
|
||||||
|
);
|
||||||
requireSource(
|
requireSource(
|
||||||
localRuntimeSource,
|
localRuntimeSource,
|
||||||
/createMindSpaceChatSaveService\(\{/,
|
/createMindSpaceChatSaveService\(\{/,
|
||||||
|
|||||||
Reference in New Issue
Block a user