@things-factory/headless-twin 10.1.278 → 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.
- package/package.json +21 -7
- package/dist-server/engine/attention-digest.js.map +0 -1
- package/dist-server/engine/canonical-ingest.js.map +0 -1
- package/dist-server/engine/checkpoint-fold.js.map +0 -1
- package/dist-server/engine/command-routing.js.map +0 -1
- package/dist-server/engine/declared-stimulus.js.map +0 -1
- package/dist-server/engine/energy-topology.js.map +0 -1
- package/dist-server/engine/event-time.js.map +0 -1
- package/dist-server/engine/index.js.map +0 -1
- package/dist-server/engine/ingest-dedupe.js.map +0 -1
- package/dist-server/engine/ingest-health.js.map +0 -1
- package/dist-server/engine/integration-coverage.js.map +0 -1
- package/dist-server/engine/integration-probes.js.map +0 -1
- package/dist-server/engine/integration-runner.js.map +0 -1
- package/dist-server/engine/integration-target-profile.js.map +0 -1
- package/dist-server/engine/kpi-baseline.js.map +0 -1
- package/dist-server/engine/kpi-fold.js.map +0 -1
- package/dist-server/engine/kpi-query.js.map +0 -1
- package/dist-server/engine/kpi-target.js.map +0 -1
- package/dist-server/engine/live-attentions.js.map +0 -1
- package/dist-server/engine/live-feed-registry.js.map +0 -1
- package/dist-server/engine/load-meter.js.map +0 -1
- package/dist-server/engine/local-declarations.js.map +0 -1
- package/dist-server/engine/log.js.map +0 -1
- package/dist-server/engine/loop-lag.js.map +0 -1
- package/dist-server/engine/measured-estimator.js.map +0 -1
- package/dist-server/engine/measured-yield.js.map +0 -1
- package/dist-server/engine/model-basis.js.map +0 -1
- package/dist-server/engine/model-gap.js.map +0 -1
- package/dist-server/engine/model-refusal.js.map +0 -1
- package/dist-server/engine/model-vocabulary.js.map +0 -1
- package/dist-server/engine/oee-accumulator.js.map +0 -1
- package/dist-server/engine/operation-basis.js.map +0 -1
- package/dist-server/engine/producer-guard.js.map +0 -1
- package/dist-server/engine/property-effects.js.map +0 -1
- package/dist-server/engine/read-time.js.map +0 -1
- package/dist-server/engine/restart-policy.js.map +0 -1
- package/dist-server/engine/runtime-key.js.map +0 -1
- package/dist-server/engine/spec-coverage.js.map +0 -1
- package/dist-server/engine/stage-path.js.map +0 -1
- package/dist-server/engine/state-axes.js.map +0 -1
- package/dist-server/engine/structure-diff.js.map +0 -1
- package/dist-server/engine/travel-estimator.js.map +0 -1
- package/dist-server/engine/twin-engine.js.map +0 -1
- package/dist-server/engine/twin-state-channel.js.map +0 -1
- package/dist-server/engine/warm-start.js.map +0 -1
- package/dist-server/index.js.map +0 -1
- package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +0 -1
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +0 -1
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +0 -1
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +0 -1
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +0 -1
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +0 -1
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +0 -1
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +0 -1
- package/dist-server/migrations/1786800000000-CreateTwinReferenceReconciliations.js.map +0 -1
- package/dist-server/migrations/index.js.map +0 -1
- package/dist-server/routes.js.map +0 -1
- package/dist-server/service/actuation/actuation-advisor.js.map +0 -1
- package/dist-server/service/actuation/actuation-outcome.js.map +0 -1
- package/dist-server/service/actuation/actuation-rule-resolver.js.map +0 -1
- package/dist-server/service/actuation/actuation-rule.js.map +0 -1
- package/dist-server/service/actuation/approval-gateway.js.map +0 -1
- package/dist-server/service/actuation/catch-up-effects.js.map +0 -1
- package/dist-server/service/actuation/command-dispatcher.js.map +0 -1
- package/dist-server/service/actuation/command-store.js.map +0 -1
- package/dist-server/service/actuation/dispatch-after-approval.js.map +0 -1
- package/dist-server/service/actuation/effect-match.js.map +0 -1
- package/dist-server/service/actuation/index.js.map +0 -1
- package/dist-server/service/actuation/retry-plan.js.map +0 -1
- package/dist-server/service/actuation/rule-evaluate.js.map +0 -1
- package/dist-server/service/actuation/rule-loop.js.map +0 -1
- package/dist-server/service/actuation/rule-runner.js.map +0 -1
- package/dist-server/service/actuation/rule-wiring.js.map +0 -1
- package/dist-server/service/actuation/settle-effects.js.map +0 -1
- package/dist-server/service/actuation/sweep-dispatch.js.map +0 -1
- package/dist-server/service/actuation/twin-command-resolver.js.map +0 -1
- package/dist-server/service/actuation/twin-command.js.map +0 -1
- package/dist-server/service/actuation/twin-now.js.map +0 -1
- package/dist-server/service/index.js.map +0 -1
- package/dist-server/service/reference/actuation-routing.js.map +0 -1
- package/dist-server/service/reference/actuation-target.js.map +0 -1
- package/dist-server/service/reference/actuation-verification.js.map +0 -1
- package/dist-server/service/reference/attention-lane.js.map +0 -1
- package/dist-server/service/reference/connection-portability-resolver.js.map +0 -1
- package/dist-server/service/reference/connection-portability.js.map +0 -1
- package/dist-server/service/reference/control-routing.js.map +0 -1
- package/dist-server/service/reference/discovery-result.js.map +0 -1
- package/dist-server/service/reference/fill-cadence.js.map +0 -1
- package/dist-server/service/reference/fill-dedupe.js.map +0 -1
- package/dist-server/service/reference/fill-loop.js.map +0 -1
- package/dist-server/service/reference/fill-span.js.map +0 -1
- package/dist-server/service/reference/hook-contract.js.map +0 -1
- package/dist-server/service/reference/hook-rejected.js.map +0 -1
- package/dist-server/service/reference/hook-store.js.map +0 -1
- package/dist-server/service/reference/index.js.map +0 -1
- package/dist-server/service/reference/ingest-space.js.map +0 -1
- package/dist-server/service/reference/knob-defaults.js.map +0 -1
- package/dist-server/service/reference/live-cadence.js.map +0 -1
- package/dist-server/service/reference/live-feed-lease.js.map +0 -1
- package/dist-server/service/reference/live-ingest.js.map +0 -1
- package/dist-server/service/reference/reference-adapter.js.map +0 -1
- package/dist-server/service/reference/reference-assessment.js.map +0 -1
- package/dist-server/service/reference/reference-fill-run.js.map +0 -1
- package/dist-server/service/reference/reference-fill.js.map +0 -1
- package/dist-server/service/reference/reference-hook.js.map +0 -1
- package/dist-server/service/reference/reference-link-groups.js.map +0 -1
- package/dist-server/service/reference/reference-links.js.map +0 -1
- package/dist-server/service/reference/reference-live.js.map +0 -1
- package/dist-server/service/reference/reference-master.js.map +0 -1
- package/dist-server/service/reference/reference-probe.js.map +0 -1
- package/dist-server/service/reference/reference-progress-channel.js.map +0 -1
- package/dist-server/service/reference/reference-progress-subscription.js.map +0 -1
- package/dist-server/service/reference/reference-progress.js.map +0 -1
- package/dist-server/service/reference/reference-reconciliation-query.js.map +0 -1
- package/dist-server/service/reference/reference-reconciliation-writer.js.map +0 -1
- package/dist-server/service/reference/reference-reconciliation.js.map +0 -1
- package/dist-server/service/reference/reference-registry.js.map +0 -1
- package/dist-server/service/reference/reference-resolver.js.map +0 -1
- package/dist-server/service/reference/template-registry.js.map +0 -1
- package/dist-server/service/reference/twin-reference-reconciliation.js.map +0 -1
- package/dist-server/service/reference/twin-reference.js.map +0 -1
- package/dist-server/service/twin-attention/index.js.map +0 -1
- package/dist-server/service/twin-attention/twin-attention-query.js.map +0 -1
- package/dist-server/service/twin-audit/command-audit.js.map +0 -1
- package/dist-server/service/twin-audit/index.js.map +0 -1
- package/dist-server/service/twin-audit/twin-audit-event.js.map +0 -1
- package/dist-server/service/twin-audit/twin-audit-query.js.map +0 -1
- package/dist-server/service/twin-backfill/backfill-period-facts.js.map +0 -1
- package/dist-server/service/twin-backfill/backfill-shape.js.map +0 -1
- package/dist-server/service/twin-backfill/index.js.map +0 -1
- package/dist-server/service/twin-backfill/twin-backfill-resolver.js.map +0 -1
- package/dist-server/service/twin-control/index.js.map +0 -1
- package/dist-server/service/twin-control/twin-control-mutation.js.map +0 -1
- package/dist-server/service/twin-event/index.js.map +0 -1
- package/dist-server/service/twin-event/journal-count.js.map +0 -1
- package/dist-server/service/twin-event/twin-event-keys.js.map +0 -1
- package/dist-server/service/twin-event/twin-event-type.js.map +0 -1
- package/dist-server/service/twin-event/twin-event.js.map +0 -1
- package/dist-server/service/twin-forecast/forecast-metrics.js.map +0 -1
- package/dist-server/service/twin-forecast/forecast-tuning.js.map +0 -1
- package/dist-server/service/twin-forecast/gap-analytics.js.map +0 -1
- package/dist-server/service/twin-forecast/index.js.map +0 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js.map +0 -1
- package/dist-server/service/twin-ingest-window/index.js.map +0 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +0 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +0 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +0 -1
- package/dist-server/service/twin-instance/index.js.map +0 -1
- package/dist-server/service/twin-instance/twin-instance.js.map +0 -1
- package/dist-server/service/twin-journal/event-type-split-shape.js.map +0 -1
- package/dist-server/service/twin-journal/event-type-split.js.map +0 -1
- package/dist-server/service/twin-journal/index.js.map +0 -1
- package/dist-server/service/twin-journal/journal-order.js.map +0 -1
- package/dist-server/service/twin-journal/twin-journal-query.js.map +0 -1
- package/dist-server/service/twin-lifecycle/domain-catalog.js.map +0 -1
- package/dist-server/service/twin-lifecycle/index.js.map +0 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +0 -1
- package/dist-server/service/twin-metrics/index.js.map +0 -1
- package/dist-server/service/twin-metrics/twin-metrics-query.js.map +0 -1
- package/dist-server/service/twin-model/axis-journal-evidence.js.map +0 -1
- package/dist-server/service/twin-model/choose-recipe.js.map +0 -1
- package/dist-server/service/twin-model/epcis-coverage.js.map +0 -1
- package/dist-server/service/twin-model/external-resolver.js.map +0 -1
- package/dist-server/service/twin-model/iec61850-coverage.js.map +0 -1
- package/dist-server/service/twin-model/index.js.map +0 -1
- package/dist-server/service/twin-model/isa95-coverage.js.map +0 -1
- package/dist-server/service/twin-model/item-ref.js.map +0 -1
- package/dist-server/service/twin-model/name-index.js.map +0 -1
- package/dist-server/service/twin-model/project-structure.js.map +0 -1
- package/dist-server/service/twin-model/standard-coverage.js.map +0 -1
- package/dist-server/service/twin-model/status-tally.js.map +0 -1
- package/dist-server/service/twin-model/twin-equipment.js.map +0 -1
- package/dist-server/service/twin-model/twin-lineage-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-location.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-item-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-mutation.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +0 -1
- package/dist-server/service/twin-model/twin-operation.js.map +0 -1
- package/dist-server/service/twin-readiness/index.js.map +0 -1
- package/dist-server/service/twin-readiness/twin-readiness-query.js.map +0 -1
- package/dist-server/service/twin-space/area-resolver.js.map +0 -1
- package/dist-server/service/twin-space/index.js.map +0 -1
- package/dist-server/service/twin-space/move-space.js.map +0 -1
- package/dist-server/service/twin-space/representation-role.js.map +0 -1
- package/dist-server/service/twin-space/space-integrity.js.map +0 -1
- package/dist-server/service/twin-space/twin-area.js.map +0 -1
- package/dist-server/service/twin-space/twin-space-area.js.map +0 -1
- package/dist-server/service/twin-space/twin-space-representation.js.map +0 -1
- package/dist-server/service/twin-space/twin-space-resolver.js.map +0 -1
- package/dist-server/service/twin-space/twin-space.js.map +0 -1
- package/dist-server/service/twin-state/index.js.map +0 -1
- package/dist-server/service/twin-state/twin-state-subscription.js.map +0 -1
- package/dist-server/service/twin-structure/index.js.map +0 -1
- package/dist-server/service/twin-structure/twin-structure.js.map +0 -1
- package/dist-server/service/twin-subject/event-subjects.js.map +0 -1
- package/dist-server/service/twin-subject/index.js.map +0 -1
- package/dist-server/service/twin-subject/item-resolver.js.map +0 -1
- package/dist-server/service/twin-subject/subject-query-shape.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-backfill.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-event.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-query.js.map +0 -1
- package/dist-server/service/twin-subject/twin-subject-writer.js.map +0 -1
- package/dist-server/service/twin-target/index.js.map +0 -1
- package/dist-server/service/twin-target/twin-target-resolver.js.map +0 -1
- package/dist-server/service/twin-target/twin-target.js.map +0 -1
- package/dist-shared/axis-read.js.map +0 -1
- package/dist-shared/entity-delta.js.map +0 -1
- package/dist-shared/kpi-broadcast.js.map +0 -1
- package/dist-shared/touched-items.js.map +0 -1
- package/dist-shared/twin-level.js.map +0 -1
- package/server/engine/attention-digest.ts +0 -102
- package/server/engine/canonical-ingest.ts +0 -511
- package/server/engine/checkpoint-fold.ts +0 -12
- package/server/engine/command-routing.ts +0 -67
- package/server/engine/declared-stimulus.ts +0 -66
- package/server/engine/energy-topology.ts +0 -189
- package/server/engine/event-time.ts +0 -96
- package/server/engine/index.ts +0 -51
- package/server/engine/ingest-dedupe.ts +0 -24
- package/server/engine/ingest-health.ts +0 -24
- package/server/engine/integration-coverage.ts +0 -147
- package/server/engine/integration-probes.ts +0 -144
- package/server/engine/integration-runner.ts +0 -95
- package/server/engine/integration-target-profile.ts +0 -103
- package/server/engine/kpi-baseline.ts +0 -202
- package/server/engine/kpi-fold.ts +0 -1516
- package/server/engine/kpi-query.ts +0 -1210
- package/server/engine/kpi-target.ts +0 -248
- package/server/engine/live-attentions.ts +0 -30
- package/server/engine/live-feed-registry.ts +0 -59
- package/server/engine/load-meter.ts +0 -393
- package/server/engine/local-declarations.ts +0 -779
- package/server/engine/log.ts +0 -72
- package/server/engine/loop-lag.ts +0 -120
- package/server/engine/measured-estimator.ts +0 -91
- package/server/engine/measured-yield.ts +0 -89
- package/server/engine/model-basis.ts +0 -162
- package/server/engine/model-gap.ts +0 -168
- package/server/engine/model-refusal.ts +0 -31
- package/server/engine/model-vocabulary.ts +0 -82
- package/server/engine/oee-accumulator.ts +0 -195
- package/server/engine/operation-basis.ts +0 -131
- package/server/engine/producer-guard.ts +0 -64
- package/server/engine/property-effects.ts +0 -216
- package/server/engine/read-time.ts +0 -77
- package/server/engine/restart-policy.ts +0 -55
- package/server/engine/runtime-key.ts +0 -58
- package/server/engine/spec-coverage.ts +0 -105
- package/server/engine/stage-path.ts +0 -172
- package/server/engine/state-axes.ts +0 -60
- package/server/engine/structure-diff.ts +0 -88
- package/server/engine/travel-estimator.ts +0 -138
- package/server/engine/twin-engine.ts +0 -4979
- package/server/engine/twin-state-channel.ts +0 -39
- package/server/engine/warm-start.ts +0 -265
- package/server/index.ts +0 -90
- package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +0 -43
- package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +0 -54
- package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +0 -53
- package/server/migrations/1786300000000-IndexEventTypeByTime.ts +0 -48
- package/server/migrations/1786400000000-IndexEventCreatedAt.ts +0 -38
- package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +0 -93
- package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +0 -66
- package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +0 -82
- package/server/migrations/1786800000000-CreateTwinReferenceReconciliations.ts +0 -39
- package/server/migrations/index.ts +0 -25
- package/server/routes.ts +0 -75
- package/server/service/actuation/actuation-advisor.ts +0 -131
- package/server/service/actuation/actuation-outcome.ts +0 -97
- package/server/service/actuation/actuation-rule-resolver.ts +0 -147
- package/server/service/actuation/actuation-rule.ts +0 -139
- package/server/service/actuation/approval-gateway.ts +0 -44
- package/server/service/actuation/catch-up-effects.ts +0 -152
- package/server/service/actuation/command-dispatcher.ts +0 -474
- package/server/service/actuation/command-store.ts +0 -236
- package/server/service/actuation/dispatch-after-approval.ts +0 -71
- package/server/service/actuation/effect-match.ts +0 -124
- package/server/service/actuation/index.ts +0 -27
- package/server/service/actuation/retry-plan.ts +0 -145
- package/server/service/actuation/rule-evaluate.ts +0 -352
- package/server/service/actuation/rule-loop.ts +0 -160
- package/server/service/actuation/rule-runner.ts +0 -216
- package/server/service/actuation/rule-wiring.ts +0 -84
- package/server/service/actuation/settle-effects.ts +0 -115
- package/server/service/actuation/sweep-dispatch.ts +0 -179
- package/server/service/actuation/twin-command-resolver.ts +0 -387
- package/server/service/actuation/twin-command.ts +0 -232
- package/server/service/actuation/twin-now.ts +0 -97
- package/server/service/index.ts +0 -100
- package/server/service/reference/actuation-routing.ts +0 -192
- package/server/service/reference/actuation-target.ts +0 -163
- package/server/service/reference/actuation-verification.ts +0 -85
- package/server/service/reference/attention-lane.ts +0 -21
- package/server/service/reference/connection-portability-resolver.ts +0 -171
- package/server/service/reference/connection-portability.ts +0 -329
- package/server/service/reference/control-routing.ts +0 -62
- package/server/service/reference/discovery-result.ts +0 -95
- package/server/service/reference/fill-cadence.ts +0 -29
- package/server/service/reference/fill-dedupe.ts +0 -66
- package/server/service/reference/fill-loop.ts +0 -153
- package/server/service/reference/fill-span.ts +0 -31
- package/server/service/reference/hook-contract.ts +0 -364
- package/server/service/reference/hook-rejected.ts +0 -53
- package/server/service/reference/hook-store.ts +0 -28
- package/server/service/reference/index.ts +0 -18
- package/server/service/reference/ingest-space.ts +0 -104
- package/server/service/reference/knob-defaults.ts +0 -59
- package/server/service/reference/live-cadence.ts +0 -129
- package/server/service/reference/live-feed-lease.ts +0 -56
- package/server/service/reference/live-ingest.ts +0 -94
- package/server/service/reference/reference-adapter.ts +0 -985
- package/server/service/reference/reference-assessment.ts +0 -250
- package/server/service/reference/reference-fill-run.ts +0 -179
- package/server/service/reference/reference-fill.ts +0 -223
- package/server/service/reference/reference-hook.ts +0 -479
- package/server/service/reference/reference-link-groups.ts +0 -21
- package/server/service/reference/reference-links.ts +0 -77
- package/server/service/reference/reference-live.ts +0 -420
- package/server/service/reference/reference-master.ts +0 -999
- package/server/service/reference/reference-probe.ts +0 -264
- package/server/service/reference/reference-progress-channel.ts +0 -26
- package/server/service/reference/reference-progress-subscription.ts +0 -78
- package/server/service/reference/reference-progress.ts +0 -95
- package/server/service/reference/reference-reconciliation-query.ts +0 -28
- package/server/service/reference/reference-reconciliation-writer.ts +0 -38
- package/server/service/reference/reference-reconciliation.ts +0 -55
- package/server/service/reference/reference-registry.ts +0 -17
- package/server/service/reference/reference-resolver.ts +0 -969
- package/server/service/reference/template-registry.ts +0 -85
- package/server/service/reference/twin-reference-reconciliation.ts +0 -27
- package/server/service/reference/twin-reference.ts +0 -190
- package/server/service/twin-attention/index.ts +0 -3
- package/server/service/twin-attention/twin-attention-query.ts +0 -70
- package/server/service/twin-audit/command-audit.ts +0 -114
- package/server/service/twin-audit/index.ts +0 -5
- package/server/service/twin-audit/twin-audit-event.ts +0 -158
- package/server/service/twin-audit/twin-audit-query.ts +0 -72
- package/server/service/twin-backfill/backfill-period-facts.ts +0 -168
- package/server/service/twin-backfill/backfill-shape.ts +0 -86
- package/server/service/twin-backfill/index.ts +0 -3
- package/server/service/twin-backfill/twin-backfill-resolver.ts +0 -35
- package/server/service/twin-control/index.ts +0 -3
- package/server/service/twin-control/twin-control-mutation.ts +0 -150
- package/server/service/twin-event/index.ts +0 -3
- package/server/service/twin-event/journal-count.ts +0 -53
- package/server/service/twin-event/twin-event-keys.ts +0 -215
- package/server/service/twin-event/twin-event-type.ts +0 -68
- package/server/service/twin-event/twin-event.ts +0 -250
- package/server/service/twin-forecast/forecast-metrics.ts +0 -106
- package/server/service/twin-forecast/forecast-tuning.ts +0 -40
- package/server/service/twin-forecast/gap-analytics.ts +0 -139
- package/server/service/twin-forecast/index.ts +0 -3
- package/server/service/twin-forecast/twin-forecast-query.ts +0 -486
- package/server/service/twin-ingest-window/index.ts +0 -7
- package/server/service/twin-ingest-window/twin-ingest-window-query.ts +0 -125
- package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +0 -57
- package/server/service/twin-ingest-window/twin-ingest-window.ts +0 -113
- package/server/service/twin-instance/index.ts +0 -3
- package/server/service/twin-instance/twin-instance.ts +0 -199
- package/server/service/twin-journal/event-type-split-shape.ts +0 -112
- package/server/service/twin-journal/event-type-split.ts +0 -144
- package/server/service/twin-journal/index.ts +0 -3
- package/server/service/twin-journal/journal-order.ts +0 -20
- package/server/service/twin-journal/twin-journal-query.ts +0 -615
- package/server/service/twin-lifecycle/domain-catalog.ts +0 -51
- package/server/service/twin-lifecycle/index.ts +0 -3
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +0 -285
- package/server/service/twin-metrics/index.ts +0 -3
- package/server/service/twin-metrics/twin-metrics-query.ts +0 -172
- package/server/service/twin-model/axis-journal-evidence.ts +0 -57
- package/server/service/twin-model/choose-recipe.ts +0 -31
- package/server/service/twin-model/epcis-coverage.ts +0 -251
- package/server/service/twin-model/external-resolver.ts +0 -173
- package/server/service/twin-model/iec61850-coverage.ts +0 -111
- package/server/service/twin-model/index.ts +0 -25
- package/server/service/twin-model/isa95-coverage.ts +0 -320
- package/server/service/twin-model/item-ref.ts +0 -80
- package/server/service/twin-model/name-index.ts +0 -94
- package/server/service/twin-model/project-structure.ts +0 -213
- package/server/service/twin-model/standard-coverage.ts +0 -35
- package/server/service/twin-model/status-tally.ts +0 -37
- package/server/service/twin-model/twin-equipment.ts +0 -191
- package/server/service/twin-model/twin-lineage-query.ts +0 -327
- package/server/service/twin-model/twin-location.ts +0 -147
- package/server/service/twin-model/twin-model-item-query.ts +0 -1029
- package/server/service/twin-model/twin-model-mutation.ts +0 -503
- package/server/service/twin-model/twin-model-query.ts +0 -792
- package/server/service/twin-model/twin-model-tree-query.ts +0 -211
- package/server/service/twin-model/twin-operation.ts +0 -157
- package/server/service/twin-readiness/index.ts +0 -3
- package/server/service/twin-readiness/twin-readiness-query.ts +0 -96
- package/server/service/twin-space/area-resolver.ts +0 -75
- package/server/service/twin-space/index.ts +0 -8
- package/server/service/twin-space/move-space.ts +0 -262
- package/server/service/twin-space/representation-role.ts +0 -15
- package/server/service/twin-space/space-integrity.ts +0 -293
- package/server/service/twin-space/twin-area.ts +0 -63
- package/server/service/twin-space/twin-space-area.ts +0 -66
- package/server/service/twin-space/twin-space-representation.ts +0 -99
- package/server/service/twin-space/twin-space-resolver.ts +0 -582
- package/server/service/twin-space/twin-space.ts +0 -148
- package/server/service/twin-state/index.ts +0 -3
- package/server/service/twin-state/twin-state-subscription.ts +0 -62
- package/server/service/twin-structure/index.ts +0 -3
- package/server/service/twin-structure/twin-structure.ts +0 -96
- package/server/service/twin-subject/event-subjects.ts +0 -162
- package/server/service/twin-subject/index.ts +0 -10
- package/server/service/twin-subject/item-resolver.ts +0 -92
- package/server/service/twin-subject/subject-query-shape.ts +0 -84
- package/server/service/twin-subject/twin-subject-backfill.ts +0 -196
- package/server/service/twin-subject/twin-subject-event.ts +0 -101
- package/server/service/twin-subject/twin-subject-fast-path.ts +0 -346
- package/server/service/twin-subject/twin-subject-query.ts +0 -210
- package/server/service/twin-subject/twin-subject-writer.ts +0 -189
- package/server/service/twin-target/index.ts +0 -5
- package/server/service/twin-target/twin-target-resolver.ts +0 -142
- package/server/service/twin-target/twin-target.ts +0 -97
- package/server/types/global.d.ts +0 -22
- package/shared/axis-read.ts +0 -28
- package/shared/entity-delta.ts +0 -335
- package/shared/kpi-broadcast.ts +0 -13
- package/shared/touched-items.ts +0 -73
- package/shared/twin-level.ts +0 -48
- package/test/ack-shape-alignment.test.ts +0 -97
- package/test/actuation-advisor.test.ts +0 -55
- package/test/actuation-approval-door.test.ts +0 -411
- package/test/actuation-dispatch.test.ts +0 -209
- package/test/actuation-effect.test.ts +0 -162
- package/test/actuation-outcome.test.ts +0 -152
- package/test/actuation-rule-runner.test.ts +0 -281
- package/test/actuation-rule.test.ts +0 -266
- package/test/actuation-seam.test.ts +0 -255
- package/test/actuation-settle.test.ts +0 -164
- package/test/actuation-target.test.ts +0 -145
- package/test/actuation-verification-state.test.ts +0 -139
- package/test/adopt-structure-live.test.ts +0 -133
- package/test/aggregate-not-findone.test.ts +0 -112
- package/test/area-resolver-db.test.ts +0 -110
- package/test/attention-digest.test.ts +0 -161
- package/test/axis-declaration-passthrough-db.test.ts +0 -152
- package/test/axis-journal-evidence.test.ts +0 -71
- package/test/axis-read.test.ts +0 -188
- package/test/backfill-shape.test.ts +0 -89
- package/test/boot-resume.test.ts +0 -287
- package/test/broadcast-cost-baseline.test.ts +0 -201
- package/test/broadcast-period.test.ts +0 -58
- package/test/broadcast-queue-overflow.test.ts +0 -244
- package/test/canonical-ingest-vocabularies.test.ts +0 -451
- package/test/canonical-quantity-door.test.ts +0 -61
- package/test/capability-mapping.test.ts +0 -89
- package/test/checkpoint-refuses-empty.test.ts +0 -103
- package/test/choose-recipe.test.ts +0 -117
- package/test/column-type-portability.test.ts +0 -122
- package/test/command-routing.test.ts +0 -61
- package/test/command-store-writes-columns.test.ts +0 -126
- package/test/connection-portability-doors.test.ts +0 -87
- package/test/connector-capability-declaration.test.ts +0 -195
- package/test/contract-layer-guard.test.ts +0 -48
- package/test/control-capability.test.ts +0 -98
- package/test/cursor-stall-not-read-failure.test.ts +0 -126
- package/test/declaration-reaches-model.test.ts +0 -226
- package/test/declared-location-types.test.ts +0 -89
- package/test/declared-stimulus.test.ts +0 -88
- package/test/dedupe-transformation.test.ts +0 -112
- package/test/discovery-result.test.ts +0 -75
- package/test/dispatch-after-approval-source.test.ts +0 -81
- package/test/duration-estimators.test.ts +0 -144
- package/test/energy-topology.test.ts +0 -113
- package/test/entity-delta.test.ts +0 -352
- package/test/equipment-identity-reaches.test.ts +0 -57
- package/test/event-subjects.test.ts +0 -148
- package/test/event-time-column.test.ts +0 -67
- package/test/event-type-split.test.ts +0 -178
- package/test/external-resolver.test.ts +0 -177
- package/test/fact-scope-wiring.test.ts +0 -96
- package/test/fill-dedupe.test.ts +0 -59
- package/test/fill-loop.test.ts +0 -35
- package/test/first-envelope.test.ts +0 -153
- package/test/fold-gap-speaks.test.ts +0 -53
- package/test/fold-shift-dst.test.ts +0 -110
- package/test/forecast-metrics.test.ts +0 -157
- package/test/forecast-tuning.test.ts +0 -42
- package/test/gap-analytics.test.ts +0 -113
- package/test/generated-not-counted.test.ts +0 -99
- package/test/guard-roots.ts +0 -76
- package/test/home-in-area.test.ts +0 -90
- package/test/hook-address.test.ts +0 -28
- package/test/hook-rejected-shape.test.ts +0 -86
- package/test/hook-response-sum.test.ts +0 -193
- package/test/hook-sequence.test.ts +0 -333
- package/test/ingest-bench.test.ts +0 -70
- package/test/ingest-dedupe.test.ts +0 -56
- package/test/ingest-expected-quiet.test.ts +0 -111
- package/test/ingest-health-engine.test.ts +0 -248
- package/test/ingest-health-wiring.test.ts +0 -120
- package/test/ingest-health.test.ts +0 -306
- package/test/ingest-history.test.ts +0 -247
- package/test/ingest-idempotent.test.ts +0 -211
- package/test/ingest-reconcile-four-ways.test.ts +0 -97
- package/test/ingest-rules-header.test.ts +0 -100
- package/test/ingest-running-guard.test.ts +0 -136
- package/test/ingest-space.test.ts +0 -78
- package/test/ingest-window-rolls-unobserved.test.ts +0 -72
- package/test/ingest-wiring-guard.test.ts +0 -197
- package/test/instance-cache-lifecycle.test.ts +0 -110
- package/test/intake-mapping-parity.test.ts +0 -175
- package/test/integration-probes.test.ts +0 -103
- package/test/integration-runner.test.ts +0 -95
- package/test/item-ref.test.ts +0 -78
- package/test/journal-order-axis.test.ts +0 -80
- package/test/journal-read-discipline.test.ts +0 -186
- package/test/journal-retention.test.ts +0 -275
- package/test/journal-sort-axis.test.ts +0 -142
- package/test/journal-write-door.test.ts +0 -110
- package/test/journal-write-trend.test.ts +0 -115
- package/test/kernel-kind-guard.test.ts +0 -98
- package/test/knob-defaults.test.ts +0 -72
- package/test/kpi-baseline-db.test.ts +0 -216
- package/test/kpi-baseline.test.ts +0 -196
- package/test/kpi-fold.test.ts +0 -1456
- package/test/kpi-query-bench.test.ts +0 -130
- package/test/lens-own-places.test.ts +0 -50
- package/test/lineage-survives-restart.test.ts +0 -234
- package/test/live-cadence.test.ts +0 -170
- package/test/live-cursor-wiring.test.ts +0 -87
- package/test/live-feed-lease.test.ts +0 -63
- package/test/live-feed-registry.test.ts +0 -75
- package/test/live-kernel-facts.test.ts +0 -161
- package/test/live-mirror-parity.test.ts +0 -286
- package/test/load-meter.test.ts +0 -328
- package/test/local-declarations.test.ts +0 -662
- package/test/log-stamp.test.ts +0 -59
- package/test/loop-lag.test.ts +0 -82
- package/test/master-to-twin.test.ts +0 -279
- package/test/measured-yield.test.ts +0 -90
- package/test/merge-streams.test.ts +0 -70
- package/test/mirror-resumes-from-checkpoint.test.ts +0 -192
- package/test/model-basis.test.ts +0 -141
- package/test/model-gap.test.ts +0 -153
- package/test/model-refusal.test.ts +0 -75
- package/test/model-vocabulary.test.ts +0 -114
- package/test/move-space.test.ts +0 -149
- package/test/mutation-gate.test.ts +0 -122
- package/test/oee-accumulator.test.ts +0 -204
- package/test/oee-site-calendar.test.ts +0 -146
- package/test/open-doors.test.ts +0 -197
- package/test/operation-basis.test.ts +0 -127
- package/test/operational-vocabulary.test.ts +0 -108
- package/test/operations-capability-db.test.ts +0 -165
- package/test/order-and-transaction-split.test.ts +0 -107
- package/test/order-fold-host.test.ts +0 -112
- package/test/producer-guard.test.ts +0 -66
- package/test/project-structure-db.test.ts +0 -226
- package/test/projection-reaches-screen.test.ts +0 -277
- package/test/projection-reads-declared.test.ts +0 -109
- package/test/property-effects.test.ts +0 -128
- package/test/provenance-promotion.test.ts +0 -99
- package/test/read-failure-ledger.test.ts +0 -106
- package/test/read-failure-visible.test.ts +0 -145
- package/test/read-time.test.ts +0 -118
- package/test/reference-fill.test.ts +0 -235
- package/test/reference-grounding.test.ts +0 -70
- package/test/reference-hook.test.ts +0 -177
- package/test/reference-links.test.ts +0 -56
- package/test/reference-reconciliation.test.ts +0 -39
- package/test/registry-key-guard.test.ts +0 -80
- package/test/rejection-carries-event-id.test.ts +0 -101
- package/test/rename-twin.test.ts +0 -89
- package/test/resolve-ts-siblings.mjs +0 -52
- package/test/restart-policy.test.ts +0 -111
- package/test/resync-origin-site.test.ts +0 -83
- package/test/retry-plan.test.ts +0 -139
- package/test/revision-axis.test.ts +0 -110
- package/test/runtime-key.test.ts +0 -66
- package/test/save-intake-collision.test.ts +0 -91
- package/test/scale-twin-bench.test.ts +0 -103
- package/test/secrets-at-rest.test.ts +0 -135
- package/test/snapshot-freshness.test.ts +0 -60
- package/test/source-outcome-audit.test.ts +0 -104
- package/test/space-integrity.test.ts +0 -223
- package/test/space-representation.test.ts +0 -66
- package/test/space-scope-includes-stopped.test.ts +0 -55
- package/test/spec-coverage.test.ts +0 -113
- package/test/stage-path.test.ts +0 -95
- package/test/standard-coverage.test.ts +0 -148
- package/test/state-axes.test.ts +0 -74
- package/test/status-tally.test.ts +0 -55
- package/test/streamline-e2e.test.ts +0 -76
- package/test/structure-revision-db.test.ts +0 -315
- package/test/subject-fast-path.test.ts +0 -148
- package/test/subject-read-model.test.ts +0 -175
- package/test/sweep-dispatch.test.ts +0 -191
- package/test/tenant-registry-db.test.ts +0 -149
- package/test/time-range.test.ts +0 -152
- package/test/touched-items.test.ts +0 -61
- package/test/twin-audit.test.ts +0 -83
- package/test/twin-event-keys.test.ts +0 -193
- package/test/twin-model-item-db.test.ts +0 -319
- package/test/twin-model-parent-relation-db.test.ts +0 -125
- package/test/twin-model-tree-db.test.ts +0 -209
- package/test/twin-origin-resync.test.ts +0 -133
- package/test/twin-state-channel.test.ts +0 -111
- package/test/vocabulary-guard.test.ts +0 -43
- package/test/warm-start-seam.test.ts +0 -162
- package/test/warm-start.test.ts +0 -297
- package/test/withheld-door.test.ts +0 -95
- package/test/yield-loop.test.ts +0 -199
- package/tsconfig.json +0 -15
- package/tsconfig.shared.json +0 -23
- package/tsconfig.shared.tsbuildinfo +0 -1
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* 트윈 템플릿(아키타입) 레지스트리 — 파라미터화된 합성 레퍼런스 마스터 빌더.
|
|
3
|
-
* 레퍼런스(reference-registry)가 "고정 마스터"라면, 템플릿은 "노브로 파라미터화된 마스터 빌더".
|
|
4
|
-
* 둘 다 같은 인제스트 경로(ingestMaster)로 흐른다 — 원천이 고정이냐 합성이냐만 다르다(board-authoring §10).
|
|
5
|
-
* 앱(operato-twin)이 bootstrap 에서 자기 아키타입을 registerTemplate 한다. 표현(map/image/model) 무관.
|
|
6
|
-
*/
|
|
7
|
-
import type { DomainSystem } from '@operato/ops-contract'
|
|
8
|
-
|
|
9
|
-
import type { ReferenceMaster } from './reference-master.js'
|
|
10
|
-
|
|
11
|
-
/** 사용자 노출 파라미터(노브) 정의 — 클라이언트가 이 스키마로 폼을 렌더한다. */
|
|
12
|
-
export interface KnobDef {
|
|
13
|
-
key: string
|
|
14
|
-
/** 'geo' = 위경도 지점(지도에서 클릭 선택). 값은 { lat, lon }. 사용자가 좌표를 몰라도 지도로 지정. */
|
|
15
|
-
label: string
|
|
16
|
-
/**
|
|
17
|
-
* 'siteEquipment' = **이 현장에 이미 있는 설비들**(`{id, kind}`). 값이 비어 있으면 만들 때 한 번
|
|
18
|
-
* 해석해서 채우고, 채운 결과를 노브 값으로 **남긴다**(`origin.params`). 그래야 나중에 다시 지어도
|
|
19
|
-
* 같은 트윈이 나온다 — 그때그때 현장을 다시 읽으면 사이에 설비가 늘고 준 만큼 다른 트윈이 된다.
|
|
20
|
-
*
|
|
21
|
-
* 종류를 함께 싣는 이유: 무엇을 받아들일지는 **템플릿이 종류로 판단**한다(이름으로 짐작하지 않는다).
|
|
22
|
-
*/
|
|
23
|
-
type: 'number' | 'text' | 'select' | 'geo' | 'siteEquipment'
|
|
24
|
-
default: any
|
|
25
|
-
min?: number
|
|
26
|
-
max?: number
|
|
27
|
-
options?: { value: string; label: string }[]
|
|
28
|
-
help?: string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* 템플릿 상세(설명 페이지용, 선택) — "이 템플릿이 무엇을 모델링하나"를 구조적으로 보여줘 확신을 준다.
|
|
33
|
-
* 순수 표시용 데이터(빌드 로직과 무관). 클라이언트가 이 스키마로 상세 뷰를 렌더한다.
|
|
34
|
-
*/
|
|
35
|
-
export interface TemplateDetail {
|
|
36
|
-
/** 한 줄 요약(누구를 위한/무엇). */
|
|
37
|
-
summary?: string
|
|
38
|
-
standards?: string[]
|
|
39
|
-
/** 밸류체인 국면(반입·보관·변환·반출 등). */
|
|
40
|
-
phases?: { key: string; label: string; system?: string; note?: string }[]
|
|
41
|
-
/** 공정 라우트(오퍼레이션 시퀀스). */
|
|
42
|
-
route?: { op: string; label?: string; resource?: string; intent?: string; bizStep?: string }[]
|
|
43
|
-
locationTypes?: { key: string; label?: string; standardClass?: string; capabilities?: string[] }[]
|
|
44
|
-
resourceTypes?: { key: string; label?: string; standardClass?: string; capabilities?: string[] }[]
|
|
45
|
-
/** BOM/레시피 요약. */
|
|
46
|
-
recipe?: {
|
|
47
|
-
inputs: { material: string; qty: number; key?: string }[]
|
|
48
|
-
outputs: { material: string; qty: number; key?: string }[]
|
|
49
|
-
/** 완성 라우트 이름(공정 라우트 참조). */
|
|
50
|
-
route?: string
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* 표준 정합 매핑 — 개념이 **어느 표준의 무엇에 대응하나.**
|
|
54
|
-
*
|
|
55
|
-
* 표준 칸이 EPCIS·ISA-95 둘로 굳어 있었다. 에너지 템플릿은 그 둘이 앵커가 아니라 적을 자리가 없었다 —
|
|
56
|
-
* 커널의 `StandardClass` 도 같은 이유로 열었다(`iso50001`·`iec61850`). 대응할 이름이 없으면 **비운다**.
|
|
57
|
-
*/
|
|
58
|
-
standardsMap?: { concept: string; epcis?: string; isa95?: string; iso50001?: string; iec61850?: string }[]
|
|
59
|
-
/** "이 템플릿이 맞나?" 판단 도움 항목. */
|
|
60
|
-
fits?: string[]
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface TwinTemplate {
|
|
64
|
-
id: string
|
|
65
|
-
label: string
|
|
66
|
-
/** 커널 카탈로그가 정본 — 종류가 늘면 여기 손댈 것이 없다(`DomainSystem`). */
|
|
67
|
-
system: DomainSystem
|
|
68
|
-
description?: string
|
|
69
|
-
/** 상세 설명(선택) — 설명 페이지/패널이 렌더. */
|
|
70
|
-
detail?: TemplateDetail
|
|
71
|
-
knobs: KnobDef[]
|
|
72
|
-
/** 노브 값 → 합성 마스터(+옵션 시나리오). scenario 는 runtime.scenario.load 로 전달되는 불투명 값. */
|
|
73
|
-
build(params: Record<string, any>): { master: ReferenceMaster; scenario?: any }
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const templates = new Map<string, TwinTemplate>()
|
|
77
|
-
export function registerTemplate(tpl: TwinTemplate): void {
|
|
78
|
-
templates.set(tpl.id, tpl)
|
|
79
|
-
}
|
|
80
|
-
export function listTemplates(): TwinTemplate[] {
|
|
81
|
-
return [...templates.values()]
|
|
82
|
-
}
|
|
83
|
-
export function getTemplate(id: string): TwinTemplate | undefined {
|
|
84
|
-
return templates.get(id)
|
|
85
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'
|
|
2
|
-
import { Field, ID, Int, ObjectType } from 'type-graphql'
|
|
3
|
-
import { Domain } from '@things-factory/shell'
|
|
4
|
-
|
|
5
|
-
/* 한 연결·Twin·단위의 최신 번호 대사 상태. 과거 추이는 ingest window가, 현재 조치 판단은 이 표가 답한다. */
|
|
6
|
-
@Entity()
|
|
7
|
-
@Index('uq_twin_reference_reconciliation_0', (e: TwinReferenceReconciliation) => [e.domain, e.instanceId, e.scope], { unique: true })
|
|
8
|
-
@Index('ix_twin_reference_reconciliation_0', (e: TwinReferenceReconciliation) => [e.domain, e.instanceId, e.checkedAt], { unique: false })
|
|
9
|
-
@ObjectType({ description: 'Latest durable sequence reconciliation for one connected source scope. It reports only what numbered source ranges can prove; it never substitutes replay-prone ingest-window counts for source facts.' })
|
|
10
|
-
export class TwinReferenceReconciliation {
|
|
11
|
-
@PrimaryGeneratedColumn('uuid') @Field(type => ID) readonly id: string
|
|
12
|
-
@ManyToOne(type => Domain) @Field(type => Domain, { nullable: true }) domain?: Domain
|
|
13
|
-
@RelationId((e: TwinReferenceReconciliation) => e.domain) domainId?: string
|
|
14
|
-
@Column() @Field() instanceId: string
|
|
15
|
-
@Column() @Field() scope: string
|
|
16
|
-
@Column() @Field() status: 'aligned' | 'gap' | 'unknown'
|
|
17
|
-
@Column({ type: 'int', nullable: true }) @Field(type => Int, { nullable: true }) sourceFirst?: number
|
|
18
|
-
@Column({ type: 'int', nullable: true }) @Field(type => Int, { nullable: true }) sourceLast?: number
|
|
19
|
-
@Column({ type: 'int', nullable: true }) @Field(type => Int, { nullable: true }) cursorSeq?: number
|
|
20
|
-
@Column({ type: 'int', nullable: true }) @Field(type => Int, { nullable: true }) firstSeqSeen?: number
|
|
21
|
-
@Column({ type: 'int', nullable: true }) @Field(type => Int, { nullable: true }) headMissing?: number
|
|
22
|
-
@Column({ type: 'int', nullable: true }) @Field(type => Int, { nullable: true }) behind?: number
|
|
23
|
-
@Column({ nullable: true }) @Field({ nullable: true }) reason?: string
|
|
24
|
-
@Column() @Field() checkedAt: Date
|
|
25
|
-
@CreateDateColumn() createdAt?: Date
|
|
26
|
-
@UpdateDateColumn() updatedAt?: Date
|
|
27
|
-
}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
|
2
|
-
import { ObjectType, Field, ID, Int } from 'type-graphql'
|
|
3
|
-
|
|
4
|
-
import type { RefusalCode, RefusalParams } from '@operato/ops-contract'
|
|
5
|
-
|
|
6
|
-
import { Domain, ScalarObject, encryptedJsonColumn } from '@things-factory/shell'
|
|
7
|
-
|
|
8
|
-
/** 조치 검증 상태 — 「아직 안 해 봤다」는 실패가 아니라 그 자체로 하나의 사실이다. */
|
|
9
|
-
export type ActuationState = 'unverified' | 'verified' | 'failed'
|
|
10
|
-
|
|
11
|
-
/** 마지막 거절 — 언어 중립 코드와 그 값들. 사람 문장은 담지 않는다. */
|
|
12
|
-
export interface ActuationFailure {
|
|
13
|
-
code: RefusalCode
|
|
14
|
-
/** 거절된 시각 (ISO 8601). */
|
|
15
|
-
at: string
|
|
16
|
-
params?: RefusalParams
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/*
|
|
20
|
-
* TwinReference — 테넌트 스코프의 외부 소스 시스템 연결(실 또는 가상). 트윈 인스턴스가 인제스트되는 원천(Face2, ADR-0018).
|
|
21
|
-
* 전역 인메모리 레퍼런스 레지스트리를 대체하는 영속·도메인별·어댑터 기반 엔티티.
|
|
22
|
-
* inbound 전용(구조·상태). 아웃바운드 액추에이션은 command-routing(ActuationAdapter) 소유.
|
|
23
|
-
* mappingSpec/scopeSpec 는 simple-json(멀티DB 이식 — postgres/mysql/sqlite/mssql/oracle 공통).
|
|
24
|
-
* connectionConfig 는 자격 증명을 담으므로 암호화되는 텍스트 칸이다(칸 주석 참조).
|
|
25
|
-
* 설계 SoT: operato-twin/design/plans/reference-management.md.
|
|
26
|
-
* (CLAUDE.md: 모든 @ObjectType/@Field 는 영문 description 필수.)
|
|
27
|
-
*/
|
|
28
|
-
@Entity()
|
|
29
|
-
@Index('ix_twin_reference_0', (e: TwinReference) => [e.domain, e.source], { unique: true })
|
|
30
|
-
@ObjectType({ description: 'A tenant-scoped connection to an external source system — the origin for ingesting twin instances (Face2).' })
|
|
31
|
-
export class TwinReference {
|
|
32
|
-
@PrimaryGeneratedColumn('uuid')
|
|
33
|
-
@Field(type => ID, { description: 'Unique identifier of the reference record.' })
|
|
34
|
-
readonly id: string
|
|
35
|
-
|
|
36
|
-
@ManyToOne(type => Domain)
|
|
37
|
-
@Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })
|
|
38
|
-
domain?: Domain
|
|
39
|
-
|
|
40
|
-
@RelationId((e: TwinReference) => e.domain)
|
|
41
|
-
domainId?: string
|
|
42
|
-
|
|
43
|
-
@Column()
|
|
44
|
-
@Field({ description: 'Reference source id (unique within a domain).' })
|
|
45
|
-
source: string
|
|
46
|
-
|
|
47
|
-
@Column({ nullable: true })
|
|
48
|
-
@Field({ nullable: true, description: 'Domain kernel system: wms | yms | mes.' })
|
|
49
|
-
system?: string
|
|
50
|
-
|
|
51
|
-
@Column({ nullable: true })
|
|
52
|
-
@Field({ nullable: true, description: 'Human-readable site/system name.' })
|
|
53
|
-
siteName?: string
|
|
54
|
-
|
|
55
|
-
@Column({ nullable: true })
|
|
56
|
-
@Field({ nullable: true, description: 'Optional description.' })
|
|
57
|
-
description?: string
|
|
58
|
-
|
|
59
|
-
@Column()
|
|
60
|
-
@Field({ description: "Adapter type registry key (e.g. 'virtual' | 'rest' | 'db' | 'epcis')." })
|
|
61
|
-
adapterType: string
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 이 연결에 필요한 값 — **자격 증명이 여기 들어온다. 그래서 저장될 때 암호화된다.**
|
|
65
|
-
*
|
|
66
|
-
* ── 왜 표에 두나 (2026-09-09) ─────────────────────────────────────────────
|
|
67
|
-
* 비밀값은 환경에 두고 이름으로 고르는 것이 원칙이다(§`webhookSecretCandidates`). 그 원칙은
|
|
68
|
-
* **설치본마다 하나인 키**에 맞는다 — 배포할 때 넣으면 된다.
|
|
69
|
-
*
|
|
70
|
-
* 트윈의 연결은 그 모양이 아니다. **사람이 화면에서 연결을 만든다.** 새 공장을 붙이려고 재배포할
|
|
71
|
-
* 수는 없으므로, 연결마다 다른 이 값은 표에 있어야 한다. 그 자리에서 원칙이 갈린다:
|
|
72
|
-
*
|
|
73
|
-
* 설치본마다 하나인 키 환경변수. 이름이 어느 상대 것인지 말한다
|
|
74
|
-
* 연결마다 다른 값 표. 대신 저장될 때 암호화한다
|
|
75
|
-
*
|
|
76
|
-
* ── 무엇을 지키고 무엇을 못 지키나 ────────────────────────────────────────
|
|
77
|
-
* 저장된 것을 지킨다 — DB 파일 · 백업 · 복제본. 2026-09-09 에 이 칸에서 `hookSecret` 과 접속
|
|
78
|
-
* 토큰을 명령 두 개로 읽었다.
|
|
79
|
-
*
|
|
80
|
-
* **프로세스를 돌릴 수 있는 사람에게서는 못 지킨다** — 그 사람은 키를 갖고 있다. 그리고 값이
|
|
81
|
-
* 화면으로 나가는 것도 이 칸이 막지 않는다: 내보내는 쪽이 어댑터 스키마의 `secret: true` 를 보고
|
|
82
|
-
* 가린다(§`reference-resolver` 의 상세 조회). **두 가지가 갈려 있으므로 한쪽만 하면 반쪽이다.**
|
|
83
|
-
*
|
|
84
|
-
* 기존 평문 행은 안 깨진다 — 변환기가 암호문 모양이 아닌 값을 알아보고 파싱하며 경고를 남기고,
|
|
85
|
-
* 다시 저장될 때 암호화된다.
|
|
86
|
-
*/
|
|
87
|
-
@Column({ nullable: true, ...encryptedJsonColumn() })
|
|
88
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Adapter-specific connection config (endpoint, credentials, params). Encrypted at rest; secret-declared fields are masked on the way out.' })
|
|
89
|
-
connectionConfig?: any
|
|
90
|
-
|
|
91
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
92
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Declarative legacy→canonical mapping rules (kernel face2-adapter AdapterRule[]).' })
|
|
93
|
-
mappingSpec?: any
|
|
94
|
-
|
|
95
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
96
|
-
@Field(type => ScalarObject, { nullable: true, description: '1:N fan-out scope (discovered sites). Multiple sites → N instances.' })
|
|
97
|
-
scopeSpec?: any
|
|
98
|
-
|
|
99
|
-
@Column({ nullable: true })
|
|
100
|
-
@Field({ nullable: true, description: 'Lifecycle status: draft | connected | error.' })
|
|
101
|
-
status?: string
|
|
102
|
-
|
|
103
|
-
@Column({ nullable: true })
|
|
104
|
-
@Field({ nullable: true, description: 'Last successful master sync time (ISO 8601 string; portable across DB drivers).' })
|
|
105
|
-
lastSyncedAt?: string
|
|
106
|
-
|
|
107
|
-
@Column({ nullable: true })
|
|
108
|
-
@Field({ nullable: true, description: 'Last connection/sync error message, if any.' })
|
|
109
|
-
lastError?: string
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* **조치를 이 주소로 실제로 넘겨 봤나** (ADR-0046 ②).
|
|
113
|
-
*
|
|
114
|
-
* ── 왜 세 값인가 ───────────────────────────────────────────────────────────
|
|
115
|
-
* 설정이 맞는 것과 저쪽이 받는 것은 다르다. 주소도 비밀값도 다 적혀 있는데 저쪽 프로세스가 그 값을
|
|
116
|
-
* 잃은 일이 실제로 있었다(§`actuationReadiness`). 그것은 **한 번 넘겨 봐야** 알 수 있고, 그래서
|
|
117
|
-
* 「아직 안 해 봤다」와 「해 봤고 됐다」와 「해 봤고 안 됐다」가 다른 사실이다.
|
|
118
|
-
*
|
|
119
|
-
* unverified 아직 왕복이 없다 — 실패가 아니다. 새 연결과 설정이 바뀐 연결이 여기 선다
|
|
120
|
-
* verified `actuate` 가 받아들여졌다. 그 시각이 `actuationVerifiedAt`
|
|
121
|
-
* failed 거절됐다. 사유는 `actuationFailure` 에 **코드로**
|
|
122
|
-
*
|
|
123
|
-
* `unverified` 를 `failed` 로 접지 않는다 — 안 해 본 것을 실패로 그리면 사람이 고칠 것을 찾으러
|
|
124
|
-
* 가고, 고칠 것이 없다.
|
|
125
|
-
*/
|
|
126
|
-
@Column({ nullable: true })
|
|
127
|
-
@Field({ nullable: true, description: "Whether an actuation has actually reached this peer: 'unverified' | 'verified' | 'failed'. Null means the same as unverified; a connection that has never been tried is not a failed one." })
|
|
128
|
-
actuationState?: ActuationState
|
|
129
|
-
|
|
130
|
-
@Column({ nullable: true })
|
|
131
|
-
@Field({ nullable: true, description: 'When an actuation was last accepted by the peer (ISO 8601 string; portable across DB drivers). Null while unverified.' })
|
|
132
|
-
actuationVerifiedAt?: string
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* 마지막 거절 — **코드와 값만 저장한다. 문장은 저장하지 않는다.**
|
|
136
|
-
*
|
|
137
|
-
* `lastError` 가 사람 문장을 저장해 두고 화면이 그것을 그대로 뿌렸다. 그러면 번역이 안 되고, 무엇이
|
|
138
|
-
* 몇 번 났는지 세지도 못하고, 커넥터가 문장을 고치는 날 옛 행과 새 행이 서로 다른 말을 한다.
|
|
139
|
-
* 코드는 `CommandAck.errorCode` 와 같은 낱말이다(ADR-0042 ③) — 표현층이 문장을 만든다.
|
|
140
|
-
*/
|
|
141
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
142
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Why the last actuation was refused: { code, at, params? }. Language-neutral codes only — the presentation layer builds the sentence. Null when the last attempt was accepted or none was made.' })
|
|
143
|
-
actuationFailure?: ActuationFailure
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* 마지막 동기에서 **못 옮긴 값의 수**. `null` = 세지 않았다(0 과 다르다).
|
|
147
|
-
*
|
|
148
|
-
* 세지 않은 구조 인제스트는 도크를 랙으로 바꿔 놓고도 성공이라 답하면서 아무 일도 하지 않는다. 그 사실을 사후에 물을 수
|
|
149
|
-
* 있어야 단계 판정이 「구조는 됐다」를 말할 수 있다 — 없는 동안 판정은 늘 `unmeasured` 였다.
|
|
150
|
-
* 기본값을 두지 않는다: 0 을 기본으로 깔면 「경고 없었다」와 「세지 않았다」가 같아진다.
|
|
151
|
-
*/
|
|
152
|
-
@Column({ type: 'int', nullable: true })
|
|
153
|
-
@Field(type => Int, { nullable: true, description: 'Number of values the last sync could not carry over (mapping fallbacks). Null means they were not counted at all, which is different from zero.' })
|
|
154
|
-
lastWarningCount?: number
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* **어디까지 읽었나** — 라이브 피드의 읽기 커서(§`LiveFeedContinuity`).
|
|
158
|
-
*
|
|
159
|
-
* ── 왜 저장하나 (2026-08-23 실측) ──────────────────────────────────────────
|
|
160
|
-
* 어댑터가 붙을 때마다 `Date.now() − 되돌아볼 날수` 로 창을 새로 만들고 있었다. 그래서 **재기동마다
|
|
161
|
-
* 미러의 과거가 잘렸다** — 작업 2,855 → 2,820(8시간 흐른 만큼). 미러가 아는 것이 「원본의 사실」이
|
|
162
|
-
* 아니라 「창의 함수」였고, 그 사실을 아무도 말하지 않았다.
|
|
163
|
-
*
|
|
164
|
-
* 커널이 그 갈림을 이미 적어 두었다(§`hydrateContinuity`): 「원천이 애초에 다시 말해 주지 않는 축」은
|
|
165
|
-
* 재기동 연속성으로 이어받는다. 「우리가 어디까지 읽었나」가 정확히 그 성질이므로 **어댑터의 사물함이
|
|
166
|
-
* 아니라 이 층**에 있다 — 원본이 늘 때마다 저장 기제가 늘고 그중 하나가 알리지 않고 다르게 동작하지 않게.
|
|
167
|
-
*
|
|
168
|
-
* ── 왜 캐시가 아니라 표인가 ────────────────────────────────────────────────
|
|
169
|
-
* 만료되면 창이 다시 미끄러지고, 그 손실은 오류 없이 들어온 것이 없다. 스냅샷 체크포인트와 성질이 다르다
|
|
170
|
-
* (그쪽은 잃어도 원천이 정정해 준다 — 이 값은 **잃으면 원천에 묻지 않게 된다**).
|
|
171
|
-
*
|
|
172
|
-
* 모양은 `{ streams: { [흐름]: { since?, seen[] } }, firstAttachedAt? }` 다. **흐름 이름은 어댑터가
|
|
173
|
-
* 정한다** — 원본마다 흐름 수와 뜻이 다르므로 이 층은 열쇠로만 다룬다. `simple-json` 이라 드라이버
|
|
174
|
-
* 다섯을 그대로 지난다.
|
|
175
|
-
*
|
|
176
|
-
* `firstAttachedAt` 은 「언제부터 아는가」다. 커널은 상한만 안다(`nowTime` = 마지막으로 들은 시각).
|
|
177
|
-
* 둘이 함께 「이 트윈이 아는 구간」이고, 화면이 수를 보일 때 그 구간을 말해야 한다.
|
|
178
|
-
*/
|
|
179
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
180
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Live feed read cursor carried across restarts, keyed by adapter-defined stream. Null means the feed has never attached, and the next attach decides its first window.' })
|
|
181
|
-
liveCursor?: any
|
|
182
|
-
|
|
183
|
-
@CreateDateColumn()
|
|
184
|
-
@Field({ nullable: true, description: 'Timestamp when the reference was first created.' })
|
|
185
|
-
createdAt?: Date
|
|
186
|
-
|
|
187
|
-
@UpdateDateColumn()
|
|
188
|
-
@Field({ nullable: true, description: 'Timestamp when the reference row was last updated.' })
|
|
189
|
-
updatedAt?: Date
|
|
190
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Arg, Ctx, Int, Query, Resolver } from 'type-graphql'
|
|
2
|
-
|
|
3
|
-
import { ScalarObject } from '@things-factory/shell'
|
|
4
|
-
|
|
5
|
-
import { TwinEngine } from '../../engine/index.js'
|
|
6
|
-
import { digestAttentions } from '../../engine/attention-digest.js'
|
|
7
|
-
|
|
8
|
-
/*
|
|
9
|
-
* 주목 신호(Attention) 질의 — 현재 스냅샷의 요약된 "봐야 할 것".
|
|
10
|
-
* 커널 computeAttentions() 파생: severity(ISA-18.2/IEC 62682) · state(OPC UA A&C) ·
|
|
11
|
-
* anchor(locationId/moverId/orderId = 공간 위치) · suggestedAction(조치 제안). kind 는 도메인 소유(무방언).
|
|
12
|
-
* full StateSnapshot 대신 이 경량 목록을 AI read 도구·insight UI 가 소싱(대용량 덤프 회피).
|
|
13
|
-
* (실시간 스트림은 twinState subscription 이 attentions 를 포함. 이건 one-shot '질의' 표면.)
|
|
14
|
-
*/
|
|
15
|
-
@Resolver()
|
|
16
|
-
export class TwinAttentionQuery {
|
|
17
|
-
@Query(returns => [ScalarObject], {
|
|
18
|
-
description: 'Active attention signals (things to look at) derived from the current twin snapshot — severity (ISA-18.2), lifecycle state (OPC UA A&C), space anchor, and suggested action.'
|
|
19
|
-
})
|
|
20
|
-
async twinAttentions(
|
|
21
|
-
@Ctx() context: ResolverContext,
|
|
22
|
-
@Arg('instanceId', { nullable: true }) instanceId?: string,
|
|
23
|
-
/*
|
|
24
|
-
* **공간으로 물으면 그 현장의 모든 렌즈에서 모아 답한다** — 한 현실을 WMS·MES·YMS 가 함께 비추므로
|
|
25
|
-
* "이 현장에서 봐야 할 것" 은 렌즈 하나로 답할 수 없다. 예전에는 화면이 인스턴스마다 물어 손으로
|
|
26
|
-
* 합쳤고, 그러면 정렬 규칙이 화면마다 갈린다.
|
|
27
|
-
*
|
|
28
|
-
* 경고는 **합집합이 그대로 뜻이 있는 유일한 렌즈**다. 예측은 합칠 수 없다(P50 두 개를 더할 수 없다) —
|
|
29
|
-
* 그래서 예측은 여전히 인스턴스별로 답하고 화면이 나란히 놓는다.
|
|
30
|
-
*/
|
|
31
|
-
@Arg('spaceId', { nullable: true }) spaceId?: string
|
|
32
|
-
/*
|
|
33
|
-
* ── 자르는 인자는 여기 없다 (2026-09-19, 수석 아키텍트 판정) ──────────────
|
|
34
|
-
*
|
|
35
|
-
* `limit` 이 있었다. 자르면서 **몇 건을 잘랐는지는 답에 싣지 못했다** — 답이 맨 목록이라 실을
|
|
36
|
-
* 자리가 없었기 때문이다. 자를 수 있는 문이 잘린 수를 못 말하면, 스무 건만 받은 화면은 그것이
|
|
37
|
-
* 전부인지 이백 중 스무 건인지 구별할 수 없다.
|
|
38
|
-
*
|
|
39
|
-
* 자르려는 소비자는 `twinAttentionDigest` 를 쓴다 — 그 문은 `attentionTotal` 을 함께 답하고,
|
|
40
|
-
* 자리별 색을 **전량을 근거로** 계산한다. 이 문은 자르지 않는다.
|
|
41
|
-
*/
|
|
42
|
-
): Promise<any[]> {
|
|
43
|
-
if (spaceId) return (await TwinEngine.attentionsOfSpace(context.state.domain.id, spaceId)).attentions
|
|
44
|
-
if (!instanceId || !TwinEngine.owns(context.state.domain.id, instanceId)) return [] // 테넌트 격리
|
|
45
|
-
// 라이브 커널 스냅샷(fresh) 우선 — snapshot()=resync() 는 캐시라 커맨드 델타 지연(recover 와 동일 원천 사용).
|
|
46
|
-
const kernel = TwinEngine.kernel(context.state.domain.id, instanceId)
|
|
47
|
-
const snap = kernel?.getSnapshot?.() ?? TwinEngine.snapshot(context.state.domain.id, instanceId)
|
|
48
|
-
return snap?.attentions ?? []
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 잘랐다면 **몇 건을 잘랐는지**와 자리 색 요약까지 — 목록만 주면 화면이 "N건 더" 를 말할 수 없다.
|
|
53
|
-
* 자리별 최고 심각도는 **전량을 근거로** 계산한다(상위 N 으로 줄이면 20위 밖 신호를 가진 자리가 색을 잃는다).
|
|
54
|
-
*/
|
|
55
|
-
@Query(returns => ScalarObject, {
|
|
56
|
-
description: 'Attention signals for a space (all its lenses) or one twin, with the total count and the per-location highest severity folded from all of them.'
|
|
57
|
-
})
|
|
58
|
-
async twinAttentionDigest(
|
|
59
|
-
@Ctx() context: ResolverContext,
|
|
60
|
-
@Arg('spaceId', { nullable: true }) spaceId?: string,
|
|
61
|
-
@Arg('instanceId', { nullable: true }) instanceId?: string,
|
|
62
|
-
@Arg('limit', type => Int, { nullable: true }) limit?: number
|
|
63
|
-
): Promise<any> {
|
|
64
|
-
if (spaceId) return TwinEngine.attentionsOfSpace(context.state.domain.id, spaceId, limit ?? undefined)
|
|
65
|
-
if (!instanceId || !TwinEngine.owns(context.state.domain.id, instanceId)) return { attentions: [], attentionTotal: 0, severityByLocation: {} }
|
|
66
|
-
const kernel = TwinEngine.kernel(context.state.domain.id, instanceId)
|
|
67
|
-
const snap = kernel?.getSnapshot?.() ?? TwinEngine.snapshot(context.state.domain.id, instanceId)
|
|
68
|
-
return digestAttentions((snap?.attentions ?? []).map((a: any) => ({ ...a, instanceId })), limit ?? undefined)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* 커맨드 감사 기록 만들기 (순수) — **누가 무엇을 허락했고, 그래서 어떻게 됐나.**
|
|
3
|
-
*
|
|
4
|
-
* 승인 게이트가 앞을 막고, 이 기록이 뒤를 설명한다. 둘 다 있어야 "사람 손을 거쳤다" 를 증명할 수 있다.
|
|
5
|
-
*
|
|
6
|
-
* 무엇을 믿는가가 이 기록의 전부다:
|
|
7
|
-
* · **신원·시각은 서버가 준다.** 클라이언트가 말한 신원을 그대로 적으면 위조가 자유로워 아무것도
|
|
8
|
-
* 증명하지 못한다. 세션이 아는 사용자와 서버 시각만 쓴다.
|
|
9
|
-
* · **의도는 클라이언트가 준다** — 출처(origin)·근거(reason). 서버가 알 수 없는 정보이고,
|
|
10
|
-
* 위조되더라도 신원 증명을 훼손하지 않는다.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
export type CommandOrigin = 'user' | 'ai' | 'automation' | 'unknown'
|
|
14
|
-
|
|
15
|
-
export type CommandAuditInput = {
|
|
16
|
-
/** 클라이언트가 실어 보낸 커맨드(신뢰하지 않는 부분을 포함한 원본). */
|
|
17
|
-
command: any
|
|
18
|
-
/** 커널 판정. */
|
|
19
|
-
ack: { accepted?: boolean; errorCode?: string; error?: string }
|
|
20
|
-
/**
|
|
21
|
-
* **원본(어댑터)이 준 답** — 허락과 일어남 사이에 끼어 있는 것을 같은 기록에 닫는다 (ADR-0029 §1 결정 C).
|
|
22
|
-
*
|
|
23
|
-
* ── 왜 이 칸이 필요한가 ──────────────────────────────────────────────────
|
|
24
|
-
* 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 오류 없이 실패하면 원장에는 승인만
|
|
25
|
-
* 남는다. 그래서 어댑터의 답을 **같은 행**에 되적는다.
|
|
26
|
-
*
|
|
27
|
-
* 셋을 구별한다:
|
|
28
|
-
* · 없음(`undefined`) — **원본에 묻지 않았다**(커널이 받은 명령이다). 「모른다」와 다르다.
|
|
29
|
-
* · `{ answered: false }` — 물었는데 **답을 못 받았다** → `unknown` 으로 남긴다. 성공으로 적지 않는다.
|
|
30
|
-
* · `{ answered: true, ok, code? }` — 원본이 답했다(적용·거절 모두 사실이다).
|
|
31
|
-
*/
|
|
32
|
-
source?: { answered: boolean; ok?: boolean; code?: string }
|
|
33
|
-
/** 세션이 아는 사용자 — **서버만 채운다.** */
|
|
34
|
-
actor?: { id?: string; email?: string; name?: string }
|
|
35
|
-
/** 서버 시각. 호출부가 주입해 테스트가 시간을 고정할 수 있게 한다. */
|
|
36
|
-
at: Date
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** `TwinAuditEvent` 에 그대로 넣을 수 있는 모양(엔티티를 몰라도 되게 순수하게 둔다). */
|
|
40
|
-
export type CommandAuditRow = {
|
|
41
|
-
eventTime: Date
|
|
42
|
-
commandId?: string
|
|
43
|
-
commandType?: string
|
|
44
|
-
origin: CommandOrigin
|
|
45
|
-
reason?: string
|
|
46
|
-
actorId?: string
|
|
47
|
-
actorEmail?: string
|
|
48
|
-
actorName?: string
|
|
49
|
-
accepted: boolean
|
|
50
|
-
errorCode?: string
|
|
51
|
-
/**
|
|
52
|
-
* 원본이 그래서 어떻게 했나 — `applied` · `refused` · `unknown`(물었지만 답이 없다).
|
|
53
|
-
* **없으면 묻지 않은 것이다**(커널이 받은 명령). 0 이나 성공으로 채우지 않는다.
|
|
54
|
-
*/
|
|
55
|
-
sourceOutcome?: 'applied' | 'refused' | 'unknown'
|
|
56
|
-
/** 원본이 준 사유 코드 — 있으면 그대로. 우리가 지어내지 않는다. */
|
|
57
|
-
sourceCode?: string
|
|
58
|
-
args?: any
|
|
59
|
-
argsTruncated: boolean
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** 신뢰할 수 있는 출처 표기로 정규화 — 모르는 값은 지어내지 않고 'unknown' 으로 둔다. */
|
|
63
|
-
export function normalizeOrigin(v: unknown): CommandOrigin {
|
|
64
|
-
return v === 'user' || v === 'ai' || v === 'automation' ? v : 'unknown'
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** args 직렬화 상한(문자). 넘으면 자르되 잘랐다고 표시한다. */
|
|
68
|
-
const ARGS_MAX = 4000
|
|
69
|
-
|
|
70
|
-
export function buildCommandAudit(input: CommandAuditInput): CommandAuditRow {
|
|
71
|
-
const { command, ack, actor, at, source } = input
|
|
72
|
-
const argsText = safeJson(command?.args)
|
|
73
|
-
const truncated = argsText !== null && argsText.length > ARGS_MAX
|
|
74
|
-
return {
|
|
75
|
-
eventTime: at,
|
|
76
|
-
commandId: str(command?.commandId),
|
|
77
|
-
commandType: str(command?.type),
|
|
78
|
-
origin: normalizeOrigin(command?.origin),
|
|
79
|
-
reason: str(command?.reason),
|
|
80
|
-
/* 원본의 답 — 묻지 않았으면 칸을 만들지 않는다(모름과 구별한다). */
|
|
81
|
-
...(source ? { sourceOutcome: sourceOutcomeOf(source), ...(source.code ? { sourceCode: source.code } : {}) } : {}),
|
|
82
|
-
/* 신원 — 세션 값만. 커맨드에 실려 온 신원 주장은 쳐다보지 않는다. */
|
|
83
|
-
actorId: str(actor?.id),
|
|
84
|
-
actorEmail: str(actor?.email),
|
|
85
|
-
actorName: str(actor?.name),
|
|
86
|
-
/* 결과 — 승인했는데 커널이 거절한 것도 감사 대상이다(무엇을 시도했는지가 남아야 한다). */
|
|
87
|
-
accepted: !!ack?.accepted,
|
|
88
|
-
errorCode: str(ack?.errorCode),
|
|
89
|
-
/* 인자는 원형 그대로. 너무 크면 잘린 문자열로 두되 잘랐다고 말한다. */
|
|
90
|
-
args: truncated ? argsText!.slice(0, ARGS_MAX) : command?.args ?? undefined,
|
|
91
|
-
argsTruncated: truncated
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const str = (v: unknown): string | undefined => (typeof v === 'string' && v ? v : undefined)
|
|
96
|
-
|
|
97
|
-
function safeJson(v: unknown): string | null {
|
|
98
|
-
try {
|
|
99
|
-
return v === undefined ? null : JSON.stringify(v)
|
|
100
|
-
} catch {
|
|
101
|
-
return null /* 순환 참조 등 — 못 재면 자르지 않는다(원본을 그대로 둔다) */
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* 원본의 답을 세 값으로 — **답이 없으면 `unknown`**(성공으로 적지 않는다).
|
|
107
|
-
*
|
|
108
|
-
* 이 함수가 있는 이유: 「물었지만 답이 없다」를 실패로도 성공으로도 적을 수 없다. 실패로 적으면 일어난 일을
|
|
109
|
-
* 없던 일로 만들고, 성공으로 적으면 없던 일을 일어난 일로 만든다. 셋째 값이 사실이다.
|
|
110
|
-
*/
|
|
111
|
-
export function sourceOutcomeOf(source: { answered: boolean; ok?: boolean }): 'applied' | 'refused' | 'unknown' {
|
|
112
|
-
if (!source.answered || typeof source.ok !== 'boolean') return 'unknown'
|
|
113
|
-
return source.ok ? 'applied' : 'refused'
|
|
114
|
-
}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'
|
|
2
|
-
import { ObjectType, Field, ID } from 'type-graphql'
|
|
3
|
-
|
|
4
|
-
import { Domain, ScalarObject } from '@things-factory/shell'
|
|
5
|
-
import { config } from '@things-factory/env'
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
* 긴 글의 컬럼 타입은 **드라이버마다 이름이 다르다** — 이 레포의 정본 관행대로 여기서 고른다
|
|
9
|
-
* (board-service 의 `Board.model` 과 같은 방식). `text` 를 그대로 적었더니 Oracle 이 모르는 이름이었다.
|
|
10
|
-
*/
|
|
11
|
-
const DATABASE_TYPE = config.get('ormconfig', {}).type
|
|
12
|
-
|
|
13
|
-
/*
|
|
14
|
-
* TwinAuditEvent — **사람이 무엇을 허락했는가.**
|
|
15
|
-
*
|
|
16
|
-
* ── 왜 저널(TwinEvent)이 아닌가 ───────────────────────────────────────────────
|
|
17
|
-
* 처음에는 저널에 함께 넣었다. "감사는 원장에서 하니까" 라는 이유였는데, 그건 **화면의 편의**였고
|
|
18
|
-
* 저장 구조를 정할 근거가 못 됐다. 넣자마자 예외가 넷 생겼다 — 리플레이에서 빼고, 백필에서 빼고,
|
|
19
|
-
* 원장 거래 분류에서 빼고, 원장 렌더에서 갈랐다. **예외가 넷이면 설계가 "여기 아니다" 라고 말하는 것이다.**
|
|
20
|
-
*
|
|
21
|
-
* 갈라 두면 예외가 0 이고, 오히려 얻는다:
|
|
22
|
-
* · 행위자가 **컬럼**이 된다 — "누가 승인한 것 전부" 는 감사의 기본 질문인데 payload 안에서는 못 찾았다
|
|
23
|
-
* · revision 이 없다. 저널에서는 그 칸을 비워 "상태가 아님" 을 뜻하게 썼는데, 없음을 종류 표시로
|
|
24
|
-
* 쓰는 것이 여러 번 문제를 냈다(백필의 `bizStep IS NULL = 옛 행` 전제가 이것 때문에 깨졌다)
|
|
25
|
-
* · bizStep 오염이 없다 — 저널의 키 추출기는 값이 없으면 이벤트 타입으로 대체하므로,
|
|
26
|
-
* 감사 행을 태우면 CBV 표준 어휘 컬럼에 `governance.command` 가 박힌다
|
|
27
|
-
*
|
|
28
|
-
* ── 무엇을 믿는가 ────────────────────────────────────────────────────────────
|
|
29
|
-
* **신원·시각은 서버가 각인한다.** 클라이언트가 말한 신원을 그대로 적으면 위조가 자유로워 그 기록은
|
|
30
|
-
* 아무것도 증명하지 못한다. 세션이 아는 사용자와 서버 시각만 신뢰한다.
|
|
31
|
-
* 클라이언트에서 받는 것은 **의도**뿐이다 — 어디서 시작됐나(origin), 왜 하나(reason).
|
|
32
|
-
*/
|
|
33
|
-
@Entity()
|
|
34
|
-
/* 목록 기본 정렬 — 최근 것부터. 감사는 "요즘 무슨 일이 있었나" 로 시작한다. */
|
|
35
|
-
@Index('ix_twin_audit_0', (e: TwinAuditEvent) => [e.domain, e.instanceId, e.eventTime], { unique: false })
|
|
36
|
-
/* 행위자로 찾기 — 저널에 있을 때는 불가능했던 질문("김현장이 승인한 것 전부"). */
|
|
37
|
-
@Index('ix_twin_audit_1', (e: TwinAuditEvent) => [e.domain, e.actorEmail, e.eventTime], { unique: false })
|
|
38
|
-
@ObjectType({ description: 'Audit record of a twin command: who approved what, and what the kernel answered.' })
|
|
39
|
-
export class TwinAuditEvent {
|
|
40
|
-
@PrimaryGeneratedColumn('uuid')
|
|
41
|
-
@Field(type => ID, { description: 'Unique identifier of the audit record.' })
|
|
42
|
-
readonly id: string
|
|
43
|
-
|
|
44
|
-
@ManyToOne(type => Domain)
|
|
45
|
-
@Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })
|
|
46
|
-
domain?: Domain
|
|
47
|
-
|
|
48
|
-
@RelationId((e: TwinAuditEvent) => e.domain)
|
|
49
|
-
domainId?: string
|
|
50
|
-
|
|
51
|
-
@Column()
|
|
52
|
-
@Field({ description: 'Twin runtime instance the command was aimed at.' })
|
|
53
|
-
instanceId: string
|
|
54
|
-
|
|
55
|
-
/*
|
|
56
|
-
* 서버 시각. 클라이언트 시계를 믿지 않는다 — 기록의 시간축이 단말 설정에 좌우되면 안 된다.
|
|
57
|
-
*
|
|
58
|
-
* **타입 이름은 적지 않는다** (2026-08-19 Postgres 부팅 실패로 고침).
|
|
59
|
-
* `datetime` 은 sqlite·MySQL 의 이름이고 Postgres 는 `timestamp` 만 안다 — 거꾸로 `timestamp` 는
|
|
60
|
-
* sqlite 가 모른다. **다섯 드라이버에 다 통하는 이름이 없다.** 그래서 이름 고르는 일을 TypeORM 에
|
|
61
|
-
* 맡긴다(`emitDecoratorMetadata` 가 켜져 있어 `Date` 에서 드라이버별 타입을 고른다).
|
|
62
|
-
*/
|
|
63
|
-
@Column()
|
|
64
|
-
@Field({ description: 'Server time when the command was dispatched.' })
|
|
65
|
-
eventTime: Date
|
|
66
|
-
|
|
67
|
-
@Column({ nullable: true })
|
|
68
|
-
@Field({ nullable: true, description: 'Client-supplied command id, for correlating with kernel logs.' })
|
|
69
|
-
commandId?: string
|
|
70
|
-
|
|
71
|
-
@Column({ nullable: true })
|
|
72
|
-
@Field({ nullable: true, description: 'Command type (e.g. order.hold, equipment.repair).' })
|
|
73
|
-
commandType?: string
|
|
74
|
-
|
|
75
|
-
/* 'user' | 'ai' | 'automation' | 'unknown'. 모르면 unknown 이지 사람이 한 것으로 치지 않는다. */
|
|
76
|
-
@Column({ nullable: true })
|
|
77
|
-
@Field({ nullable: true, description: "Where the command originated: 'user' | 'ai' | 'automation' | 'unknown'." })
|
|
78
|
-
origin?: string
|
|
79
|
-
|
|
80
|
-
/*
|
|
81
|
-
* 승인 사유 — 사람이 쓰는 글이라 길이를 미리 자르지 않는다.
|
|
82
|
-
*
|
|
83
|
-
* 이름을 드라이버별로 고른다(2026-08-19): `text` 는 Oracle 이 모르고(그쪽은 `clob`), MySQL 계열은
|
|
84
|
-
* 긴 글에 `longtext` 를, MSSQL 은 `nvarchar(MAX)` 를 쓴다. 다중 DB 를 지키는 이 레포의 관행이 그렇다.
|
|
85
|
-
*/
|
|
86
|
-
@Column({
|
|
87
|
-
nullable: true,
|
|
88
|
-
type:
|
|
89
|
-
DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
|
|
90
|
-
? 'longtext'
|
|
91
|
-
: DATABASE_TYPE == 'oracle'
|
|
92
|
-
? 'clob'
|
|
93
|
-
: DATABASE_TYPE == 'mssql'
|
|
94
|
-
? 'nvarchar'
|
|
95
|
-
: 'text',
|
|
96
|
-
length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined
|
|
97
|
-
})
|
|
98
|
-
@Field({ nullable: true, description: 'Why this action — the rationale shown on the approval card.' })
|
|
99
|
-
reason?: string
|
|
100
|
-
|
|
101
|
-
/* ── 신원: 세션에서만 온다 ── */
|
|
102
|
-
/*
|
|
103
|
-
* **원본이 그래서 어떻게 했나** — 허락과 일어남 사이에 끼어 있는 것을 같은 행에 닫는다
|
|
104
|
-
* (ADR-0029 §1 결정 C, 2026-08-19).
|
|
105
|
-
*
|
|
106
|
-
* 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 오류 없이 실패하면 원장에는 승인만
|
|
107
|
-
* 남는다. 그래서 어댑터의 답을 되적는다.
|
|
108
|
-
*
|
|
109
|
-
* · 비어 있음 — **원본에 묻지 않았다**(커널이 받은 명령이다). 「모른다」와 다르다.
|
|
110
|
-
* · `unknown` — 물었는데 **답을 못 받았다**. 성공으로 적지 않는다.
|
|
111
|
-
* · `applied` · `refused` — 원본이 답했다(둘 다 사실이다).
|
|
112
|
-
*/
|
|
113
|
-
@Column({ nullable: true })
|
|
114
|
-
@Field({ nullable: true, description: "What the source did with it: 'applied' | 'refused' | 'unknown' (asked but no answer). Empty means the source was not asked — the kernel took the command." })
|
|
115
|
-
sourceOutcome?: string
|
|
116
|
-
|
|
117
|
-
/** 원본이 준 사유 코드 — 있으면 그대로 적는다(우리가 지어내지 않는다). */
|
|
118
|
-
@Column({ nullable: true })
|
|
119
|
-
@Field({ nullable: true, description: 'Reason code the source returned, as it gave it.' })
|
|
120
|
-
sourceCode?: string
|
|
121
|
-
|
|
122
|
-
@Column({ nullable: true })
|
|
123
|
-
@Field({ nullable: true, description: 'Approving user id, stamped by the server from the session.' })
|
|
124
|
-
actorId?: string
|
|
125
|
-
|
|
126
|
-
@Column({ nullable: true })
|
|
127
|
-
@Field({ nullable: true, description: 'Approving user email, stamped by the server from the session.' })
|
|
128
|
-
actorEmail?: string
|
|
129
|
-
|
|
130
|
-
@Column({ nullable: true })
|
|
131
|
-
@Field({ nullable: true, description: 'Approving user name, stamped by the server from the session.' })
|
|
132
|
-
actorName?: string
|
|
133
|
-
|
|
134
|
-
/* ── 결과: 거절도 남긴다 ── */
|
|
135
|
-
@Column({ default: false })
|
|
136
|
-
@Field({ description: 'Whether the kernel accepted the command.' })
|
|
137
|
-
accepted: boolean
|
|
138
|
-
|
|
139
|
-
@Column({ nullable: true })
|
|
140
|
-
@Field({ nullable: true, description: 'Language-neutral rejection code when the kernel refused.' })
|
|
141
|
-
errorCode?: string
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* 명령 인자 — **원형 그대로.** 무엇에 대한 명령이었는지가 감사의 핵심이라 요약하지 않는다.
|
|
145
|
-
* 지나치게 크면 자르되 `argsTruncated` 로 잘랐다는 사실을 남긴다(알리지 않고 버리지 않는다).
|
|
146
|
-
*/
|
|
147
|
-
@Column({ type: 'simple-json', nullable: true })
|
|
148
|
-
@Field(type => ScalarObject, { nullable: true, description: 'Command arguments as given.' })
|
|
149
|
-
args?: any
|
|
150
|
-
|
|
151
|
-
@Column({ default: false })
|
|
152
|
-
@Field({ description: 'True when args were too large and stored truncated.' })
|
|
153
|
-
argsTruncated: boolean
|
|
154
|
-
|
|
155
|
-
@CreateDateColumn()
|
|
156
|
-
@Field({ nullable: true, description: 'Timestamp when the audit row was written.' })
|
|
157
|
-
createdAt?: Date
|
|
158
|
-
}
|