storage-sensitive-policy.mjs 4.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import fs from 'node:fs';
  2. import path from 'node:path';
  3. import { fileURLToPath } from 'node:url';
  4. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  5. const rootDir = path.resolve(__dirname, '..', '..');
  6. const boundaryDoc = path.join(
  7. rootDir,
  8. 'docs',
  9. 'superpowers',
  10. '计划',
  11. '全系统存储治理',
  12. '2026-06-17-全系统存储边界矩阵.md',
  13. );
  14. const routeDoc = path.join(
  15. rootDir,
  16. 'docs',
  17. 'superpowers',
  18. '计划',
  19. '全系统存储治理',
  20. '2026-06-17-全系统存储执行路线图.md',
  21. );
  22. const sourceFiles = {
  23. viral: path.join(rootDir, 'src', 'app', 'services', 'viral-analysis.service.ts'),
  24. ipOperator: path.join(rootDir, 'src', 'app', 'services', 'ip-operator.service.ts'),
  25. assistant: path.join(rootDir, 'src', 'app', 'services', 'assistant.service.ts'),
  26. };
  27. const errors = [];
  28. const boundaryText = read(boundaryDoc);
  29. const routeText = read(routeDoc);
  30. assertIncludes(boundaryText, '敏感数据与大对象归档决策', 'Boundary matrix must define sensitive/big-object archival decisions');
  31. assertIncludes(boundaryText, 'viralAnalysis.comment', 'Boundary matrix must cover viral comment child entities');
  32. assertIncludes(boundaryText, 'viralAnalysis.reply', 'Boundary matrix must cover viral reply child entities');
  33. assertIncludes(boundaryText, 'viralAnalysis.transcript', 'Boundary matrix must cover viral transcript child entities');
  34. assertIncludes(boundaryText, 'ipOperator.accountSnapshotWork', 'Boundary matrix must cover account snapshot work child entities');
  35. assertIncludes(boundaryText, 'ipOperator.accountSnapshotComment', 'Boundary matrix must cover account snapshot comment child entities');
  36. assertIncludes(boundaryText, 'ipOperator.planScriptBody', 'Boundary matrix must cover IP operator script body child entities');
  37. assertIncludes(boundaryText, 'ipOperator.planGenerationPreview', 'Boundary matrix must cover IP operator raw preview child entities');
  38. assertIncludes(boundaryText, 'assistantThread', 'Boundary matrix must cover assistant thread storage');
  39. assertIncludes(boundaryText, 'localStorage', 'Boundary matrix must state browser long-term cache boundaries');
  40. assertIncludes(boundaryText, '七牛', 'Boundary matrix must define Qiniu archival placement');
  41. assertIncludes(boundaryText, '决策红线', 'Boundary matrix must include red lines for sensitive data handling');
  42. assertIncludes(routeText, '敏感数据与大对象归档策略复核', 'Route map must track sensitive/big-object policy review as a completed checkpoint');
  43. assertIncludes(routeText, '历史存量数据归档执行', 'Route map must keep real historical data archival execution as a separate remaining checkpoint');
  44. const viralText = read(sourceFiles.viral);
  45. assertIncludes(viralText, 'viralAnalysis.comment', 'Viral analysis service must externalize comment samples');
  46. assertIncludes(viralText, 'viralAnalysis.reply', 'Viral analysis service must externalize reply samples');
  47. assertIncludes(viralText, 'viralAnalysis.transcript', 'Viral analysis service must externalize transcripts');
  48. assertIncludes(viralText, 'compactAnalysisForStorage', 'Viral analysis service must compact the main analysis entity');
  49. const ipOperatorText = read(sourceFiles.ipOperator);
  50. assertIncludes(ipOperatorText, 'ipOperator.accountSnapshotWork', 'IP operator service must externalize account works');
  51. assertIncludes(ipOperatorText, 'ipOperator.accountSnapshotComment', 'IP operator service must externalize account comments');
  52. assertIncludes(ipOperatorText, 'ipOperator.planScriptBody', 'IP operator service must externalize full script bodies');
  53. assertIncludes(ipOperatorText, 'ipOperator.planGenerationPreview', 'IP operator service must externalize raw generation previews');
  54. const assistantText = read(sourceFiles.assistant);
  55. assertIncludes(assistantText, 'assistantThread', 'Assistant service must use a cloud entity for assistant threads');
  56. if (errors.length) {
  57. for (const error of errors) console.error(`FAIL ${error}`);
  58. process.exit(1);
  59. }
  60. console.log('Sensitive storage policy validation passed');
  61. function read(filePath) {
  62. try {
  63. return fs.readFileSync(filePath, 'utf8');
  64. } catch (error) {
  65. errors.push(`Cannot read ${path.relative(rootDir, filePath)}: ${error.message}`);
  66. return '';
  67. }
  68. }
  69. function assertIncludes(text, needle, message) {
  70. if (!text.includes(needle)) errors.push(message);
  71. }