@things-factory/headless-twin 10.1.277 → 10.1.279

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (614) hide show
  1. package/package.json +21 -7
  2. package/dist-server/engine/attention-digest.js.map +0 -1
  3. package/dist-server/engine/canonical-ingest.js.map +0 -1
  4. package/dist-server/engine/checkpoint-fold.js.map +0 -1
  5. package/dist-server/engine/command-routing.js.map +0 -1
  6. package/dist-server/engine/declared-stimulus.js.map +0 -1
  7. package/dist-server/engine/energy-topology.js.map +0 -1
  8. package/dist-server/engine/event-time.js.map +0 -1
  9. package/dist-server/engine/index.js.map +0 -1
  10. package/dist-server/engine/ingest-dedupe.js.map +0 -1
  11. package/dist-server/engine/ingest-health.js.map +0 -1
  12. package/dist-server/engine/integration-coverage.js.map +0 -1
  13. package/dist-server/engine/integration-probes.js.map +0 -1
  14. package/dist-server/engine/integration-runner.js.map +0 -1
  15. package/dist-server/engine/integration-target-profile.js.map +0 -1
  16. package/dist-server/engine/kpi-baseline.js.map +0 -1
  17. package/dist-server/engine/kpi-fold.js.map +0 -1
  18. package/dist-server/engine/kpi-query.js.map +0 -1
  19. package/dist-server/engine/kpi-target.js.map +0 -1
  20. package/dist-server/engine/live-attentions.js.map +0 -1
  21. package/dist-server/engine/live-feed-registry.js.map +0 -1
  22. package/dist-server/engine/load-meter.js.map +0 -1
  23. package/dist-server/engine/local-declarations.js.map +0 -1
  24. package/dist-server/engine/log.js.map +0 -1
  25. package/dist-server/engine/loop-lag.js.map +0 -1
  26. package/dist-server/engine/measured-estimator.js.map +0 -1
  27. package/dist-server/engine/measured-yield.js.map +0 -1
  28. package/dist-server/engine/model-basis.js.map +0 -1
  29. package/dist-server/engine/model-gap.js.map +0 -1
  30. package/dist-server/engine/model-refusal.js.map +0 -1
  31. package/dist-server/engine/model-vocabulary.js.map +0 -1
  32. package/dist-server/engine/oee-accumulator.js.map +0 -1
  33. package/dist-server/engine/operation-basis.js.map +0 -1
  34. package/dist-server/engine/producer-guard.js.map +0 -1
  35. package/dist-server/engine/property-effects.js.map +0 -1
  36. package/dist-server/engine/read-time.js.map +0 -1
  37. package/dist-server/engine/restart-policy.js.map +0 -1
  38. package/dist-server/engine/runtime-key.js.map +0 -1
  39. package/dist-server/engine/spec-coverage.js.map +0 -1
  40. package/dist-server/engine/stage-path.js.map +0 -1
  41. package/dist-server/engine/state-axes.js.map +0 -1
  42. package/dist-server/engine/structure-diff.js.map +0 -1
  43. package/dist-server/engine/travel-estimator.js.map +0 -1
  44. package/dist-server/engine/twin-engine.js.map +0 -1
  45. package/dist-server/engine/twin-state-channel.js.map +0 -1
  46. package/dist-server/engine/warm-start.js.map +0 -1
  47. package/dist-server/index.js.map +0 -1
  48. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +0 -1
  49. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +0 -1
  50. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +0 -1
  51. package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +0 -1
  52. package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +0 -1
  53. package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +0 -1
  54. package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +0 -1
  55. package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +0 -1
  56. package/dist-server/migrations/1786800000000-CreateTwinReferenceReconciliations.js.map +0 -1
  57. package/dist-server/migrations/index.js.map +0 -1
  58. package/dist-server/routes.js.map +0 -1
  59. package/dist-server/service/actuation/actuation-advisor.js.map +0 -1
  60. package/dist-server/service/actuation/actuation-outcome.js.map +0 -1
  61. package/dist-server/service/actuation/actuation-rule-resolver.js.map +0 -1
  62. package/dist-server/service/actuation/actuation-rule.js.map +0 -1
  63. package/dist-server/service/actuation/approval-gateway.js.map +0 -1
  64. package/dist-server/service/actuation/catch-up-effects.js.map +0 -1
  65. package/dist-server/service/actuation/command-dispatcher.js.map +0 -1
  66. package/dist-server/service/actuation/command-store.js.map +0 -1
  67. package/dist-server/service/actuation/dispatch-after-approval.js.map +0 -1
  68. package/dist-server/service/actuation/effect-match.js.map +0 -1
  69. package/dist-server/service/actuation/index.js.map +0 -1
  70. package/dist-server/service/actuation/retry-plan.js.map +0 -1
  71. package/dist-server/service/actuation/rule-evaluate.js.map +0 -1
  72. package/dist-server/service/actuation/rule-loop.js.map +0 -1
  73. package/dist-server/service/actuation/rule-runner.js.map +0 -1
  74. package/dist-server/service/actuation/rule-wiring.js.map +0 -1
  75. package/dist-server/service/actuation/settle-effects.js.map +0 -1
  76. package/dist-server/service/actuation/sweep-dispatch.js.map +0 -1
  77. package/dist-server/service/actuation/twin-command-resolver.js.map +0 -1
  78. package/dist-server/service/actuation/twin-command.js.map +0 -1
  79. package/dist-server/service/actuation/twin-now.js.map +0 -1
  80. package/dist-server/service/index.js.map +0 -1
  81. package/dist-server/service/reference/actuation-routing.js.map +0 -1
  82. package/dist-server/service/reference/actuation-target.js.map +0 -1
  83. package/dist-server/service/reference/actuation-verification.js.map +0 -1
  84. package/dist-server/service/reference/attention-lane.js.map +0 -1
  85. package/dist-server/service/reference/connection-portability-resolver.js.map +0 -1
  86. package/dist-server/service/reference/connection-portability.js.map +0 -1
  87. package/dist-server/service/reference/control-routing.js.map +0 -1
  88. package/dist-server/service/reference/discovery-result.js.map +0 -1
  89. package/dist-server/service/reference/fill-cadence.js.map +0 -1
  90. package/dist-server/service/reference/fill-dedupe.js.map +0 -1
  91. package/dist-server/service/reference/fill-loop.js.map +0 -1
  92. package/dist-server/service/reference/fill-span.js.map +0 -1
  93. package/dist-server/service/reference/hook-contract.js.map +0 -1
  94. package/dist-server/service/reference/hook-rejected.js.map +0 -1
  95. package/dist-server/service/reference/hook-store.js.map +0 -1
  96. package/dist-server/service/reference/index.js.map +0 -1
  97. package/dist-server/service/reference/ingest-space.js.map +0 -1
  98. package/dist-server/service/reference/knob-defaults.js.map +0 -1
  99. package/dist-server/service/reference/live-cadence.js.map +0 -1
  100. package/dist-server/service/reference/live-feed-lease.js.map +0 -1
  101. package/dist-server/service/reference/live-ingest.js.map +0 -1
  102. package/dist-server/service/reference/reference-adapter.js.map +0 -1
  103. package/dist-server/service/reference/reference-assessment.js.map +0 -1
  104. package/dist-server/service/reference/reference-fill-run.js.map +0 -1
  105. package/dist-server/service/reference/reference-fill.js.map +0 -1
  106. package/dist-server/service/reference/reference-hook.js.map +0 -1
  107. package/dist-server/service/reference/reference-link-groups.js.map +0 -1
  108. package/dist-server/service/reference/reference-links.js.map +0 -1
  109. package/dist-server/service/reference/reference-live.js.map +0 -1
  110. package/dist-server/service/reference/reference-master.js.map +0 -1
  111. package/dist-server/service/reference/reference-probe.js.map +0 -1
  112. package/dist-server/service/reference/reference-progress-channel.js.map +0 -1
  113. package/dist-server/service/reference/reference-progress-subscription.js.map +0 -1
  114. package/dist-server/service/reference/reference-progress.js.map +0 -1
  115. package/dist-server/service/reference/reference-reconciliation-query.js.map +0 -1
  116. package/dist-server/service/reference/reference-reconciliation-writer.js.map +0 -1
  117. package/dist-server/service/reference/reference-reconciliation.js.map +0 -1
  118. package/dist-server/service/reference/reference-registry.js.map +0 -1
  119. package/dist-server/service/reference/reference-resolver.js.map +0 -1
  120. package/dist-server/service/reference/template-registry.js.map +0 -1
  121. package/dist-server/service/reference/twin-reference-reconciliation.js.map +0 -1
  122. package/dist-server/service/reference/twin-reference.js.map +0 -1
  123. package/dist-server/service/twin-attention/index.js.map +0 -1
  124. package/dist-server/service/twin-attention/twin-attention-query.js.map +0 -1
  125. package/dist-server/service/twin-audit/command-audit.js.map +0 -1
  126. package/dist-server/service/twin-audit/index.js.map +0 -1
  127. package/dist-server/service/twin-audit/twin-audit-event.js.map +0 -1
  128. package/dist-server/service/twin-audit/twin-audit-query.js.map +0 -1
  129. package/dist-server/service/twin-backfill/backfill-period-facts.js.map +0 -1
  130. package/dist-server/service/twin-backfill/backfill-shape.js.map +0 -1
  131. package/dist-server/service/twin-backfill/index.js.map +0 -1
  132. package/dist-server/service/twin-backfill/twin-backfill-resolver.js.map +0 -1
  133. package/dist-server/service/twin-control/index.js.map +0 -1
  134. package/dist-server/service/twin-control/twin-control-mutation.js.map +0 -1
  135. package/dist-server/service/twin-event/index.js.map +0 -1
  136. package/dist-server/service/twin-event/journal-count.js.map +0 -1
  137. package/dist-server/service/twin-event/twin-event-keys.js.map +0 -1
  138. package/dist-server/service/twin-event/twin-event-type.js.map +0 -1
  139. package/dist-server/service/twin-event/twin-event.js.map +0 -1
  140. package/dist-server/service/twin-forecast/forecast-metrics.js.map +0 -1
  141. package/dist-server/service/twin-forecast/forecast-tuning.js.map +0 -1
  142. package/dist-server/service/twin-forecast/gap-analytics.js.map +0 -1
  143. package/dist-server/service/twin-forecast/index.js.map +0 -1
  144. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +0 -1
  145. package/dist-server/service/twin-ingest-window/index.js.map +0 -1
  146. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +0 -1
  147. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +0 -1
  148. package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +0 -1
  149. package/dist-server/service/twin-instance/index.js.map +0 -1
  150. package/dist-server/service/twin-instance/twin-instance.js.map +0 -1
  151. package/dist-server/service/twin-journal/event-type-split-shape.js.map +0 -1
  152. package/dist-server/service/twin-journal/event-type-split.js.map +0 -1
  153. package/dist-server/service/twin-journal/index.js.map +0 -1
  154. package/dist-server/service/twin-journal/journal-order.js.map +0 -1
  155. package/dist-server/service/twin-journal/twin-journal-query.js.map +0 -1
  156. package/dist-server/service/twin-lifecycle/domain-catalog.js.map +0 -1
  157. package/dist-server/service/twin-lifecycle/index.js.map +0 -1
  158. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +0 -1
  159. package/dist-server/service/twin-metrics/index.js.map +0 -1
  160. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +0 -1
  161. package/dist-server/service/twin-model/axis-journal-evidence.js.map +0 -1
  162. package/dist-server/service/twin-model/choose-recipe.js.map +0 -1
  163. package/dist-server/service/twin-model/epcis-coverage.js.map +0 -1
  164. package/dist-server/service/twin-model/external-resolver.js.map +0 -1
  165. package/dist-server/service/twin-model/iec61850-coverage.js.map +0 -1
  166. package/dist-server/service/twin-model/index.js.map +0 -1
  167. package/dist-server/service/twin-model/isa95-coverage.js.map +0 -1
  168. package/dist-server/service/twin-model/item-ref.js.map +0 -1
  169. package/dist-server/service/twin-model/name-index.js.map +0 -1
  170. package/dist-server/service/twin-model/project-structure.js.map +0 -1
  171. package/dist-server/service/twin-model/standard-coverage.js.map +0 -1
  172. package/dist-server/service/twin-model/status-tally.js.map +0 -1
  173. package/dist-server/service/twin-model/twin-equipment.js.map +0 -1
  174. package/dist-server/service/twin-model/twin-lineage-query.js.map +0 -1
  175. package/dist-server/service/twin-model/twin-location.js.map +0 -1
  176. package/dist-server/service/twin-model/twin-model-item-query.js.map +0 -1
  177. package/dist-server/service/twin-model/twin-model-mutation.js.map +0 -1
  178. package/dist-server/service/twin-model/twin-model-query.js.map +0 -1
  179. package/dist-server/service/twin-model/twin-model-tree-query.js.map +0 -1
  180. package/dist-server/service/twin-model/twin-operation.js.map +0 -1
  181. package/dist-server/service/twin-readiness/index.js.map +0 -1
  182. package/dist-server/service/twin-readiness/twin-readiness-query.js.map +0 -1
  183. package/dist-server/service/twin-space/area-resolver.js.map +0 -1
  184. package/dist-server/service/twin-space/index.js.map +0 -1
  185. package/dist-server/service/twin-space/move-space.js.map +0 -1
  186. package/dist-server/service/twin-space/representation-role.js.map +0 -1
  187. package/dist-server/service/twin-space/space-integrity.js.map +0 -1
  188. package/dist-server/service/twin-space/twin-area.js.map +0 -1
  189. package/dist-server/service/twin-space/twin-space-area.js.map +0 -1
  190. package/dist-server/service/twin-space/twin-space-representation.js.map +0 -1
  191. package/dist-server/service/twin-space/twin-space-resolver.js.map +0 -1
  192. package/dist-server/service/twin-space/twin-space.js.map +0 -1
  193. package/dist-server/service/twin-state/index.js.map +0 -1
  194. package/dist-server/service/twin-state/twin-state-subscription.js.map +0 -1
  195. package/dist-server/service/twin-structure/index.js.map +0 -1
  196. package/dist-server/service/twin-structure/twin-structure.js.map +0 -1
  197. package/dist-server/service/twin-subject/event-subjects.js.map +0 -1
  198. package/dist-server/service/twin-subject/index.js.map +0 -1
  199. package/dist-server/service/twin-subject/item-resolver.js.map +0 -1
  200. package/dist-server/service/twin-subject/subject-query-shape.js.map +0 -1
  201. package/dist-server/service/twin-subject/twin-subject-backfill.js.map +0 -1
  202. package/dist-server/service/twin-subject/twin-subject-event.js.map +0 -1
  203. package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +0 -1
  204. package/dist-server/service/twin-subject/twin-subject-query.js.map +0 -1
  205. package/dist-server/service/twin-subject/twin-subject-writer.js.map +0 -1
  206. package/dist-server/service/twin-target/index.js.map +0 -1
  207. package/dist-server/service/twin-target/twin-target-resolver.js.map +0 -1
  208. package/dist-server/service/twin-target/twin-target.js.map +0 -1
  209. package/dist-shared/axis-read.js.map +0 -1
  210. package/dist-shared/entity-delta.js.map +0 -1
  211. package/dist-shared/kpi-broadcast.js.map +0 -1
  212. package/dist-shared/touched-items.js.map +0 -1
  213. package/dist-shared/twin-level.js.map +0 -1
  214. package/server/engine/attention-digest.ts +0 -102
  215. package/server/engine/canonical-ingest.ts +0 -511
  216. package/server/engine/checkpoint-fold.ts +0 -12
  217. package/server/engine/command-routing.ts +0 -67
  218. package/server/engine/declared-stimulus.ts +0 -66
  219. package/server/engine/energy-topology.ts +0 -189
  220. package/server/engine/event-time.ts +0 -96
  221. package/server/engine/index.ts +0 -51
  222. package/server/engine/ingest-dedupe.ts +0 -24
  223. package/server/engine/ingest-health.ts +0 -24
  224. package/server/engine/integration-coverage.ts +0 -147
  225. package/server/engine/integration-probes.ts +0 -144
  226. package/server/engine/integration-runner.ts +0 -95
  227. package/server/engine/integration-target-profile.ts +0 -103
  228. package/server/engine/kpi-baseline.ts +0 -202
  229. package/server/engine/kpi-fold.ts +0 -1516
  230. package/server/engine/kpi-query.ts +0 -1210
  231. package/server/engine/kpi-target.ts +0 -248
  232. package/server/engine/live-attentions.ts +0 -30
  233. package/server/engine/live-feed-registry.ts +0 -59
  234. package/server/engine/load-meter.ts +0 -393
  235. package/server/engine/local-declarations.ts +0 -779
  236. package/server/engine/log.ts +0 -72
  237. package/server/engine/loop-lag.ts +0 -120
  238. package/server/engine/measured-estimator.ts +0 -91
  239. package/server/engine/measured-yield.ts +0 -89
  240. package/server/engine/model-basis.ts +0 -162
  241. package/server/engine/model-gap.ts +0 -168
  242. package/server/engine/model-refusal.ts +0 -31
  243. package/server/engine/model-vocabulary.ts +0 -82
  244. package/server/engine/oee-accumulator.ts +0 -195
  245. package/server/engine/operation-basis.ts +0 -131
  246. package/server/engine/producer-guard.ts +0 -64
  247. package/server/engine/property-effects.ts +0 -216
  248. package/server/engine/read-time.ts +0 -77
  249. package/server/engine/restart-policy.ts +0 -55
  250. package/server/engine/runtime-key.ts +0 -58
  251. package/server/engine/spec-coverage.ts +0 -105
  252. package/server/engine/stage-path.ts +0 -172
  253. package/server/engine/state-axes.ts +0 -60
  254. package/server/engine/structure-diff.ts +0 -88
  255. package/server/engine/travel-estimator.ts +0 -138
  256. package/server/engine/twin-engine.ts +0 -4979
  257. package/server/engine/twin-state-channel.ts +0 -39
  258. package/server/engine/warm-start.ts +0 -265
  259. package/server/index.ts +0 -90
  260. package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +0 -43
  261. package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +0 -54
  262. package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +0 -53
  263. package/server/migrations/1786300000000-IndexEventTypeByTime.ts +0 -48
  264. package/server/migrations/1786400000000-IndexEventCreatedAt.ts +0 -38
  265. package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +0 -93
  266. package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +0 -66
  267. package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +0 -82
  268. package/server/migrations/1786800000000-CreateTwinReferenceReconciliations.ts +0 -39
  269. package/server/migrations/index.ts +0 -25
  270. package/server/routes.ts +0 -75
  271. package/server/service/actuation/actuation-advisor.ts +0 -131
  272. package/server/service/actuation/actuation-outcome.ts +0 -97
  273. package/server/service/actuation/actuation-rule-resolver.ts +0 -147
  274. package/server/service/actuation/actuation-rule.ts +0 -139
  275. package/server/service/actuation/approval-gateway.ts +0 -44
  276. package/server/service/actuation/catch-up-effects.ts +0 -152
  277. package/server/service/actuation/command-dispatcher.ts +0 -474
  278. package/server/service/actuation/command-store.ts +0 -236
  279. package/server/service/actuation/dispatch-after-approval.ts +0 -71
  280. package/server/service/actuation/effect-match.ts +0 -124
  281. package/server/service/actuation/index.ts +0 -27
  282. package/server/service/actuation/retry-plan.ts +0 -145
  283. package/server/service/actuation/rule-evaluate.ts +0 -352
  284. package/server/service/actuation/rule-loop.ts +0 -160
  285. package/server/service/actuation/rule-runner.ts +0 -216
  286. package/server/service/actuation/rule-wiring.ts +0 -84
  287. package/server/service/actuation/settle-effects.ts +0 -115
  288. package/server/service/actuation/sweep-dispatch.ts +0 -179
  289. package/server/service/actuation/twin-command-resolver.ts +0 -387
  290. package/server/service/actuation/twin-command.ts +0 -232
  291. package/server/service/actuation/twin-now.ts +0 -97
  292. package/server/service/index.ts +0 -100
  293. package/server/service/reference/actuation-routing.ts +0 -192
  294. package/server/service/reference/actuation-target.ts +0 -163
  295. package/server/service/reference/actuation-verification.ts +0 -85
  296. package/server/service/reference/attention-lane.ts +0 -21
  297. package/server/service/reference/connection-portability-resolver.ts +0 -171
  298. package/server/service/reference/connection-portability.ts +0 -329
  299. package/server/service/reference/control-routing.ts +0 -62
  300. package/server/service/reference/discovery-result.ts +0 -95
  301. package/server/service/reference/fill-cadence.ts +0 -29
  302. package/server/service/reference/fill-dedupe.ts +0 -66
  303. package/server/service/reference/fill-loop.ts +0 -153
  304. package/server/service/reference/fill-span.ts +0 -31
  305. package/server/service/reference/hook-contract.ts +0 -364
  306. package/server/service/reference/hook-rejected.ts +0 -53
  307. package/server/service/reference/hook-store.ts +0 -28
  308. package/server/service/reference/index.ts +0 -18
  309. package/server/service/reference/ingest-space.ts +0 -104
  310. package/server/service/reference/knob-defaults.ts +0 -59
  311. package/server/service/reference/live-cadence.ts +0 -129
  312. package/server/service/reference/live-feed-lease.ts +0 -56
  313. package/server/service/reference/live-ingest.ts +0 -94
  314. package/server/service/reference/reference-adapter.ts +0 -985
  315. package/server/service/reference/reference-assessment.ts +0 -250
  316. package/server/service/reference/reference-fill-run.ts +0 -179
  317. package/server/service/reference/reference-fill.ts +0 -223
  318. package/server/service/reference/reference-hook.ts +0 -479
  319. package/server/service/reference/reference-link-groups.ts +0 -21
  320. package/server/service/reference/reference-links.ts +0 -77
  321. package/server/service/reference/reference-live.ts +0 -420
  322. package/server/service/reference/reference-master.ts +0 -999
  323. package/server/service/reference/reference-probe.ts +0 -264
  324. package/server/service/reference/reference-progress-channel.ts +0 -26
  325. package/server/service/reference/reference-progress-subscription.ts +0 -78
  326. package/server/service/reference/reference-progress.ts +0 -95
  327. package/server/service/reference/reference-reconciliation-query.ts +0 -28
  328. package/server/service/reference/reference-reconciliation-writer.ts +0 -38
  329. package/server/service/reference/reference-reconciliation.ts +0 -55
  330. package/server/service/reference/reference-registry.ts +0 -17
  331. package/server/service/reference/reference-resolver.ts +0 -969
  332. package/server/service/reference/template-registry.ts +0 -85
  333. package/server/service/reference/twin-reference-reconciliation.ts +0 -27
  334. package/server/service/reference/twin-reference.ts +0 -190
  335. package/server/service/twin-attention/index.ts +0 -3
  336. package/server/service/twin-attention/twin-attention-query.ts +0 -70
  337. package/server/service/twin-audit/command-audit.ts +0 -114
  338. package/server/service/twin-audit/index.ts +0 -5
  339. package/server/service/twin-audit/twin-audit-event.ts +0 -158
  340. package/server/service/twin-audit/twin-audit-query.ts +0 -72
  341. package/server/service/twin-backfill/backfill-period-facts.ts +0 -168
  342. package/server/service/twin-backfill/backfill-shape.ts +0 -86
  343. package/server/service/twin-backfill/index.ts +0 -3
  344. package/server/service/twin-backfill/twin-backfill-resolver.ts +0 -35
  345. package/server/service/twin-control/index.ts +0 -3
  346. package/server/service/twin-control/twin-control-mutation.ts +0 -150
  347. package/server/service/twin-event/index.ts +0 -3
  348. package/server/service/twin-event/journal-count.ts +0 -53
  349. package/server/service/twin-event/twin-event-keys.ts +0 -215
  350. package/server/service/twin-event/twin-event-type.ts +0 -68
  351. package/server/service/twin-event/twin-event.ts +0 -250
  352. package/server/service/twin-forecast/forecast-metrics.ts +0 -106
  353. package/server/service/twin-forecast/forecast-tuning.ts +0 -40
  354. package/server/service/twin-forecast/gap-analytics.ts +0 -139
  355. package/server/service/twin-forecast/index.ts +0 -3
  356. package/server/service/twin-forecast/twin-forecast-query.ts +0 -486
  357. package/server/service/twin-ingest-window/index.ts +0 -7
  358. package/server/service/twin-ingest-window/twin-ingest-window-query.ts +0 -125
  359. package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +0 -57
  360. package/server/service/twin-ingest-window/twin-ingest-window.ts +0 -113
  361. package/server/service/twin-instance/index.ts +0 -3
  362. package/server/service/twin-instance/twin-instance.ts +0 -199
  363. package/server/service/twin-journal/event-type-split-shape.ts +0 -112
  364. package/server/service/twin-journal/event-type-split.ts +0 -144
  365. package/server/service/twin-journal/index.ts +0 -3
  366. package/server/service/twin-journal/journal-order.ts +0 -20
  367. package/server/service/twin-journal/twin-journal-query.ts +0 -615
  368. package/server/service/twin-lifecycle/domain-catalog.ts +0 -51
  369. package/server/service/twin-lifecycle/index.ts +0 -3
  370. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +0 -285
  371. package/server/service/twin-metrics/index.ts +0 -3
  372. package/server/service/twin-metrics/twin-metrics-query.ts +0 -172
  373. package/server/service/twin-model/axis-journal-evidence.ts +0 -57
  374. package/server/service/twin-model/choose-recipe.ts +0 -31
  375. package/server/service/twin-model/epcis-coverage.ts +0 -251
  376. package/server/service/twin-model/external-resolver.ts +0 -173
  377. package/server/service/twin-model/iec61850-coverage.ts +0 -111
  378. package/server/service/twin-model/index.ts +0 -25
  379. package/server/service/twin-model/isa95-coverage.ts +0 -320
  380. package/server/service/twin-model/item-ref.ts +0 -80
  381. package/server/service/twin-model/name-index.ts +0 -94
  382. package/server/service/twin-model/project-structure.ts +0 -213
  383. package/server/service/twin-model/standard-coverage.ts +0 -35
  384. package/server/service/twin-model/status-tally.ts +0 -37
  385. package/server/service/twin-model/twin-equipment.ts +0 -191
  386. package/server/service/twin-model/twin-lineage-query.ts +0 -327
  387. package/server/service/twin-model/twin-location.ts +0 -147
  388. package/server/service/twin-model/twin-model-item-query.ts +0 -1029
  389. package/server/service/twin-model/twin-model-mutation.ts +0 -503
  390. package/server/service/twin-model/twin-model-query.ts +0 -792
  391. package/server/service/twin-model/twin-model-tree-query.ts +0 -211
  392. package/server/service/twin-model/twin-operation.ts +0 -157
  393. package/server/service/twin-readiness/index.ts +0 -3
  394. package/server/service/twin-readiness/twin-readiness-query.ts +0 -96
  395. package/server/service/twin-space/area-resolver.ts +0 -75
  396. package/server/service/twin-space/index.ts +0 -8
  397. package/server/service/twin-space/move-space.ts +0 -262
  398. package/server/service/twin-space/representation-role.ts +0 -15
  399. package/server/service/twin-space/space-integrity.ts +0 -293
  400. package/server/service/twin-space/twin-area.ts +0 -63
  401. package/server/service/twin-space/twin-space-area.ts +0 -66
  402. package/server/service/twin-space/twin-space-representation.ts +0 -99
  403. package/server/service/twin-space/twin-space-resolver.ts +0 -582
  404. package/server/service/twin-space/twin-space.ts +0 -148
  405. package/server/service/twin-state/index.ts +0 -3
  406. package/server/service/twin-state/twin-state-subscription.ts +0 -62
  407. package/server/service/twin-structure/index.ts +0 -3
  408. package/server/service/twin-structure/twin-structure.ts +0 -96
  409. package/server/service/twin-subject/event-subjects.ts +0 -162
  410. package/server/service/twin-subject/index.ts +0 -10
  411. package/server/service/twin-subject/item-resolver.ts +0 -92
  412. package/server/service/twin-subject/subject-query-shape.ts +0 -84
  413. package/server/service/twin-subject/twin-subject-backfill.ts +0 -196
  414. package/server/service/twin-subject/twin-subject-event.ts +0 -101
  415. package/server/service/twin-subject/twin-subject-fast-path.ts +0 -346
  416. package/server/service/twin-subject/twin-subject-query.ts +0 -210
  417. package/server/service/twin-subject/twin-subject-writer.ts +0 -189
  418. package/server/service/twin-target/index.ts +0 -5
  419. package/server/service/twin-target/twin-target-resolver.ts +0 -142
  420. package/server/service/twin-target/twin-target.ts +0 -97
  421. package/server/types/global.d.ts +0 -22
  422. package/shared/axis-read.ts +0 -28
  423. package/shared/entity-delta.ts +0 -335
  424. package/shared/kpi-broadcast.ts +0 -13
  425. package/shared/touched-items.ts +0 -73
  426. package/shared/twin-level.ts +0 -48
  427. package/test/ack-shape-alignment.test.ts +0 -97
  428. package/test/actuation-advisor.test.ts +0 -55
  429. package/test/actuation-approval-door.test.ts +0 -411
  430. package/test/actuation-dispatch.test.ts +0 -209
  431. package/test/actuation-effect.test.ts +0 -162
  432. package/test/actuation-outcome.test.ts +0 -152
  433. package/test/actuation-rule-runner.test.ts +0 -281
  434. package/test/actuation-rule.test.ts +0 -266
  435. package/test/actuation-seam.test.ts +0 -255
  436. package/test/actuation-settle.test.ts +0 -164
  437. package/test/actuation-target.test.ts +0 -145
  438. package/test/actuation-verification-state.test.ts +0 -139
  439. package/test/adopt-structure-live.test.ts +0 -133
  440. package/test/aggregate-not-findone.test.ts +0 -112
  441. package/test/area-resolver-db.test.ts +0 -110
  442. package/test/attention-digest.test.ts +0 -161
  443. package/test/axis-declaration-passthrough-db.test.ts +0 -152
  444. package/test/axis-journal-evidence.test.ts +0 -71
  445. package/test/axis-read.test.ts +0 -188
  446. package/test/backfill-shape.test.ts +0 -89
  447. package/test/boot-resume.test.ts +0 -287
  448. package/test/broadcast-cost-baseline.test.ts +0 -201
  449. package/test/broadcast-period.test.ts +0 -58
  450. package/test/broadcast-queue-overflow.test.ts +0 -244
  451. package/test/canonical-ingest-vocabularies.test.ts +0 -451
  452. package/test/canonical-quantity-door.test.ts +0 -61
  453. package/test/capability-mapping.test.ts +0 -89
  454. package/test/checkpoint-refuses-empty.test.ts +0 -103
  455. package/test/choose-recipe.test.ts +0 -117
  456. package/test/column-type-portability.test.ts +0 -122
  457. package/test/command-routing.test.ts +0 -61
  458. package/test/command-store-writes-columns.test.ts +0 -126
  459. package/test/connection-portability-doors.test.ts +0 -87
  460. package/test/connector-capability-declaration.test.ts +0 -195
  461. package/test/contract-layer-guard.test.ts +0 -48
  462. package/test/control-capability.test.ts +0 -98
  463. package/test/cursor-stall-not-read-failure.test.ts +0 -126
  464. package/test/declaration-reaches-model.test.ts +0 -226
  465. package/test/declared-location-types.test.ts +0 -89
  466. package/test/declared-stimulus.test.ts +0 -88
  467. package/test/dedupe-transformation.test.ts +0 -112
  468. package/test/discovery-result.test.ts +0 -75
  469. package/test/dispatch-after-approval-source.test.ts +0 -81
  470. package/test/duration-estimators.test.ts +0 -144
  471. package/test/energy-topology.test.ts +0 -113
  472. package/test/entity-delta.test.ts +0 -352
  473. package/test/equipment-identity-reaches.test.ts +0 -57
  474. package/test/event-subjects.test.ts +0 -148
  475. package/test/event-time-column.test.ts +0 -67
  476. package/test/event-type-split.test.ts +0 -178
  477. package/test/external-resolver.test.ts +0 -177
  478. package/test/fact-scope-wiring.test.ts +0 -96
  479. package/test/fill-dedupe.test.ts +0 -59
  480. package/test/fill-loop.test.ts +0 -35
  481. package/test/first-envelope.test.ts +0 -153
  482. package/test/fold-gap-speaks.test.ts +0 -53
  483. package/test/fold-shift-dst.test.ts +0 -110
  484. package/test/forecast-metrics.test.ts +0 -157
  485. package/test/forecast-tuning.test.ts +0 -42
  486. package/test/gap-analytics.test.ts +0 -113
  487. package/test/generated-not-counted.test.ts +0 -99
  488. package/test/guard-roots.ts +0 -76
  489. package/test/home-in-area.test.ts +0 -90
  490. package/test/hook-address.test.ts +0 -28
  491. package/test/hook-rejected-shape.test.ts +0 -86
  492. package/test/hook-response-sum.test.ts +0 -193
  493. package/test/hook-sequence.test.ts +0 -333
  494. package/test/ingest-bench.test.ts +0 -70
  495. package/test/ingest-dedupe.test.ts +0 -56
  496. package/test/ingest-expected-quiet.test.ts +0 -111
  497. package/test/ingest-health-engine.test.ts +0 -248
  498. package/test/ingest-health-wiring.test.ts +0 -120
  499. package/test/ingest-health.test.ts +0 -306
  500. package/test/ingest-history.test.ts +0 -247
  501. package/test/ingest-idempotent.test.ts +0 -211
  502. package/test/ingest-reconcile-four-ways.test.ts +0 -97
  503. package/test/ingest-rules-header.test.ts +0 -100
  504. package/test/ingest-running-guard.test.ts +0 -136
  505. package/test/ingest-space.test.ts +0 -78
  506. package/test/ingest-window-rolls-unobserved.test.ts +0 -72
  507. package/test/ingest-wiring-guard.test.ts +0 -197
  508. package/test/instance-cache-lifecycle.test.ts +0 -110
  509. package/test/intake-mapping-parity.test.ts +0 -175
  510. package/test/integration-probes.test.ts +0 -103
  511. package/test/integration-runner.test.ts +0 -95
  512. package/test/item-ref.test.ts +0 -78
  513. package/test/journal-order-axis.test.ts +0 -80
  514. package/test/journal-read-discipline.test.ts +0 -186
  515. package/test/journal-retention.test.ts +0 -275
  516. package/test/journal-sort-axis.test.ts +0 -142
  517. package/test/journal-write-door.test.ts +0 -110
  518. package/test/journal-write-trend.test.ts +0 -115
  519. package/test/kernel-kind-guard.test.ts +0 -98
  520. package/test/knob-defaults.test.ts +0 -72
  521. package/test/kpi-baseline-db.test.ts +0 -216
  522. package/test/kpi-baseline.test.ts +0 -196
  523. package/test/kpi-fold.test.ts +0 -1456
  524. package/test/kpi-query-bench.test.ts +0 -130
  525. package/test/lens-own-places.test.ts +0 -50
  526. package/test/lineage-survives-restart.test.ts +0 -234
  527. package/test/live-cadence.test.ts +0 -170
  528. package/test/live-cursor-wiring.test.ts +0 -87
  529. package/test/live-feed-lease.test.ts +0 -63
  530. package/test/live-feed-registry.test.ts +0 -75
  531. package/test/live-kernel-facts.test.ts +0 -161
  532. package/test/live-mirror-parity.test.ts +0 -286
  533. package/test/load-meter.test.ts +0 -328
  534. package/test/local-declarations.test.ts +0 -662
  535. package/test/log-stamp.test.ts +0 -59
  536. package/test/loop-lag.test.ts +0 -82
  537. package/test/master-to-twin.test.ts +0 -279
  538. package/test/measured-yield.test.ts +0 -90
  539. package/test/merge-streams.test.ts +0 -70
  540. package/test/mirror-resumes-from-checkpoint.test.ts +0 -192
  541. package/test/model-basis.test.ts +0 -141
  542. package/test/model-gap.test.ts +0 -153
  543. package/test/model-refusal.test.ts +0 -75
  544. package/test/model-vocabulary.test.ts +0 -114
  545. package/test/move-space.test.ts +0 -149
  546. package/test/mutation-gate.test.ts +0 -122
  547. package/test/oee-accumulator.test.ts +0 -204
  548. package/test/oee-site-calendar.test.ts +0 -146
  549. package/test/open-doors.test.ts +0 -197
  550. package/test/operation-basis.test.ts +0 -127
  551. package/test/operational-vocabulary.test.ts +0 -108
  552. package/test/operations-capability-db.test.ts +0 -165
  553. package/test/order-and-transaction-split.test.ts +0 -107
  554. package/test/order-fold-host.test.ts +0 -112
  555. package/test/producer-guard.test.ts +0 -66
  556. package/test/project-structure-db.test.ts +0 -226
  557. package/test/projection-reaches-screen.test.ts +0 -277
  558. package/test/projection-reads-declared.test.ts +0 -109
  559. package/test/property-effects.test.ts +0 -128
  560. package/test/provenance-promotion.test.ts +0 -99
  561. package/test/read-failure-ledger.test.ts +0 -106
  562. package/test/read-failure-visible.test.ts +0 -145
  563. package/test/read-time.test.ts +0 -118
  564. package/test/reference-fill.test.ts +0 -235
  565. package/test/reference-grounding.test.ts +0 -70
  566. package/test/reference-hook.test.ts +0 -177
  567. package/test/reference-links.test.ts +0 -56
  568. package/test/reference-reconciliation.test.ts +0 -39
  569. package/test/registry-key-guard.test.ts +0 -80
  570. package/test/rejection-carries-event-id.test.ts +0 -101
  571. package/test/rename-twin.test.ts +0 -89
  572. package/test/resolve-ts-siblings.mjs +0 -52
  573. package/test/restart-policy.test.ts +0 -111
  574. package/test/resync-origin-site.test.ts +0 -83
  575. package/test/retry-plan.test.ts +0 -139
  576. package/test/revision-axis.test.ts +0 -110
  577. package/test/runtime-key.test.ts +0 -66
  578. package/test/save-intake-collision.test.ts +0 -91
  579. package/test/scale-twin-bench.test.ts +0 -103
  580. package/test/secrets-at-rest.test.ts +0 -135
  581. package/test/snapshot-freshness.test.ts +0 -60
  582. package/test/source-outcome-audit.test.ts +0 -104
  583. package/test/space-integrity.test.ts +0 -223
  584. package/test/space-representation.test.ts +0 -66
  585. package/test/space-scope-includes-stopped.test.ts +0 -55
  586. package/test/spec-coverage.test.ts +0 -113
  587. package/test/stage-path.test.ts +0 -95
  588. package/test/standard-coverage.test.ts +0 -148
  589. package/test/state-axes.test.ts +0 -74
  590. package/test/status-tally.test.ts +0 -55
  591. package/test/streamline-e2e.test.ts +0 -76
  592. package/test/structure-revision-db.test.ts +0 -315
  593. package/test/subject-fast-path.test.ts +0 -148
  594. package/test/subject-read-model.test.ts +0 -175
  595. package/test/sweep-dispatch.test.ts +0 -191
  596. package/test/tenant-registry-db.test.ts +0 -149
  597. package/test/time-range.test.ts +0 -152
  598. package/test/touched-items.test.ts +0 -61
  599. package/test/twin-audit.test.ts +0 -83
  600. package/test/twin-event-keys.test.ts +0 -193
  601. package/test/twin-model-item-db.test.ts +0 -319
  602. package/test/twin-model-parent-relation-db.test.ts +0 -125
  603. package/test/twin-model-tree-db.test.ts +0 -209
  604. package/test/twin-origin-resync.test.ts +0 -133
  605. package/test/twin-state-channel.test.ts +0 -111
  606. package/test/vocabulary-guard.test.ts +0 -43
  607. package/test/warm-start-seam.test.ts +0 -162
  608. package/test/warm-start.test.ts +0 -297
  609. package/test/withheld-door.test.ts +0 -95
  610. package/test/yield-loop.test.ts +0 -199
  611. package/tsconfig.json +0 -15
  612. package/tsconfig.shared.json +0 -23
  613. package/tsconfig.shared.tsbuildinfo +0 -1
  614. package/tsconfig.tsbuildinfo +0 -1
@@ -1,110 +0,0 @@
1
- /*
2
- * ★ 리비전은 **두 셈**이고, 둘이 같은 것을 세지 않는다 — 그 사실을 코드가 지키는지 본다.
3
- *
4
- * ── 무엇이 어긋나 있었나 (2026-08-23 실측) ──────────────────────────────────
5
- * 포천 미러의 체크포인트가 뜻이 다른 두 수를 나란히 적었다.
6
- *
7
- * 바깥 revision 12,972 저널에 적힌 줄 번호
8
- * state.revision 6,478 커널이 처리한 봉투 수
9
- *
10
- * 차이 6,494 는 그 트윈을 **다시 세운 시각**(09:11)에 저널이 이미 갖고 있던 줄 수와 정확히 같았다
11
- * (줄 6494 = 08:23:59 · 줄 6495 = 09:11:13). 산수가 맞았으니 결함은 「수가 틀렸다」가 아니다.
12
- *
13
- * 결함은 **비대칭**이었다. 재기동 경로(`start` → `resumeRevision`)는 커널에 저널 머리를 알려 주는데
14
- * 미러를 세우는 경로(`startLive`)는 알려 주지 않았다. 그래서 같은 저장물을 읽는 사람이 같은 이름의 두
15
- * 수를 같은 축으로 견주게 되고, 실제로 그렇게 읽혔다(반나절이 그 오독에서 나갔다).
16
- *
17
- * ── 왜 알려 주어야 하나 ─────────────────────────────────────────────────────
18
- * 커널의 계약이 그 이유를 적어 두었다(`resumeRevision`): 「저널이 비어 있지 않은데 0부터 다시 세면 같은
19
- * 트윈에 같은 리비전이 둘 생기고, 재생 순서가 뒤섞이며, 시간여행이 엉뚱한 시점을 답한다 — 오류는 안 난다.」
20
- * 알리지 않고 깨지는 종류이므로 시험이 지킨다.
21
- *
22
- * ── 이 시험이 무엇을 재는가 ─────────────────────────────────────────────────
23
- * DB 도 커널도 띄우지 않는다. 이 규율은 **어느 경로가 무엇을 부르나**에 있고 그것은 소스에서 확인된다.
24
- */
25
- import { test } from 'node:test'
26
- import assert from 'node:assert/strict'
27
- import { readFileSync } from 'node:fs'
28
- import { join } from 'node:path'
29
-
30
- const ENGINE = join(import.meta.dirname, '..', 'server', 'engine', 'twin-engine.ts')
31
- const src = readFileSync(ENGINE, 'utf8')
32
-
33
- /**
34
- * 그 함수 본문만 — 다른 경로의 호출이 섞여 판정이 흐려지지 않게.
35
- *
36
- * 끝은 **다음 멤버 선언**으로 자른다. 글자 수로 자르면 주석이 늘어난 날 알리지 않고 짧아져서, 있는 것을
37
- * 없다고 말한다(거짓 빨강을 내는 가드는 없는 것보다 나쁘다).
38
- */
39
- function bodyOf(signature: string): string {
40
- const at = src.indexOf(signature)
41
- assert.ok(at > 0, `${signature} 이 있어야 한다`)
42
- const rest = src.slice(at + signature.length)
43
- const end = rest.search(/\n (?:static|private static|\/\*\*)/)
44
- const body = end === -1 ? rest : rest.slice(0, end)
45
- /* 잘라낸 본문이 비면 판정이 성립하지 않는다 — 그것을 통과로 읽지 않는다. */
46
- assert.ok(body.length > 200, `${signature} 본문을 잘라내지 못했다(${body.length}자)`)
47
- return body
48
- }
49
-
50
- test('미러를 세우는 경로도 커널에 저널 머리를 알려 준다', () => {
51
- const body = bodyOf('static startLive(')
52
- /*
53
- * 저널 머리를 읽는다 — 이 조회는 예전부터 있었다(inst.revision 시드용).
54
- *
55
- * 2026-08-28: 모양을 `findOne(order: revision DESC)` 에서 `MAX(e.revision)` 으로 바꿨다. 앞의 것은
56
- * 관계로 물어 두 단계 질의가 되고 안쪽에 상한이 없어 그 트윈의 저널을 전부 만든 뒤 한 줄을 고른다.
57
- * **묻는 것은 같다** — 저널 머리다. 그래서 이 단정은 「머리를 읽는가」로 남고 모양만 따라간다.
58
- */
59
- assert.match(body, /select\('MAX\(e\.revision\)'/, '저널 머리를 읽어야 한다')
60
- /* 그리고 **커널에도** 알려 준다 — 이 한 줄이 없어서 두 수가 갈렸다. */
61
- assert.match(body, /resumeRevision\(head\)/, '커널에도 그 번호를 알려 준다')
62
- })
63
-
64
- test('재기동 경로는 예전부터 알려 주고 있었다 — 두 경로가 같아졌는지 본다', () => {
65
- /*
66
- * 이 단정은 「고쳤다」가 아니라 **두 경로가 대칭인지**를 지킨다. 한쪽만 남으면 같은 결함이 다른
67
- * 문으로 되살아난다.
68
- */
69
- const body = bodyOf('static start(')
70
- assert.match(body, /resumeRevision\(resumeFrom\)/, '재기동 경로도 알려 준다')
71
- })
72
-
73
- test('저널이 비어 있으면 알려 주지 않는다 — 새 트윈은 0 부터 세는 것이 맞다', () => {
74
- const body = bodyOf('static startLive(')
75
- assert.match(body, /if \(!head \|\| typeof/, '머리가 0 이면 아무 일도 하지 않는다')
76
- })
77
-
78
- test('뒤로 되돌리려는 거절을 삼키지 않는다', () => {
79
- /*
80
- * 조회가 비동기라 그 사이에 이벤트가 들어와 있을 수 있다. 그때 커널은 뒤로 가기를 거절한다(겹치는
81
- * 번호를 막는 그 판정이다). 그 거절을 알리지 않고 버리면 「왜 두 수가 아직 다르지」를 답할 계기가 없다.
82
- */
83
- const body = bodyOf('static startLive(')
84
- assert.match(body, /catch \(err[^)]*\)[\s\S]{0,200}twinWarn/, '거절을 로그에 남긴다')
85
- assert.match(body, /is behind the kernel/, '무엇이 어긋났는지 말한다')
86
- })
87
-
88
- test('체크포인트는 두 수를 나란히 적는다 — 그 사실 자체는 옳다', () => {
89
- /*
90
- * 바깥은 저널 줄 번호(이어 쓸 자리), 안쪽은 커널이 계산한 봉투 수다. **둘을 하나로 합치지 않는다** —
91
- * 합치면 「어디까지 적었나」와 「어디까지 반영했나」를 구별할 수 없고, 그 구별이 미러의 정직성이다.
92
- * 두 경로가 대칭이면 값이 같아지지만, **자리는 둘이어야 한다.**
93
- */
94
- const at = src.indexOf('static async persistSnapshot')
95
- assert.ok(at > 0, 'persistSnapshot 이 있어야 한다')
96
- /*
97
- * 창을 넓혀 왔다 — 이 함수 앞쪽에 「빈 상태로 좋은 스냅샷을 덮지 않는다」 가드가 들어오고(§
98
- * `checkpoint-refuses-empty`), 뒤쪽에 「이어 계산할 씨앗을 함께 적는다」가 들어왔다(§
99
- * `mirror-resumes-from-checkpoint`). 검사하는 **사실은 그대로**다.
100
- *
101
- * 그리고 **줄 모양이 아니라 두 자리를 검사한다**: 예전에는 `{ revision, state` 라는 한 줄 모양을
102
- * 봤는데, 저장 인자가 여러 줄로 나뉘자 사실이 그대로인데도 빨강이 됐다. 서식이 검사를 깨면 다음
103
- * 사람이 검사를 지우게 된다 — 그래서 이름 둘이 함께 실리는지만 본다.
104
- */
105
- const body = src.slice(at, at + 5000)
106
- assert.match(body, /inst\.revision \?\? state\.revision/, '바깥은 저널 줄 번호를 먼저 쓴다')
107
- const call = body.slice(body.indexOf('setInCache'))
108
- assert.match(call, /revision/, '저널 줄 번호를 싣는다')
109
- assert.match(call, /state/, '커널이 계산한 상태를 함께 싣는다 — 두 자리를 하나로 합치지 않는다')
110
- })
@@ -1,66 +0,0 @@
1
- /*
2
- * 런타임 키 — **트윈의 정체성은 `(도메인, 인스턴스 id)`.**
3
- *
4
- * 계기(2026-08-06): 런타임 레지스트리가 `instanceId` 하나로 키를 잡고 있었다. 레퍼런스 경로가 소스
5
- * 이름을 그대로 id 로 쓰므로(`sap-ewm-1710`) 두 테넌트가 같은 벤더 시스템에 연결하면 같은 id 가 된다 —
6
- * 그때 남의 커널에 이벤트가 적용되거나, 웜스타트 씨앗이 남의 스냅샷이 됐다.
7
- *
8
- * 이 테스트가 지키는 것은 **키가 모호해지지 않는 것** 하나다. 모호한 키는 오류 없이 틀린 값을 낸다.
9
- */
10
- import { test } from 'node:test'
11
- import assert from 'node:assert/strict'
12
-
13
- import { RUNTIME_KEY_SEP, isOfDomain, parseRuntimeKey, runtimeKey } from '../server/engine/runtime-key.ts'
14
-
15
- const D1 = '11111111-1111-1111-1111-111111111111'
16
- const D2 = '22222222-2222-2222-2222-222222222222'
17
-
18
- test('같은 인스턴스 id 라도 테넌트가 다르면 다른 키다 — 이 작업의 요점', () => {
19
- assert.notEqual(runtimeKey(D1, 'sap-ewm-1710'), runtimeKey(D2, 'sap-ewm-1710'))
20
- })
21
-
22
- test('같은 테넌트·같은 id 는 같은 키다 — 재기동이 자기 자리를 찾는다', () => {
23
- assert.equal(runtimeKey(D1, 'hatiolab-wms'), runtimeKey(D1, 'hatiolab-wms'))
24
- })
25
-
26
- test('되돌리면 원래 둘이 나온다', () => {
27
- const { domainId, instanceId } = parseRuntimeKey(runtimeKey(D1, 'hatiolab-wms'))
28
-
29
- assert.equal(domainId, D1)
30
- assert.equal(instanceId, 'hatiolab-wms')
31
- })
32
-
33
- test('인스턴스 id 안의 구분자를 보존한다 — 첫 구분자에서만 자른다', () => {
34
- /* 레퍼런스 소스 이름에 `:` 가 들어갈 수 있다. 마지막 구분자에서 자르면 id 가 잘려 다른 트윈이 된다. */
35
- const weird = 'urn:epc:id:sgln:0614141.12345'
36
- const { domainId, instanceId } = parseRuntimeKey(runtimeKey(D1, weird))
37
-
38
- assert.equal(domainId, D1)
39
- assert.equal(instanceId, weird)
40
- })
41
-
42
- test('도메인 id 에 구분자가 있으면 오류를 낸다 — 알리지 않고 모호한 키를 만들지 않는다', () => {
43
- /* 알리지 않고 만들면 그게 곧 이 결함의 재발이다(어느 테넌트인지 알 수 없는 키). */
44
- assert.throws(() => runtimeKey(`a${RUNTIME_KEY_SEP}b`, 'x'), /ambiguous/)
45
- })
46
-
47
- test('빈 값은 키가 될 수 없다 — 테넌트 없는 런타임은 없다', () => {
48
- assert.throws(() => runtimeKey('', 'x'), /domainId is required/)
49
- assert.throws(() => runtimeKey(D1, ''), /instanceId is required/)
50
- })
51
-
52
- test('키가 아닌 것을 되돌리려 하면 오류를 낸다', () => {
53
- for (const bad of ['', 'no-separator', `${RUNTIME_KEY_SEP}leading`, `trailing${RUNTIME_KEY_SEP}`]) {
54
- assert.throws(() => parseRuntimeKey(bad), /is not a runtime key/, `입력: "${bad}"`)
55
- }
56
- })
57
-
58
- test('도메인으로 걸러낸다 — 접두사가 아니라 경계까지 본다', () => {
59
- const key = runtimeKey(D1, 'wms')
60
-
61
- assert.equal(isOfDomain(key, D1), true)
62
- assert.equal(isOfDomain(key, D2), false)
63
- /* 도메인 id 의 앞부분만 같은 것에 걸리지 않는다(구분자까지 붙여 본다). */
64
- assert.equal(isOfDomain(key, D1.slice(0, 8)), false)
65
- assert.equal(isOfDomain(key, ''), false)
66
- })
@@ -1,91 +0,0 @@
1
- /*
2
- * ★ **화면 저장도 받는 사이트 충돌을 거부한다** (ADR-0046 ②-1, 2026-09-16)
3
- *
4
- * 들여오기에는 충돌 거부가 있는데 화면 저장(`saveTwinReference`)에는 없었다. `intakeEndpoint::intakeSiteId`
5
- * 가 같은 연결 둘을 만들면 받는 문은 둘 다 200 으로 받고 경고가 0 이다 — 잘못된 공장이 실제로 만든다.
6
- * 이 검사는 저장의 문이 쓰는 판정(`refuseIntakeCollision`)을 값으로 못 박는다.
7
- */
8
- import { test } from 'node:test'
9
- import assert from 'node:assert/strict'
10
- import { readFileSync } from 'node:fs'
11
-
12
- import { intakeCollisions, refuseIntakeCollision } from '../server/service/reference/connection-portability.js'
13
-
14
- const intake = { intakeEndpoint: 'https://plant.example/intake/', intakeSiteId: 'system' }
15
- const existing = [
16
- { source: 'mes-line-a', siteName: 'Line A', connectionConfig: { baseUrl: 'https://plant.example', ...intake } }
17
- ]
18
-
19
- test('★ 같은 받는 사이트를 가리키는 둘째 연결은 거부되고, 부딪힌 연결의 이름을 말한다', () => {
20
- const r = refuseIntakeCollision('mes-line-b', { baseUrl: 'https://plant.example', ...intake }, existing)
21
- assert.ok(r, '베낀 연결이 그대로 저장된다')
22
- assert.equal(r.code, 'intake-site-taken')
23
- assert.equal(r.params.site, 'system')
24
- assert.equal(r.params.connection, 'Line A', '무엇과 부딪혔는지 말하지 않는다')
25
- })
26
-
27
- test('주소 끝의 / 하나로 비껴가지 않는다', () => {
28
- const r = refuseIntakeCollision('mes-line-b', { intakeEndpoint: 'https://plant.example/intake', intakeSiteId: 'system' }, existing)
29
- assert.ok(r)
30
- })
31
-
32
- test('자기 자신을 다시 저장하는 것은 충돌이 아니다', () => {
33
- assert.equal(refuseIntakeCollision('mes-line-a', existing[0].connectionConfig, existing), null)
34
- })
35
-
36
- test('사이트를 고치면 저장된다 — 한 글자 고친 사람은 그 자리에서 지난다', () => {
37
- assert.equal(refuseIntakeCollision('mes-line-b', { ...intake, intakeSiteId: 'line-b' }, existing), null)
38
- })
39
-
40
- test('조치 주소가 없는 연결은 부딪힐 것이 없다', () => {
41
- assert.equal(refuseIntakeCollision('wms-x', { baseUrl: 'https://plant.example', siteId: 'system' }, existing), null)
42
- })
43
-
44
- test('★ 저장의 문이 그 판정을 부르고, 거부하면 쓰기 전에 돌아간다', () => {
45
- const src = readFileSync(new URL('../server/service/reference/reference-resolver.ts', import.meta.url), 'utf8')
46
- const body = src.slice(src.indexOf('async saveTwinReference('), src.indexOf('async deleteTwinReference('))
47
- const check = body.indexOf('refuseIntakeCollision(')
48
- const write = body.indexOf('repo.save(')
49
- assert.ok(check > 0, 'saveTwinReference 가 충돌 판정을 부르지 않는다')
50
- assert.ok(check < write, '판정이 쓰기 뒤에 있다 — 이미 저장된 뒤의 거부는 거부가 아니다')
51
- assert.match(body, /errorCode: taken\.code/)
52
- })
53
-
54
- /*
55
- * ★ **같은 충돌을 두 모양으로 건다** (ADR-0053 ②, 2026-09-16).
56
- *
57
- * 패키지는 `config`, `TwinReference` 행은 `connectionConfig` 다. 전에는 `config` 만 읽어서 행을 그대로
58
- * 넘기면 `[]` 였다 — 오류도 경고도 없이 저장이 통과했다. 부르는 둘이 마침 옮겨서 부른 덕에 멀쩡했는데,
59
- * 그건 계약이 아니라 우연이다(이 함수는 화면이 쓰라고 리졸버에서 다시 내보내진다).
60
- *
61
- * 옮기기가 다시 갈리는 날 **빨개지는 자리가 여기 하나**다. 그래서 「두 모양이 같은 답을 낸다」를
62
- * 값으로 센다 — 결정의 내용이 그것이므로.
63
- */
64
- const pair = [
65
- { source: 'mes-line-a', ...intake },
66
- { source: 'mes-line-b', ...intake }
67
- ]
68
-
69
- test('★ DB 행 모양(connectionConfig)으로 걸어도 같은 충돌이 나온다 — 「없다」가 편한 답인 자리다', () => {
70
- const rows = intakeCollisions(pair.map(({ source, ...cfg }) => ({ source, connectionConfig: cfg })))
71
-
72
- assert.equal(rows.length, 1, '행 모양을 못 알아보고 조용히 넘어갔다')
73
- assert.deepEqual(rows[0].sources, ['mes-line-a', 'mes-line-b'])
74
- })
75
-
76
- test('★ 두 모양이 같은 답을 낸다 — 옮기기가 갈리면 여기가 빨개진다', () => {
77
- const asConfig = intakeCollisions(pair.map(({ source, ...cfg }) => ({ source, config: cfg })))
78
- const asRow = intakeCollisions(pair.map(({ source, ...cfg }) => ({ source, connectionConfig: cfg })))
79
-
80
- assert.deepEqual(asRow, asConfig)
81
- })
82
-
83
- test('섞여 들어와도 한 충돌로 본다 — 들여오기는 실제로 행과 패키지를 함께 넘긴다', () => {
84
- const mixed = intakeCollisions([
85
- { source: 'mes-line-a', connectionConfig: { ...intake } },
86
- { source: 'mes-line-b', config: { ...intake } }
87
- ])
88
-
89
- assert.equal(mixed.length, 1, '섞인 목록에서 한쪽만 세었다')
90
- assert.deepEqual(mixed[0].sources, ['mes-line-a', 'mes-line-b'])
91
- })
@@ -1,103 +0,0 @@
1
- /*
2
- * 스케일 테스트 트윈 벤치 — 미국 공장(WMS+MES+YMS) 형태를 대규모로 스케일업, 5종 동기 엔티티 전부 부하.
3
- * 동기 엔티티 = locations·items(재고)·equipment·tasks·orders (노드/무버뿐이 아님). area 는 계층(건물>층>존).
4
- * 측정(가정 아닌 실측): masterToTwin(구조 생성)·apply(혼합 이벤트 처리량)·snapshot(전체 투영)·buildEntityDeltas(브로드캐스팅, 't1')·heap.
5
- * 순수 커널+호스트 매핑(shell·DB 무관) → node:test. area 는 공간층(projector State 밖)이라 처리량엔 무영향 — 구조 생성 비용에만.
6
- */
7
- import { test } from 'node:test'
8
- import assert from 'node:assert/strict'
9
-
10
- import { StateProjector } from '@operato/twin-kernel'
11
- import { objectEvent, BIZSTEP, DISP, OP_EVENT } from '@operato/ops-contract'
12
- import { masterToTwin } from '../server/service/reference/reference-master.ts'
13
- import { buildEntityDeltas } from '../shared/entity-delta.ts'
14
-
15
- const T0 = '2026-07-20T00:00:00.000Z'
16
- const MB = (b: number) => Math.round(b / 1048576)
17
-
18
- /** 미국 공장형 대규모 master 생성: 건물>층>존 area 계층 + 노드(storage/dock/station) + 무버(forklift/cutter/welder/hostler). */
19
- function bigMaster(tier: { buildings: number; floorsPer: number; zonesPer: number; nodesPerZone: number; equipment: number }) {
20
- const locations: any[] = []
21
- let nodeN = 0
22
- for (let b = 0; b < tier.buildings; b++) {
23
- locations.push({ id: `bld-${b}`, type: 'building', role: 'area', name: `건물 ${b}` })
24
- for (let f = 0; f < tier.floorsPer; f++) {
25
- locations.push({ id: `bld-${b}-flr-${f}`, type: 'floor', role: 'area', name: `층 ${b}-${f}`, parentId: `bld-${b}` })
26
- for (let z = 0; z < tier.zonesPer; z++) {
27
- const zid = `bld-${b}-flr-${f}-zn-${z}`
28
- locations.push({ id: zid, type: 'zone', role: 'area', name: `존 ${b}-${f}-${z}`, parentId: `bld-${b}-flr-${f}` })
29
- for (let n = 0; n < tier.nodesPerZone; n++) {
30
- const t = n % 4 === 0 ? 'dock' : n % 4 === 1 ? 'staging' : 'storage'
31
- locations.push({ id: `nd-${nodeN}`, type: t, role: 'location', name: `노드 ${nodeN}`, parentId: zid, capacity: 500, footprint: { x: nodeN % 100, y: (nodeN / 100) | 0, w: 1, h: 1 } })
32
- nodeN++
33
- }
34
- }
35
- }
36
- }
37
- const KINDS = ['forklift', 'cutter', 'welder', 'hostler']
38
- const equipment = Array.from({ length: tier.equipment }, (_, i) => ({ id: `mv-${i}`, kind: KINDS[i % 4], homeLocationId: `nd-${i % nodeN}` }))
39
- return {
40
- master: { source: 'scale-us', system: 'wms' as const, siteName: 'US 공장(스케일)', space: { width: 500, depth: 300, unit: 'm', geo: { lat: 32.7, lon: -117.1 } }, locations, equipment },
41
- locationCount: nodeN,
42
- areaCount: locations.filter(l => l.role === 'area').length
43
- }
44
- }
45
-
46
- function itemEnv(i: number, location: string): any {
47
- const ev = objectEvent({ eventTime: T0, action: 'OBSERVE' as any, bizStep: BIZSTEP.storing, disposition: DISP.sellable, epcList: [`urn:epc:id:sscc:0614141.${i}`], readPoint: location })
48
- return { eventId: `i${i}`, eventType: `epcis.${ev.type}`, eventTime: T0, tenantId: 't', data: ev }
49
- }
50
- const equipmentEnv = (id: string, kind: string, loc: string): any => ({ eventId: id, eventType: OP_EVENT.equipment, eventTime: T0, tenantId: 't', data: { moverId: id, kind, status: 'running', location: loc } })
51
- const taskEnv = (id: string, to: string): any => ({ eventId: id, eventType: OP_EVENT.task, eventTime: T0, tenantId: 't', data: { taskId: id, kind: 'move', status: 'in-progress', toNode: to } })
52
- const orderEnv = (id: string): any => ({ eventId: id, eventType: OP_EVENT.order, eventTime: T0, tenantId: 't', data: { orderId: id, kind: 'inbound', status: 'in-progress', requested: 100, fulfilled: 50 } })
53
-
54
- const TIERS = {
55
- medium: { buildings: 3, floorsPer: 3, zonesPer: 4, nodesPerZone: 8, equipment: 80, items: 30000, tasks: 2000, orders: 500 },
56
- large: { buildings: 6, floorsPer: 4, zonesPer: 6, nodesPerZone: 12, equipment: 300, items: 120000, tasks: 10000, orders: 2000 }
57
- }
58
-
59
- for (const [name, tier] of Object.entries(TIERS)) {
60
- test(`스케일 트윈 [${name}] — 구조 생성 + 5종 엔티티 부하 실측`, () => {
61
- // 1) 구조 생성(masterToTwin) — 노드·무버·area 계층
62
- const { master, locationCount, areaCount } = bigMaster(tier)
63
- let t = performance.now()
64
- const { model, spaceContent } = masterToTwin(master)
65
- const tMaster = performance.now() - t
66
- console.log(`\n [${name}] 구조: 노드 ${locationCount.toLocaleString()} · 무버 ${tier.equipment} · area ${areaCount}(계층) · masterToTwin ${tMaster.toFixed(0)}ms`)
67
- assert.equal(model.locations.length, locationCount)
68
- assert.equal((spaceContent.areas ?? []).length, areaCount, 'area 계층 생성')
69
-
70
- const proj = new StateProjector(model)
71
- const equipment = model.equipment as any[]
72
-
73
- // 2) apply 처리량 — 5종 혼합(items·equipment·tasks·orders)
74
- t = performance.now()
75
- for (let i = 0; i < tier.items; i++) proj.apply(itemEnv(i, `nd-${i % locationCount}`))
76
- for (let i = 0; i < tier.equipment; i++) proj.apply(equipmentEnv(equipment[i].id, equipment[i].kind, `nd-${i % locationCount}`))
77
- for (let i = 0; i < tier.tasks; i++) proj.apply(taskEnv(`tk-${i}`, `nd-${i % locationCount}`))
78
- for (let i = 0; i < tier.orders; i++) proj.apply(orderEnv(`or-${i}`))
79
- const total = tier.items + tier.equipment + tier.tasks + tier.orders
80
- const tApply = performance.now() - t
81
- console.log(` [${name}] apply: ${total.toLocaleString()} 이벤트(items+equipment+tasks+orders) ${tApply.toFixed(0)}ms = ${Math.round((total / tApply) * 1000).toLocaleString()} ev/s`)
82
-
83
- // 3) snapshot(전체 투영) — 5종 전부
84
- let s: any
85
- const iters = 30
86
- t = performance.now()
87
- for (let k = 0; k < iters; k++) s = proj.snapshot()
88
- const tSnap = (performance.now() - t) / iters
89
- console.log(` [${name}] snapshot: ${tSnap.toFixed(2)}ms/call (items ${s.items.length.toLocaleString()}·locations ${s.locations.length.toLocaleString()}·equipment ${s.equipment.length}·tasks ${s.tasks.length}·orders ${s.orders.length}) → 최대 ${Math.round(1000 / tSnap).toLocaleString()} snap/s`)
90
-
91
- // 4) 브로드캐스팅 payload(buildEntityDeltas)
92
- t = performance.now()
93
- for (let k = 0; k < iters; k++) buildEntityDeltas(s, 't1')
94
- const tDelta = (performance.now() - t) / iters
95
- console.log(` [${name}] buildEntityDeltas: ${tDelta.toFixed(2)}ms/call`)
96
- console.log(` [${name}] heap: ${MB(process.memoryUsage().heapUsed)}MB`)
97
-
98
- // 정합 sanity
99
- assert.equal(s.equipment.length, tier.equipment)
100
- assert.equal(s.orders.length, tier.orders)
101
- assert.ok(s.items.length > 0)
102
- })
103
- }
@@ -1,135 +0,0 @@
1
- /*
2
- * A column that can hold a credential has to be encrypted at rest.
3
- *
4
- * ── What this catches, and what it cost to find by hand (2026-09-09) ──────
5
- * `TwinReference.connectionConfig` was a plain `simple-json` column holding a signing secret
6
- * and a live access token. Two shell commands read both:
7
- *
8
- * sqlite3 -readonly db.sqlite "select connection_config from twin_references"
9
- * {"endpoint":"…","hookSecret":"dev-only-localhost-hook-2026","token":"eyJhbGciOi…"}
10
- *
11
- * The read path was already guarded — the detail resolver masks fields an adapter declares
12
- * `secret: true`. So the leak was not on the way out, it was the stored bytes: the database
13
- * file, its backups, its replicas. **Two different protections, and having one reads exactly
14
- * like having both.**
15
- *
16
- * ── Why a guard and not a review habit ────────────────────────────────────
17
- * The framework has had the pieces for a while — `encryptJsonTransformer` and
18
- * `longTextColumn` — and nothing used them together. Two packages imported the transformer and
19
- * left it commented out. A rule that depends on someone remembering two exports is a rule that
20
- * holds until the next new column.
21
- *
22
- * So the rule is measured instead: any column whose name says it can carry a credential must
23
- * carry an encrypting transformer. New entities are covered the day they are written.
24
- *
25
- * ── What this does not claim ──────────────────────────────────────────────
26
- * Encryption at rest does not protect a value from anyone who can run this process — that
27
- * person holds the key. It protects the stored copy, which is a different set of people.
28
- */
29
- import { test } from 'node:test'
30
- import assert from 'node:assert/strict'
31
- import { readFileSync, readdirSync, statSync } from 'node:fs'
32
- import { fileURLToPath } from 'node:url'
33
- import { join } from 'node:path'
34
-
35
- const SERVER = fileURLToPath(new URL('../server', import.meta.url))
36
-
37
- /**
38
- * 이름이 「자격 증명이 들 수 있다」고 말하는 칸.
39
- *
40
- * 이름으로 판정하는 것의 한계를 적어 둔다 — `connectionConfig` 처럼 **이름이 비밀을 말하지 않는**
41
- * 칸이 실제로 비밀을 담고 있었다. 그래서 그 이름을 목록에 넣는다. 새 칸이 같은 부류이면 여기 더한다.
42
- */
43
- const CREDENTIAL_NAMES = /^(secret|token|password|passwd|apiKey|credential|credentials|privateKey|connectionConfig)\??$/i
44
-
45
- /** 암호화를 붙이는 방법 — 둘 중 하나면 된다(shell 이 내놓는 것). */
46
- const ENCRYPTED = /encryptedJsonColumn\(\)|encryptTransformer|encryptJsonTransformer/
47
-
48
- function entityFiles(dir: string, out: string[] = []): string[] {
49
- for (const name of readdirSync(dir)) {
50
- const full = join(dir, name)
51
- if (statSync(full).isDirectory()) {
52
- entityFiles(full, out)
53
- continue
54
- }
55
- if (!full.endsWith('.ts') || full.endsWith('.d.ts')) continue
56
- const src = readFileSync(full, 'utf-8')
57
- if (src.includes('@Entity(')) out.push(full)
58
- }
59
- return out
60
- }
61
-
62
- /** 한 파일에서 `@Column` 선언과 그것이 붙은 속성 이름의 짝. */
63
- function columnsOf(src: string): { property: string; declaration: string; line: number }[] {
64
- const lines = src.split('\n')
65
- const out: { property: string; declaration: string; line: number }[] = []
66
-
67
- for (let i = 0; i < lines.length; i++) {
68
- if (!/^\s*@Column\(/.test(lines[i])) continue
69
-
70
- /* 선언이 여러 줄일 수 있다 — 괄호가 닫힐 때까지 모은다. */
71
- let declaration = ''
72
- let depth = 0
73
- let j = i
74
- do {
75
- declaration += lines[j]
76
- for (const ch of lines[j]) {
77
- if (ch === '(') depth++
78
- else if (ch === ')') depth--
79
- }
80
- j++
81
- } while (depth > 0 && j < lines.length && j - i < 12)
82
-
83
- /* 데코레이터 다음의 첫 속성 줄 — 사이에 @Field 등이 끼어든다. */
84
- for (let k = j; k < Math.min(j + 6, lines.length); k++) {
85
- const m = /^\s{2}(?:readonly\s+)?([A-Za-z_][A-Za-z0-9_]*)\??\s*[:!]/.exec(lines[k])
86
- if (m) {
87
- out.push({ property: m[1], declaration, line: i + 1 })
88
- break
89
- }
90
- }
91
- }
92
- return out
93
- }
94
-
95
- test('★ a column that can hold a credential is encrypted at rest', () => {
96
- const offenders: string[] = []
97
- let examined = 0
98
-
99
- for (const file of entityFiles(SERVER)) {
100
- const src = readFileSync(file, 'utf-8')
101
- for (const column of columnsOf(src)) {
102
- examined++
103
- if (!CREDENTIAL_NAMES.test(column.property)) continue
104
- if (ENCRYPTED.test(column.declaration)) continue
105
- offenders.push(`${file.slice(SERVER.length + 1)}:${column.line} ${column.property}`)
106
- }
107
- }
108
-
109
- assert.ok(examined > 40, `본 칸이 ${examined}개다 — 찾는 방법이 깨졌다`)
110
- assert.deepEqual(
111
- offenders,
112
- [],
113
- 'these columns can hold a credential and are stored in the clear:\n ' +
114
- offenders.join('\n ') +
115
- '\nAdd ...encryptedJsonColumn() (json) or transformer: encryptTransformer (string) from @things-factory/shell.\n' +
116
- 'Note the column type has to change with it — encryptedJsonColumn() carries both, which is why it exists.'
117
- )
118
- })
119
-
120
- test('this guard reads real entities, so a broken scan is red and not green', () => {
121
- /*
122
- * 위 검사는 위반이 없으면 통과한다. **아무것도 못 읽어도** 통과하므로, 읽었다는 사실을 따로 잰다 —
123
- * 오늘 이 저장소의 다른 검사가 견준 것이 0인데 초록이던 부류가 넷이었다.
124
- */
125
- const files = entityFiles(SERVER)
126
- assert.ok(files.length > 10, `엔티티 파일이 ${files.length}개다 — 순회가 깨졌다`)
127
-
128
- const reference = files.find(f => f.endsWith('twin-reference.ts'))
129
- assert.ok(reference, 'twin-reference.ts 를 못 찾았다 — 이 검사가 생긴 이유가 그 파일이다')
130
-
131
- const found = columnsOf(readFileSync(reference!, 'utf-8'))
132
- const config = found.find(c => c.property === 'connectionConfig')
133
- assert.ok(config, 'connectionConfig 칸을 못 읽었다 — 짝짓기가 깨졌다')
134
- assert.match(config!.declaration, ENCRYPTED, 'connectionConfig 가 암호화되어 있지 않다')
135
- })
@@ -1,60 +0,0 @@
1
- /*
2
- * 영속 스냅샷이 **사실을 이기지 않는다** — 쓸 수 있는 조건을 못 박는다.
3
- *
4
- * 멈춘 트윈을 조회할 때마다 저널을 전량 계산하고 있었다(23,731건짜리 트윈에서 4.6초). 스냅샷은 같은
5
- * 폴드의 결과이므로 그 뒤로 아무 일도 없었다면 다시 계산해 봐야 같은 값이다 — 그래서 쓴다.
6
- *
7
- * 위험은 하나다: **낡은 스냅샷을 "지금" 이라고 내는 것.** 그래서 쓰는 조건을 좁게 잡았고, 그 조건을
8
- * 여기서 고정한다. 엔진 본체는 DB 를 물고 있어 부를 수 없으므로 판정식만 떼어 시험한다 —
9
- * 엔진이 쓰는 식과 **같은 식**이어야 의미가 있으므로, 식이 바뀌면 이 시험이 먼저 깨진다.
10
- */
11
- import { test } from 'node:test'
12
- import assert from 'node:assert/strict'
13
-
14
- /** 엔진의 조건과 같은 식(twin-engine.recover 의 스냅샷 사용 조건). */
15
- const usable = (
16
- cached: { revision?: number; structureRev?: number | null; state?: any } | null,
17
- tip: { revision: number; structureRev: number | null },
18
- asOfNow: boolean
19
- ): boolean =>
20
- !!(asOfNow && cached?.state && (cached.revision ?? 0) === tip.revision && (cached.structureRev ?? null) === tip.structureRev)
21
-
22
- const TIP = { revision: 23731, structureRev: 2 }
23
- const FRESH = { revision: 23731, structureRev: 2, state: { locations: [] } }
24
-
25
- test('끝에 있고 구조도 같으면 쓴다 — 다시 계산해도 같은 값이다', () => {
26
- assert.equal(usable(FRESH, TIP, true), true)
27
- })
28
-
29
- test('이벤트가 더 있으면 쓰지 않는다 — 그 사이의 사실이 빠진다', () => {
30
- assert.equal(usable({ ...FRESH, revision: 23730 }, TIP, true), false)
31
- })
32
-
33
- test('구조가 바뀌었으면 쓰지 않는다 — 이벤트가 안 늘어도 공장이 달라졌다', () => {
34
- /* 재프로비저닝이 정확히 이 모양이다: 부스를 넷 늘렸는데 새 이벤트는 아직 없다.
35
- 리비전만 보면 "끝" 이라 새 설비가 없는 옛 상태를 지금으로 내게 된다. */
36
- assert.equal(usable({ ...FRESH, structureRev: 1 }, TIP, true), false)
37
- })
38
-
39
- test('구조 이력이 없던 시절의 스냅샷은 쓰지 않는다 — 모르는 것을 같다고 하지 않는다', () => {
40
- const legacy = { revision: 23731, state: { locations: [] } } // structureRev 없음
41
- assert.equal(usable(legacy, TIP, true), false)
42
- })
43
-
44
- test('구조가 양쪽 다 없으면 그것은 같은 것이다 — 없는 것끼리는 어긋나지 않는다', () => {
45
- assert.equal(usable({ revision: 5, structureRev: null, state: {} }, { revision: 5, structureRev: null }, true), true)
46
- assert.equal(usable({ revision: 5, state: {} }, { revision: 5, structureRev: null }, true), true)
47
- })
48
-
49
- test('시간여행에는 쓰지 않는다 — 그 시점까지 계산해야 한다', () => {
50
- assert.equal(usable(FRESH, TIP, false), false)
51
- })
52
-
53
- test('상태가 비어 있는 스냅샷은 쓰지 않는다 — 빈 공장을 지금으로 내지 않는다', () => {
54
- assert.equal(usable({ revision: 23731, structureRev: 2, state: null }, TIP, true), false)
55
- assert.equal(usable(null, TIP, true), false)
56
- })
57
-
58
- test('이벤트가 하나도 없는 트윈도 성립한다 — 0 과 0 은 같다', () => {
59
- assert.equal(usable({ revision: 0, structureRev: null, state: { locations: [] } }, { revision: 0, structureRev: null }, true), true)
60
- })