@things-factory/headless-twin 10.0.10 → 10.0.12

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 (138) hide show
  1. package/dist-server/engine/canonical-ingest.d.ts +25 -2
  2. package/dist-server/engine/canonical-ingest.js +48 -10
  3. package/dist-server/engine/canonical-ingest.js.map +1 -1
  4. package/dist-server/engine/declared-stimulus.d.ts +43 -0
  5. package/dist-server/engine/declared-stimulus.js +57 -0
  6. package/dist-server/engine/declared-stimulus.js.map +1 -0
  7. package/dist-server/engine/index.d.ts +2 -0
  8. package/dist-server/engine/index.js +2 -0
  9. package/dist-server/engine/index.js.map +1 -1
  10. package/dist-server/engine/kpi-fold.d.ts +12 -0
  11. package/dist-server/engine/kpi-fold.js +21 -1
  12. package/dist-server/engine/kpi-fold.js.map +1 -1
  13. package/dist-server/engine/kpi-query.d.ts +3 -3
  14. package/dist-server/engine/kpi-query.js +4 -4
  15. package/dist-server/engine/kpi-query.js.map +1 -1
  16. package/dist-server/engine/live-feed-registry.d.ts +1 -1
  17. package/dist-server/engine/live-feed-registry.js +1 -1
  18. package/dist-server/engine/live-feed-registry.js.map +1 -1
  19. package/dist-server/engine/local-declarations.d.ts +3 -6
  20. package/dist-server/engine/local-declarations.js +97 -16
  21. package/dist-server/engine/local-declarations.js.map +1 -1
  22. package/dist-server/engine/measured-yield.d.ts +42 -0
  23. package/dist-server/engine/measured-yield.js +75 -0
  24. package/dist-server/engine/measured-yield.js.map +1 -0
  25. package/dist-server/engine/operation-basis.d.ts +16 -0
  26. package/dist-server/engine/operation-basis.js +20 -2
  27. package/dist-server/engine/operation-basis.js.map +1 -1
  28. package/dist-server/engine/property-effects.js +17 -0
  29. package/dist-server/engine/property-effects.js.map +1 -1
  30. package/dist-server/engine/restart-policy.d.ts +13 -0
  31. package/dist-server/engine/restart-policy.js +52 -0
  32. package/dist-server/engine/restart-policy.js.map +1 -0
  33. package/dist-server/engine/spec-coverage.d.ts +8 -0
  34. package/dist-server/engine/spec-coverage.js +3 -1
  35. package/dist-server/engine/spec-coverage.js.map +1 -1
  36. package/dist-server/engine/twin-engine.d.ts +48 -15
  37. package/dist-server/engine/twin-engine.js +179 -39
  38. package/dist-server/engine/twin-engine.js.map +1 -1
  39. package/dist-server/index.js +1 -1
  40. package/dist-server/index.js.map +1 -1
  41. package/dist-server/service/index.d.ts +1 -1
  42. package/dist-server/service/reference/control-routing.d.ts +14 -0
  43. package/dist-server/service/reference/control-routing.js +64 -0
  44. package/dist-server/service/reference/control-routing.js.map +1 -0
  45. package/dist-server/service/reference/index.d.ts +1 -0
  46. package/dist-server/service/reference/index.js +2 -0
  47. package/dist-server/service/reference/index.js.map +1 -1
  48. package/dist-server/service/reference/reference-adapter.d.ts +67 -0
  49. package/dist-server/service/reference/reference-adapter.js +18 -0
  50. package/dist-server/service/reference/reference-adapter.js.map +1 -1
  51. package/dist-server/service/reference/reference-live.js +3 -3
  52. package/dist-server/service/reference/reference-live.js.map +1 -1
  53. package/dist-server/service/reference/reference-resolver.d.ts +3 -3
  54. package/dist-server/service/reference/reference-resolver.js +35 -18
  55. package/dist-server/service/reference/reference-resolver.js.map +1 -1
  56. package/dist-server/service/twin-audit/command-audit.d.ts +34 -0
  57. package/dist-server/service/twin-audit/command-audit.js +15 -1
  58. package/dist-server/service/twin-audit/command-audit.js.map +1 -1
  59. package/dist-server/service/twin-audit/twin-audit-event.d.ts +3 -0
  60. package/dist-server/service/twin-audit/twin-audit-event.js +28 -2
  61. package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -1
  62. package/dist-server/service/twin-control/twin-control-mutation.d.ts +15 -2
  63. package/dist-server/service/twin-control/twin-control-mutation.js +85 -34
  64. package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
  65. package/dist-server/service/twin-event/twin-event.js +1 -1
  66. package/dist-server/service/twin-event/twin-event.js.map +1 -1
  67. package/dist-server/service/twin-instance/twin-instance.d.ts +1 -1
  68. package/dist-server/service/twin-instance/twin-instance.js +2 -2
  69. package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
  70. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +2 -1
  71. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
  72. package/dist-server/service/twin-model/twin-equipment.js +1 -1
  73. package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
  74. package/dist-server/service/twin-model/twin-location.js +1 -1
  75. package/dist-server/service/twin-model/twin-location.js.map +1 -1
  76. package/dist-server/service/twin-model/twin-model-query.js +1 -1
  77. package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
  78. package/dist-server/service/twin-model/twin-operation.js +1 -1
  79. package/dist-server/service/twin-model/twin-operation.js.map +1 -1
  80. package/package.json +3 -3
  81. package/server/engine/canonical-ingest.ts +78 -14
  82. package/server/engine/declared-stimulus.ts +66 -0
  83. package/server/engine/index.ts +2 -0
  84. package/server/engine/kpi-fold.ts +29 -1
  85. package/server/engine/kpi-query.ts +8 -8
  86. package/server/engine/live-feed-registry.ts +2 -2
  87. package/server/engine/local-declarations.ts +97 -19
  88. package/server/engine/measured-yield.ts +89 -0
  89. package/server/engine/operation-basis.ts +33 -2
  90. package/server/engine/property-effects.ts +17 -0
  91. package/server/engine/restart-policy.ts +55 -0
  92. package/server/engine/spec-coverage.ts +23 -3
  93. package/server/engine/twin-engine.ts +201 -42
  94. package/server/index.ts +1 -1
  95. package/server/service/reference/control-routing.ts +62 -0
  96. package/server/service/reference/index.ts +1 -0
  97. package/server/service/reference/reference-adapter.ts +78 -0
  98. package/server/service/reference/reference-live.ts +3 -3
  99. package/server/service/reference/reference-resolver.ts +46 -7
  100. package/server/service/twin-audit/command-audit.ts +34 -1
  101. package/server/service/twin-audit/twin-audit-event.ts +50 -4
  102. package/server/service/twin-control/twin-control-mutation.ts +75 -28
  103. package/server/service/twin-event/twin-event.ts +10 -2
  104. package/server/service/twin-instance/twin-instance.ts +16 -10
  105. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +2 -1
  106. package/server/service/twin-model/twin-equipment.ts +8 -1
  107. package/server/service/twin-model/twin-location.ts +8 -1
  108. package/server/service/twin-model/twin-model-query.ts +1 -1
  109. package/server/service/twin-model/twin-operation.ts +8 -1
  110. package/test/adopt-structure-live.test.ts +7 -7
  111. package/test/boot-resume.test.ts +3 -3
  112. package/test/column-type-portability.test.ts +122 -0
  113. package/test/control-capability.test.ts +103 -0
  114. package/test/declared-stimulus.test.ts +88 -0
  115. package/test/ingest-running-guard.test.ts +5 -5
  116. package/test/instance-cache-lifecycle.test.ts +1 -1
  117. package/test/kpi-baseline-db.test.ts +1 -1
  118. package/test/kpi-query-bench.test.ts +1 -1
  119. package/test/lineage-survives-restart.test.ts +3 -3
  120. package/test/live-feed-registry.test.ts +6 -6
  121. package/test/local-declarations.test.ts +108 -1
  122. package/test/measured-yield.test.ts +90 -0
  123. package/test/operation-basis.test.ts +28 -1
  124. package/test/operational-vocabulary.test.ts +108 -0
  125. package/test/operations-capability-db.test.ts +4 -4
  126. package/test/project-structure-db.test.ts +1 -1
  127. package/test/projection-reaches-screen.test.ts +1 -1
  128. package/test/property-effects.test.ts +28 -0
  129. package/test/restart-policy.test.ts +111 -0
  130. package/test/resync-origin-site.test.ts +7 -1
  131. package/test/source-outcome-audit.test.ts +104 -0
  132. package/test/structure-revision-db.test.ts +27 -27
  133. package/test/tenant-registry-db.test.ts +2 -2
  134. package/test/twin-model-item-db.test.ts +3 -3
  135. package/test/twin-model-tree-db.test.ts +7 -7
  136. package/test/twin-origin-resync.test.ts +4 -4
  137. package/test/yield-loop.test.ts +144 -0
  138. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"reference-resolver.js","sourceRoot":"","sources":["../../../server/service/reference/reference-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Mutation, Query, Resolver, Directive} from 'type-graphql'\n\nimport { ScalarObject, getRepository } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { readBoardEquipment } from '@operato/twin-kernel'\n\nimport { applyKnobDefaults, filledKnobKeys } from './knob-defaults.js'\nimport type { KnobDef } from './template-registry.js'\nimport { knobDefaultsFilled, pickOriginSite, siteEquipmentAdopted } from './reference-master.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinReference } from './twin-reference.js'\nimport { listReferences, getReference } from './reference-registry.js'\nimport { getAdapter, listAdapterTypes, listAdapters } from './reference-adapter.js'\nimport {\n discovered, failed, detailOf,\n referenceNotFound, adapterUnknown, discoveryFailed, discoveryTimedOut\n} from './discovery-result.js'\nimport { refuseImportSpace } from './ingest-space.js'\nimport { startReferenceLiveFeed } from './reference-live.js'\nimport { listTemplates, getTemplate } from './template-registry.js'\n\n/*\n * Face2 레퍼런스 인제스트 채널(ADR-0018) — 등록된 레퍼런스 소스를 열거하고, 골라서 트윈으로 인제스트.\n * \"연결하고 내 것을 불러온다\" — 엔티티는 레퍼런스에서 오지 손배선/발명이 아니다.\n */\n\n/**\n * 발견 조회의 시간 상한 — 15초.\n *\n * 어댑터 계약에 시간 제한이 없다. 주소가 틀린 엔드포인트는 답하지 않고, 그러면 화면이 무한히 로딩된다 —\n * 사용자에게는 \"실패\" 보다 못한 상태다(무엇을 기다리는지 모른 채 기다린다). 실 시스템 조회가 몇 초\n * 걸리는 것은 정상이므로 넉넉히 두되, 끝은 있어야 한다.\n */\nconst DISCOVER_TIMEOUT_MS = 15_000\nconst TIMEOUT = 'discover-timeout'\n\nfunction withTimeout<T>(work: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(Object.assign(new Error('timeout'), { code: TIMEOUT })), ms)\n work.then(\n v => { clearTimeout(timer); resolve(v) },\n e => { clearTimeout(timer); reject(e) }\n )\n })\n}\n\n/**\n * 거절을 **사용자 언어로 옮겨 보낸다** — 번역은 한 곳에서 한다.\n *\n * ── 왜 서버인가 (2026-08-14) ────────────────────────────────────────────────\n * 실측: 실행 중인 트윈을 다시 프로비저닝하면 「instance \"order-check\" is running — stop before\n * re-provisioning」 이라는 **영어 한 줄이 토스트로** 떴다(다섯 언어 제품에서).\n *\n * 서버와 앱은 **같은 사전**을 쓰고, 사용자의 현재 언어가 백엔드에 반영된다. 그래서 이 문구는 서버가\n * 옮기는 것이 맞다 — 프레임워크가 이미 같은 규약이다(`authenticate-401-middleware` 가\n * `context.t('error.' + errorCode, detail)` 로 옮긴다).\n *\n * ── 그러면 코드는 왜 함께 보내나 ────────────────────────────────────────────\n * 화면이 **구조로** 다뤄야 하는 거절이 따로 있다(정합성 표의 행·심각도·수리 버튼 — 그것들은\n * `twin.compose.chk.*` 처럼 화면이 옮긴다). 그리고 브라우저가 아닌 소비자(AI·스크립트·API)에게는\n * 코드가 계약이다. 문장과 코드는 서로를 대신하지 않는다.\n *\n * **두 곳에서 같은 코드를 옮기지 않는다** — 문장이 두 벌이 되면 반드시 어긋난다.\n */\nfunction refusal(context: ResolverContext, e: any, fallback: string): Record<string, unknown> {\n const code = typeof e?.code === 'string' ? e.code : undefined\n const params = e?.params && typeof e.params === 'object' ? e.params : undefined\n /* 영어 canonical 은 항상 남긴다 — 번역 키가 없으면 그것이 보이고, 로그에는 그것이 남는다. */\n const canonical = e?.message || fallback\n const message =\n code && typeof context.t === 'function'\n ? String(context.t(`twin.provision.err.${code}`, { ...(params ?? {}), defaultValue: canonical }))\n : canonical\n return { ok: false, error: message, ...(code ? { errorCode: code } : {}), ...(params ? { errorParams: params } : {}) }\n}\n\n/**\n * `siteEquipmentIds` 노브를 이 현장의 설비로 채운다 — **비어 있을 때만.**\n *\n * 사용자가 목록을 직접 준 경우에는 손대지 않는다(고른 것이 정본이다). 현장이 없으면 채울 것도 없다.\n * 등록부의 모델에서 읽는다(런타임이 아니다) — 트윈이 도는 중이 아니어도 그 현장의 설비는 사실이다.\n */\nasync function resolveSiteEquipmentKnobs(\n knobs: readonly KnobDef[] | undefined,\n effective: Record<string, any>,\n domainId: string,\n spaceId?: string\n): Promise<{ key: string; count: number }[]> {\n const targets = (knobs ?? []).filter(k => k?.type === 'siteEquipment')\n if (!targets.length) return []\n const out: { key: string; count: number }[] = []\n let ids: { id: string; kind: string }[] | undefined\n for (const k of targets) {\n const given = effective[k.key]\n if (Array.isArray(given) && given.length) continue // 사용자가 고른 것이 정본이다\n if (!spaceId) {\n effective[k.key] = []\n continue\n }\n if (ids === undefined) {\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n const seen = new Map<string, { id: string; kind: string }>()\n for (const r of rows) {\n for (const e of readBoardEquipment((r.model as any) ?? {})) {\n if (!e?.id || seen.has(String(e.id))) continue\n seen.set(String(e.id), { id: String(e.id), kind: String((e as any).kind ?? '') })\n }\n }\n ids = [...seen.values()]\n }\n effective[k.key] = ids\n out.push({ key: k.key, count: ids.length })\n }\n return out\n}\n\n@Resolver()\nexport class TwinReferenceResolver {\n /** 등록된 레퍼런스 소스 목록(요약 + 이미 인제스트됐는지). */\n @Query(returns => [ScalarObject], { description: 'List registered reference sources (virtual or real adapters) available to ingest.' })\n async referenceSources(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const out: any[] = []\n for (const m of listReferences()) {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: m.source } })\n out.push({\n source: m.source,\n system: m.system,\n siteName: m.siteName,\n locationCount: m.locations.filter(l => l.role === 'location' || l.role === 'both').length,\n areaCount: m.locations.filter(l => l.role === 'area' || l.role === 'both').length,\n equipmentCount: (m.equipment ?? []).length,\n imported: !!reg,\n running: TwinEngine.owns(domainId, m.source)\n })\n }\n return out\n }\n\n /** 소스를 인제스트 → 공간 + 인스턴스 생성(provision). start 면 기동까지. */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Ingest a registered reference source into a twin (space + instance). Optionally start it.' })\n async importFromReference(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('start', { nullable: true }) start?: boolean\n ): Promise<any> {\n const master = getReference(source)\n if (!master) return { ok: false, error: `unknown reference source: ${source}` }\n const domainId = context.state.domain.id\n try {\n /* 어디서 왔는지 남긴다 — 이것이 없으면 이 트윈은 두 번 다시 읽을 수 없다.\n 이 경로는 **메모리에 등록된 마스터 하나**를 그대로 쓰므로 사이트 서술자가 없다(사이트 정체를\n 적을 것이 없다). 다시 읽기도 같은 등록본을 집으므로 사이트를 찾을 필요가 없다. */\n const res = await TwinEngine.ingestMaster(domainId, { ...master, origin: { kind: 'reference', source } }, undefined, context.state.user)\n if (start) await TwinEngine.startFromRegistry(domainId, res.instanceId)\n return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings: res.warnings }\n } catch (e: any) {\n return refusal(context, e, 'ingest failed')\n }\n }\n\n /**\n * **원본에서 다시 읽는다** — 이 트윈의 구조를 지금의 원본 모습으로 갱신한다.\n *\n * ── 왜 진입점이 하나여야 하나 ──────────────────────────────────────────────\n * 지금까지 다시 읽기는 **만드는 경로에 얹혀 있었다**(`importFromReference`·`createFromTemplate`).\n * 그래서 이미 있는 트윈을 갱신하려면 만들 때 무엇을 골랐는지 사람이 기억해 같은 화면을 다시\n * 거쳐야 했고, 템플릿으로 세운 트윈은 노브를 어디에도 안 남겨서 **아예 갱신할 방법이 없었다.**\n * 원천이 무엇이든 트윈 자신이 기억하게 하고(`TwinInstance.origin`), 여기 한 곳에서 그것을 따른다.\n *\n * ── 무엇이 일어나나 ────────────────────────────────────────────────────────\n * 원본에서 마스터를 다시 얻어 인제스트에 그대로 태운다. 그다음은 인제스트가 아는 일이다 —\n * 구조가 달라졌으면 새 리비전이 남고, 구조 행이 다시 그려지고, **실행 중인 미러는 멈추지 않고\n * 전환한다.** 실행 중인 시뮬레이션은 거절된다(조건이 바뀐 실험은 다른 실험이다).\n *\n * ── 못 할 때는 못 한다고 한다 ──────────────────────────────────────────────\n * `origin` 이 없는 트윈(이 자리가 생기기 전에 만들어진 것)은 다시 읽을 수 없다. 짐작으로\n * 템플릿을 고르거나 첫 레퍼런스를 집지 않는다 — 엉뚱한 원본으로 현장을 덮는 것이 훨씬 나쁘다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n \"Re-read a twin's structure from the source it remembers (TwinInstance.origin). Works for both reference- and template-born twins. A running mirror adopts the new structure without stopping; a running simulation is refused.\"\n })\n async resyncTwin(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any> {\n const domainId = context.state.domain.id\n const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!inst) return { ok: false, error: `unknown twin: ${instanceId}` }\n\n const origin = inst.origin as any\n if (!origin?.kind)\n return {\n ok: false,\n error: `twin \"${instanceId}\" does not remember where it came from — it cannot be re-read. Re-create it from its template or reference so the origin is recorded.`\n }\n\n try {\n const master = await this.masterFromOrigin(domainId, origin, instanceId)\n /*\n * **어느 현장의 트윈이었나를 지킨다** — 다시 읽기는 구조만 새로 그리는 일이고, 현장 소속은 그때\n * 사람이 고른 것이다. 기억이 없는 옛 트윈은 **지금 있는 현장**을 그대로 쓴다(빈손으로 두면 템플릿\n * 기본 공간으로 옮겨 간다 — 조용히 현장을 떠나고 그 현장의 값도 잃는다).\n */\n const keepSpace = origin.spaceId || inst.spaceId\n const res = await TwinEngine.ingestMaster(domainId, master, keepSpace ? { spaceId: keepSpace } : undefined, context.state.user)\n return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings: res.warnings }\n } catch (e: any) {\n return refusal(context, e, 'resync failed')\n }\n }\n\n /** 기억해 둔 원천에서 마스터를 다시 얻는다 — 어댑터든 템플릿이든 이 한 곳에서 갈린다. */\n private async masterFromOrigin(domainId: string, origin: any, instanceId: string): Promise<any> {\n if (origin.kind === 'template') {\n const tpl = getTemplate(origin.templateId)\n if (!tpl) throw new Error(`unknown template: ${origin.templateId} — this twin cannot be rebuilt`)\n /* 저장해 둔 노브 그대로 다시 짓는다. 기본값을 다시 입히지 않는다 — 그 사이 템플릿의 기본값이\n 바뀌었다면, 사용자가 고르지 않은 값이 조용히 현장을 바꾸게 된다. */\n const { master } = tpl.build(origin.params ?? {})\n master.origin = origin\n return master\n }\n\n /* 레퍼런스 — 메모리 등록본이 있으면 그것, 없으면 저장된 어댑터 연결로 다시 가져온다.\n (부팅 뒤에는 메모리 등록본이 비어 있으므로 어댑터 경로가 실제로 쓰이는 길이다.) */\n const inMemory = getReference(origin.source)\n if (inMemory) return { ...inMemory, origin }\n\n const ref = await getRepository(TwinReference).findOne({ where: { domain: { id: domainId }, source: origin.source } })\n if (!ref) throw new Error(`reference \"${origin.source}\" is no longer registered — nothing to re-read from`)\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) throw new Error(`no adapter for type: ${ref.adapterType}`)\n const cfg = ref.connectionConfig ?? {}\n const sites = await adapter.discoverSites(cfg)\n\n /*\n * ── 무엇을 무엇과 견주나 (2026-08-18 실측으로 고침) ────────────────────────\n *\n * 예전에는 `master.source === origin.source` 로 사이트를 찾았다. 그런데 `origin.source` 는 **레퍼런스\n * 등록 이름**이고(그 참조의 사이트 전부에 같다) `master.source` 는 **사이트별 인스턴스 id** 다 —\n * 서로 다른 것을 견줬으니 사이트가 멀쩡히 있어도 「더 이상 보고하지 않는다」로 거절했다. 사이트가\n * 여럿인 참조에서 온 트윈은 그래서 **전부** 재동기가 불가했고, 오류 문장은 원인을 참조 쪽으로\n * 잘못 가리켰다.\n *\n * 이제 ① 기억해 둔 사이트로 곧장 간다(`origin.siteId`) ② 기억이 없는 옛 트윈은 사이트를 살펴\n * **마스터의 정체(=이 인스턴스 id)** 와 견준다. 어느 쪽도 못 찾으면 **첫 사이트로 때우지 않는다** —\n * 다른 현장의 구조를 이 트윈에 덮는 것은 오류가 아니라 조용히 틀린 공장으로 나타난다.\n */\n const picked = pickOriginSite(sites, origin)\n if (picked.site) return { ...(await adapter.fetchMaster(cfg, picked.site)), origin }\n if (picked.reason === 'site-gone')\n throw new Error(\n `reference \"${origin.source}\" no longer reports site \"${origin.siteId}\" — refusing to overwrite this twin with a different site`\n )\n\n for (const site of sites) {\n const master = await adapter.fetchMaster(cfg, site)\n if (master.source === instanceId) return { ...master, origin: { ...origin, siteId: site.siteId } }\n }\n throw new Error(\n `reference \"${origin.source}\" does not report a site that rebuilds twin \"${instanceId}\" ` +\n `(this twin was imported before the site identity was recorded, and no site's master carries its id) — refusing to overwrite it with a different site`\n )\n }\n\n /** 등록된 트윈 템플릿(파라미터화 아키타입) 목록 — 노브 스키마 포함(클라이언트 폼용). */\n @Query(returns => [ScalarObject], { description: 'List registered twin templates (parameterized archetypes) with their knob schema.' })\n async twinTemplates(@Ctx() _context: ResolverContext): Promise<any[]> {\n return listTemplates().map(t => ({ id: t.id, label: t.label, system: t.system, description: t.description, detail: t.detail, knobs: t.knobs }))\n }\n\n /** 템플릿 + 노브 → 합성 마스터 → 인제스트(+기동+시나리오). 레퍼런스 import 와 같은 경로, 원천만 합성. */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Instantiate a twin template with params → synthetic master → ingest (+start+scenario). Returns {ok, instanceId, spaceId}.' })\n async createFromTemplate(\n @Arg('templateId') templateId: string,\n @Arg('params', type => ScalarObject) params: any,\n @Ctx() context: ResolverContext,\n @Arg('start', { nullable: true }) start?: boolean,\n @Arg('spaceId', { nullable: true, description: 'Existing space to co-locate this twin into (add a lens to a site). Omit to create its own space.' }) spaceId?: string\n ): Promise<any> {\n const tpl = getTemplate(templateId)\n if (!tpl) return { ok: false, error: `unknown template: ${templateId}` }\n const domainId = context.state.domain.id\n try {\n /*\n * **빠진 노브를 서버가 채운다.** 기본값을 아는 곳은 노브 스키마(계약)인데 그것을 적용하는 곳이\n * 위자드뿐이었다 — 그래서 화면을 거치지 않는 호출자(AI·스크립트·API)가 파라미터를 일부만 주면\n * 템플릿 안에서 발생률이 0 이 되고 **아무것도 하지 않는 트윈**이 조용히 만들어졌다.\n * 채운 노브 이름은 경고로 함께 돌려준다 — 조용히 채우는 것도 조용히 비우는 것만큼 위험하다.\n */\n const filled = filledKnobKeys(tpl.knobs, params)\n const effective = applyKnobDefaults(tpl.knobs, params)\n /*\n * **이 현장에 이미 있는 설비를 노브 값으로 확정한다** (`siteEquipmentIds`).\n *\n * 에너지 트윈이 「공장이 돌면 전기가 오른다」를 말하려면 부하를 **이웃 트윈의 설비 id 로**\n * 선언해야 한다(설비 하나에 사실 둘). 그 목록을 빌드할 때마다 현장에서 다시 읽으면, 사이에\n * 설비가 늘거나 준 만큼 **다시 지을 때 다른 트윈**이 된다. 그래서 여기서 한 번 해석하고\n * 그 결과를 노브 값으로 남긴다(아래 `origin.params` 에 그대로 저장된다).\n */\n const adopted = await resolveSiteEquipmentKnobs(tpl.knobs, effective, domainId, spaceId)\n const { master, scenario } = tpl.build(effective)\n /* **무엇으로 지었는지 남긴다.** 합성은 결정적이므로 같은 노브면 같은 마스터가 다시 나온다 —\n 그래서 템플릿 트윈도 어댑터 트윈과 똑같이 다시 읽을 수 있다. 남기지 않으면 그 트윈은\n 첫날의 모습에 영원히 머문다(원본을 잃은 트윈). */\n /* 고른 현장도 남긴다 — 없으면 다시 읽기가 트윈을 템플릿 기본 공간으로 옮겨 버린다(현장 값도 잃는다). */\n master.origin = { kind: 'template', templateId, params: effective, ...(spaceId ? { spaceId } : {}) }\n /* 공간 선택은 템플릿을 거치지 않는다 — 템플릿마다 이 노브를 알고 있어야 한다면 새 템플릿이\n 조용히 무시하게 된다. 합성된 마스터에 한 곳에서 얹는다(레퍼런스 인제스트와 같은 경로). */\n const res = await TwinEngine.ingestMaster(domainId, master, { spaceId }, context.state.user)\n if (start !== false) {\n await TwinEngine.startFromRegistry(domainId, res.instanceId)\n if (scenario) {\n const runtime = TwinEngine.runtime(domainId, res.instanceId)\n if (runtime) {\n runtime.scenario.load(scenario)\n runtime.scenario.start()\n }\n }\n }\n const warnings = [\n ...(filled.length ? [knobDefaultsFilled(filled)] : []),\n ...adopted.filter(a => a.count > 0).map(a => siteEquipmentAdopted(a.key, a.count)),\n ...res.warnings\n ]\n return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings }\n } catch (e: any) {\n return refusal(context, e, 'template instantiation failed')\n }\n }\n\n /* ── 레퍼런스 관리(엔티티 기반·테넌트 스코프) — reference-management P1 ────────\n * 전역 인메모리(referenceSources/importFromReference)와 공존. 이쪽은 TwinReference 행 + 어댑터 레지스트리.\n */\n\n @Query(returns => [ScalarObject], { description: 'List tenant-scoped persisted twin references (adapter-backed).' })\n async twinReferences(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const rows = await getRepository(TwinReference).find({ where: { domain: { id: domainId } } })\n // provenance 라이브 대조 — 지워진 트윈은 producedCount 에서 자동 제외(상태 동기의 lazy 방식).\n const liveIds = new Set((await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId))\n return rows.map(r => {\n const produced = (((r.scopeSpec as any)?.produced ?? []) as any[]).filter(p => liveIds.has(p.instanceId))\n return {\n source: r.source, system: r.system, siteName: r.siteName, description: r.description,\n adapterType: r.adapterType, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError,\n producedCount: produced.length, produced\n }\n })\n }\n\n @Query(returns => [String], { description: 'List registered reference adapter type keys.' })\n referenceAdapterTypes(): string[] {\n return listAdapterTypes()\n }\n\n /**\n * 인티그레이션 그룹핑 (reference-management §2.3·D11) — 산출물을 커넥터 타입 ▸ Connection ▸ 인스턴스 2단으로.\n * 트윈-네이티브 온톨로지(integration 무의존): TwinReference 가 그룹핑 노드(source=connectionName),\n * scopeSpec.connectorType 로 상위 분류. producedCount 는 라이브 인스턴스로 대조(지워진 트윈 제외).\n */\n @Query(returns => [ScalarObject], { description: 'Group integration items 2-tier: connector type ▸ connection ▸ produced twins. (reference-management §2.3)' })\n async twinConnections(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const rows = await getRepository(TwinReference).find({ where: { domain: { id: domainId } } })\n const liveIds = new Set((await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId))\n const groups = new Map<string, any[]>()\n for (const r of rows) {\n const connectorType = (r.scopeSpec as any)?.connectorType ?? r.adapterType\n const producedCount = (((r.scopeSpec as any)?.produced ?? []) as any[]).filter(p => liveIds.has(p.instanceId)).length\n const conn = { source: r.source, name: r.siteName, status: r.status, adapterType: r.adapterType, producedCount, lastSyncedAt: r.lastSyncedAt }\n if (!groups.has(connectorType)) groups.set(connectorType, [])\n groups.get(connectorType)!.push(conn)\n }\n return [...groups.entries()].map(([connectorType, connections]) => ({\n connectorType,\n connectionCount: connections.length,\n instanceCount: connections.reduce((s, c) => s + c.producedCount, 0),\n connections\n }))\n }\n\n /** 한 Connection 그룹 노드 상세 — 그 아래 생성된 트윈 인스턴스(라이브 대조·상태·기동여부). */\n @Query(returns => ScalarObject, { nullable: true, description: 'One connection grouping location with its produced twin instances (live-checked). (reference-management §2.3)' })\n async twinConnection(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const domainId = context.state.domain.id\n const r = await getRepository(TwinReference).findOne({ where: { domain: { id: domainId }, source } })\n if (!r) return null\n const produced = ((r.scopeSpec as any)?.produced ?? []) as any[]\n const instMap = new Map((await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => [i.instanceId, i]))\n const instances = produced\n .filter(p => instMap.has(p.instanceId))\n .map(p => {\n const inst = instMap.get(p.instanceId) as any\n return { instanceId: p.instanceId, spaceId: p.spaceId, siteId: p.siteId, kind: inst.kind, status: inst.status, running: TwinEngine.owns(domainId, p.instanceId) }\n })\n return {\n source: r.source,\n connectorType: (r.scopeSpec as any)?.connectorType ?? r.adapterType,\n name: r.siteName,\n status: r.status,\n system: r.system,\n lastSyncedAt: r.lastSyncedAt,\n instanceCount: instances.length,\n instances\n }\n }\n\n /** 단건 상세(뷰/편집) — connectionConfig 포함, 어댑터 스키마의 secret 필드는 마스킹(있으면 '••••••'). */\n @Query(returns => ScalarObject, { nullable: true, description: 'Get one tenant-scoped reference with its connection config (secret fields masked) for view/edit.' })\n async twinReference(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const r = await getRepository(TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } })\n if (!r) return null\n const secretKeys = new Set((getAdapter(r.adapterType)?.meta?.configSchema ?? []).filter(f => f.secret).map(f => f.key))\n const cfg: any = {}\n for (const [k, v] of Object.entries((r.connectionConfig as any) ?? {})) cfg[k] = secretKeys.has(k) ? (v ? '••••••' : '') : v\n return {\n source: r.source, system: r.system, siteName: r.siteName, description: r.description,\n adapterType: r.adapterType, connectionConfig: cfg, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError\n }\n }\n\n @Query(returns => [ScalarObject], { description: 'List reference connector metadata (label, domain, config schema, availability) for the connect UI.' })\n referenceAdapters(): any[] {\n return listAdapters().map(a => ({ type: a.type, ...(a.meta ?? {}) }))\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Create or update a tenant-scoped twin reference (persisted).' })\n async saveTwinReference(\n @Arg('source') source: string,\n @Arg('patch', type => ScalarObject) patch: any,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinReference)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, source } })\n const saved = await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n source,\n system: patch.system ?? existing?.system,\n siteName: patch.siteName ?? existing?.siteName,\n description: patch.description ?? existing?.description,\n adapterType: patch.adapterType ?? existing?.adapterType,\n // 필드 단위 병합 — 편집 시 생략된 키(예: 마스킹된 secret)는 기존 값 유지.\n connectionConfig: patch.connectionConfig\n ? { ...((existing?.connectionConfig as any) ?? {}), ...patch.connectionConfig }\n : existing?.connectionConfig,\n mappingSpec: patch.mappingSpec ?? existing?.mappingSpec,\n scopeSpec: patch.scopeSpec ?? existing?.scopeSpec,\n status: patch.status ?? existing?.status ?? 'draft'\n })\n )\n return { ok: true, source: saved.source }\n }\n\n /** 연결 해제 — removeTwins=true 면 이 레퍼런스가 만든 트윈(provenance)도 함께 제거(라이프사이클 연쇄). 기본은 트윈 보존(분리). */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a tenant-scoped reference. If removeTwins, also remove the twin instances it produced (provenance cascade); otherwise twins are kept (detached).' })\n async deleteTwinReference(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('removeTwins', { nullable: true }) removeTwins?: boolean\n ): Promise<boolean> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: domainId }, source } })\n if (removeTwins && ref) {\n for (const p of (((ref.scopeSpec as any)?.produced ?? []) as any[])) {\n try {\n await TwinEngine.remove(domainId, p.instanceId)\n } catch {\n /* 이미 없거나 실패 — 연쇄는 best-effort. */\n }\n }\n }\n await repo.delete({ domain: { id: domainId } as any, source })\n return true\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Test a reference connection via its adapter; updates status.' })\n async testReferenceConnection(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any> {\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: context.state.domain.id }, source } })\n if (!ref) return { ok: false, error: `unknown reference: ${source}` }\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) return { ok: false, error: `no adapter for type: ${ref.adapterType}` }\n try {\n const res = await adapter.testConnection(ref.connectionConfig ?? {})\n await repo.update({ id: ref.id }, { status: res.ok ? 'connected' : 'error', lastError: res.error ?? null } as any)\n return res\n } catch (e: any) {\n return { ok: false, error: e?.message ?? 'test failed' }\n }\n }\n\n /**\n * 어댑터 기반 인제스트 — discoverSites → 사이트별 fetchMaster → ingestMaster (fan-out, §2.2·§4.2).\n * P1 은 대개 N=1(virtual/단일). start 면 각 인스턴스 기동. 라이브 피드·mode 는 face2-inbound-live 소유.\n */\n /** 레퍼런스가 노출하는 사이트/공장 발견 — 트윈 생성 시 \"어느 공장\" 선택용(§2.2). */\n @Query(returns => ScalarObject, { description: 'Discover sites/factories exposed by a reference. Returns { sites, error? } — an empty list with no error means the system genuinely has none, which is different from a failure.' })\n async discoverReferenceSites(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any> {\n /*\n * **\"못 찾았다\" 와 \"없다\" 를 구분한다.** 예전에는 넷을 빈 배열 하나로 접었고(레퍼런스 없음·어댑터\n * 미상·조회 실패·정말 0건), 화면은 그 모두를 \"사이트를 찾지 못했습니다\" 라고만 말했다. 실 시스템\n * 연결에서 가장 자주 막히는 자리인데 자격이 틀렸는지 주소가 틀렸는지 알 수 없었다.\n * 판정과 문장 형태는 `discovery-result`(순수)가 갖는다.\n */\n const ref = await getRepository(TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } })\n if (!ref) return failed(referenceNotFound(source))\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) return failed(adapterUnknown(ref.adapterType, source))\n try {\n /*\n * **기다려도 답이 없으면 사유를 준다.** 어댑터 계약에 시간 제한이 없어서, 주소가 틀린 엔드포인트는\n * 화면을 무한히 돌게 만들었다 — 무한히 도는 화면은 조용한 실패의 다른 얼굴이다.\n * 상한은 여기서 정한다(어댑터마다 다르게 두면 사용자가 어느 것을 기다리는지 알 수 없다).\n */\n const sites = await withTimeout(adapter.discoverSites(ref.connectionConfig ?? {}), DISCOVER_TIMEOUT_MS)\n return discovered(sites)\n } catch (e: any) {\n if (e?.code === TIMEOUT) return failed(discoveryTimedOut(source, DISCOVER_TIMEOUT_MS / 1000))\n return failed(discoveryFailed(source, detailOf(e)))\n }\n }\n\n /**\n * 트윈 생성 — 레퍼런스에서 사이트 발견 → (siteIds 있으면 그 공장만) → fetchMaster → provision. 사이트별 resilient.\n * 여러 공장을 관할하는 소스는 siteIds 로 \"어느 공장\"을 골라 생성(1:N, §2.1·§2.2).\n *\n * ── 현장 선택이 이 경로에도 있다 (2026-08-13) ────────────────────────────\n * 한 현실을 여러 렌즈가 비춘다(WMS·MES·YMS). 그런데 **그 선택이 템플릿 경로에만** 있어서\n * (`createFromTemplate(spaceId)`), 실 시스템에서 가져온 트윈은 어댑터가 파생한 공간 id 가 우연히\n * 일치할 때만 한 현장에 모였다 — 사람이 \"이 MES 와 같은 현장에 넣어라\" 를 말할 방법이 없었다.\n * 데이터로는 가능한 일이 저작으로는 불가능한, `ingest-space` 가 이미 지적한 그 비대칭이다.\n *\n * 판정은 그 순수 모듈이 갖는다: 없는 공간은 거절(`resolveIngestSpace`), 사이트 여럿을 한 공간에\n * 넣는 것도 거절(`refuseImportSpace`) — 서로 다른 현장이 조용히 합쳐지는 것을 막는다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Create twins from a reference: discover sites → filter by siteIds (if given) → fetch master(s) → provision. spaceId co-locates the twin into an existing space (one site only). start=false to only provision; live=true to run as a mirror (adapter openLiveFeed → live projector) instead of sim.' })\n async importTwinReference(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('siteIds', type => [String], { nullable: true }) siteIds?: string[],\n @Arg('start', { nullable: true }) start?: boolean,\n @Arg('live', { nullable: true }) live?: boolean,\n @Arg('spaceId', { nullable: true, description: 'Existing space to co-locate this twin into (add a lens to a site). Only when importing a single site. Omit to give each site its own space.' }) spaceId?: string\n ): Promise<any> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: domainId }, source } })\n if (!ref) return { ok: false, error: `unknown reference: ${source}` }\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) return { ok: false, error: `no adapter for type: ${ref.adapterType}` }\n const cfg = ref.connectionConfig ?? {}\n try {\n let sites = await adapter.discoverSites(cfg)\n if (siteIds?.length) sites = sites.filter(s => siteIds.includes(s.siteId))\n /* 아무것도 쓰기 전에 거절한다 — 한 사이트를 넘으면 \"이 현장에 더한다\" 가 성립하지 않는다. */\n const refusal = refuseImportSpace(sites.length, spaceId)\n if (refusal) return { ok: false, error: refusal.message, errorCode: refusal.code, errorParams: refusal.params }\n const instances: any[] = []\n const failed: any[] = []\n for (const site of sites) {\n try {\n const master = await adapter.fetchMaster(cfg, site)\n /* 어느 레퍼런스의 **어느 사이트**에서 왔는지 남긴다 — 다시 읽기가 같은 어댑터·같은 사이트로 돌아오려면\n 사이트 정체가 있어야 한다(`source` 는 참조 이름이라 사이트 전부에 같다). */\n const res = await TwinEngine.ingestMaster(\n domainId,\n { ...master, origin: { kind: 'reference', source, siteId: site.siteId, ...(spaceId ? { spaceId } : {}) } },\n { spaceId },\n context.state.user\n )\n if (start !== false) {\n // live=true + 어댑터가 openLiveFeed 지원 → mirror(실 이벤트 미러). 아니면 sim 기동(fallback).\n const wentLive = live ? await startReferenceLiveFeed(domainId, ref.adapterType, cfg, site, res.instanceId) : false\n if (!wentLive) await TwinEngine.startFromRegistry(domainId, res.instanceId)\n instances.push({ siteId: site.siteId, instanceId: res.instanceId, spaceId: res.spaceId, mode: wentLive ? 'live' : 'sim', warnings: res.warnings })\n } else {\n instances.push({ siteId: site.siteId, instanceId: res.instanceId, spaceId: res.spaceId, mode: 'provisioned', warnings: res.warnings })\n }\n } catch (e: any) {\n failed.push({ siteId: site.siteId, error: e?.message ?? 'failed' })\n }\n }\n // provenance — 이 레퍼런스가 만든 인스턴스 추적(scopeSpec.produced). 삭제 연쇄·상태 동기·네비게이션 근거.\n const producedNew = instances.map(i => ({ siteId: i.siteId, instanceId: i.instanceId, spaceId: i.spaceId }))\n const prev: any[] = ((ref.scopeSpec as any)?.produced ?? []).filter((p: any) => !producedNew.some(n => n.instanceId === p.instanceId))\n await repo.update(\n { id: ref.id },\n {\n status: 'connected',\n lastSyncedAt: new Date().toISOString(),\n /*\n * **영어 canonical 로 남긴다.** 이 값은 DB 에 저장되고 연결 화면이 그대로 뿌린다 — 예전에는\n * 한글 산문(`N개 사이트 실패`)이라 다섯 언어 화면에 한글이 새어 나갔다. 어댑터가 주는 사유도\n * 같은 필드에 들어오므로(그것은 원 시스템의 말이다) 키가 아니라 영어 문장으로 통일한다.\n * 어느 사이트가 왜 실패했는지는 `failed[]` 가 답한다 — 화면이 그것을 보여 준다.\n */\n lastError: failed.length ? `${failed.length} of ${sites.length} site(s) failed: ${failed.map((f: any) => f.siteId).join(', ')}` : null,\n scopeSpec: { ...((ref.scopeSpec as any) ?? {}), produced: [...prev, ...producedNew] }\n } as any\n )\n return { ok: instances.length > 0, instances, failed }\n } catch (e: any) {\n /* 레퍼런스 행에는 **영어 canonical** 을 남긴다 — 저장되는 값은 언어중립이어야 다시 읽을 수 있다. */\n await repo.update({ id: ref.id }, { status: 'error', lastError: e?.message ?? 'ingest failed' } as any)\n return refusal(context, e, 'ingest failed')\n }\n }\n}\n"]}
1
+ {"version":3,"file":"reference-resolver.js","sourceRoot":"","sources":["../../../server/service/reference/reference-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Mutation, Query, Resolver, Directive} from 'type-graphql'\n\nimport { ScalarObject, getRepository } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { readRestartPolicy } from '../../engine/restart-policy.js'\nimport { readBoardEquipment } from '@operato/twin-kernel'\n\nimport { applyKnobDefaults, filledKnobKeys } from './knob-defaults.js'\nimport type { KnobDef } from './template-registry.js'\nimport { knobDefaultsFilled, pickOriginSite, siteEquipmentAdopted } from './reference-master.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinReference } from './twin-reference.js'\nimport { listReferences, getReference } from './reference-registry.js'\nimport { getAdapter, listAdapterTypes, listAdapters } from './reference-adapter.js'\nimport {\n discovered, failed, detailOf,\n referenceNotFound, adapterUnknown, discoveryFailed, discoveryTimedOut\n} from './discovery-result.js'\nimport { refuseImportSpace } from './ingest-space.js'\nimport { startReferenceLiveFeed } from './reference-live.js'\nimport { listTemplates, getTemplate } from './template-registry.js'\n\n/*\n * Face2 레퍼런스 인제스트 채널(ADR-0018) — 등록된 레퍼런스 소스를 열거하고, 골라서 트윈으로 인제스트.\n * \"연결하고 내 것을 불러온다\" — 엔티티는 레퍼런스에서 오지 손배선/발명이 아니다.\n */\n\n/**\n * 발견 조회의 시간 상한 — 15초.\n *\n * 어댑터 계약에 시간 제한이 없다. 주소가 틀린 엔드포인트는 답하지 않고, 그러면 화면이 무한히 로딩된다 —\n * 사용자에게는 \"실패\" 보다 못한 상태다(무엇을 기다리는지 모른 채 기다린다). 실 시스템 조회가 몇 초\n * 걸리는 것은 정상이므로 넉넉히 두되, 끝은 있어야 한다.\n */\nconst DISCOVER_TIMEOUT_MS = 15_000\nconst TIMEOUT = 'discover-timeout'\n\nfunction withTimeout<T>(work: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(Object.assign(new Error('timeout'), { code: TIMEOUT })), ms)\n work.then(\n v => { clearTimeout(timer); resolve(v) },\n e => { clearTimeout(timer); reject(e) }\n )\n })\n}\n\n/**\n * 거절을 **사용자 언어로 옮겨 보낸다** — 번역은 한 곳에서 한다.\n *\n * ── 왜 서버인가 (2026-08-14) ────────────────────────────────────────────────\n * 실측: 실행 중인 트윈을 다시 프로비저닝하면 「instance \"order-check\" is running — stop before\n * re-provisioning」 이라는 **영어 한 줄이 토스트로** 떴다(다섯 언어 제품에서).\n *\n * 서버와 앱은 **같은 사전**을 쓰고, 사용자의 현재 언어가 백엔드에 반영된다. 그래서 이 문구는 서버가\n * 옮기는 것이 맞다 — 프레임워크가 이미 같은 규약이다(`authenticate-401-middleware` 가\n * `context.t('error.' + errorCode, detail)` 로 옮긴다).\n *\n * ── 그러면 코드는 왜 함께 보내나 ────────────────────────────────────────────\n * 화면이 **구조로** 다뤄야 하는 거절이 따로 있다(정합성 표의 행·심각도·수리 버튼 — 그것들은\n * `twin.compose.chk.*` 처럼 화면이 옮긴다). 그리고 브라우저가 아닌 소비자(AI·스크립트·API)에게는\n * 코드가 계약이다. 문장과 코드는 서로를 대신하지 않는다.\n *\n * **두 곳에서 같은 코드를 옮기지 않는다** — 문장이 두 벌이 되면 반드시 어긋난다.\n */\nfunction refusal(context: ResolverContext, e: any, fallback: string): Record<string, unknown> {\n const code = typeof e?.code === 'string' ? e.code : undefined\n const params = e?.params && typeof e.params === 'object' ? e.params : undefined\n /* 영어 canonical 은 항상 남긴다 — 번역 키가 없으면 그것이 보이고, 로그에는 그것이 남는다. */\n const canonical = e?.message || fallback\n const message =\n code && typeof context.t === 'function'\n ? String(context.t(`twin.provision.err.${code}`, { ...(params ?? {}), defaultValue: canonical }))\n : canonical\n return { ok: false, error: message, ...(code ? { errorCode: code } : {}), ...(params ? { errorParams: params } : {}) }\n}\n\n/**\n * `siteEquipmentIds` 노브를 이 현장의 설비로 채운다 — **비어 있을 때만.**\n *\n * 사용자가 목록을 직접 준 경우에는 손대지 않는다(고른 것이 정본이다). 현장이 없으면 채울 것도 없다.\n * 등록부의 모델에서 읽는다(런타임이 아니다) — 트윈이 도는 중이 아니어도 그 현장의 설비는 사실이다.\n */\nasync function resolveSiteEquipmentKnobs(\n knobs: readonly KnobDef[] | undefined,\n effective: Record<string, any>,\n domainId: string,\n spaceId?: string\n): Promise<{ key: string; count: number }[]> {\n const targets = (knobs ?? []).filter(k => k?.type === 'siteEquipment')\n if (!targets.length) return []\n const out: { key: string; count: number }[] = []\n let ids: { id: string; kind: string }[] | undefined\n for (const k of targets) {\n const given = effective[k.key]\n if (Array.isArray(given) && given.length) continue // 사용자가 고른 것이 정본이다\n if (!spaceId) {\n effective[k.key] = []\n continue\n }\n if (ids === undefined) {\n const rows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n const seen = new Map<string, { id: string; kind: string }>()\n for (const r of rows) {\n for (const e of readBoardEquipment((r.model as any) ?? {})) {\n if (!e?.id || seen.has(String(e.id))) continue\n seen.set(String(e.id), { id: String(e.id), kind: String((e as any).kind ?? '') })\n }\n }\n ids = [...seen.values()]\n }\n effective[k.key] = ids\n out.push({ key: k.key, count: ids.length })\n }\n return out\n}\n\n@Resolver()\nexport class TwinReferenceResolver {\n /** 등록된 레퍼런스 소스 목록(요약 + 이미 인제스트됐는지). */\n @Query(returns => [ScalarObject], { description: 'List registered reference sources (virtual or real adapters) available to ingest.' })\n async referenceSources(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const out: any[] = []\n for (const m of listReferences()) {\n const reg = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: m.source } })\n out.push({\n source: m.source,\n system: m.system,\n siteName: m.siteName,\n locationCount: m.locations.filter(l => l.role === 'location' || l.role === 'both').length,\n areaCount: m.locations.filter(l => l.role === 'area' || l.role === 'both').length,\n equipmentCount: (m.equipment ?? []).length,\n imported: !!reg,\n running: TwinEngine.owns(domainId, m.source)\n })\n }\n return out\n }\n\n /** 소스를 인제스트 → 공간 + 인스턴스 생성(provision). start 면 기동까지. */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n \"Ingest a registered reference source into a twin (space + instance). Optionally start it. restartPolicy declares how the new twin treats its own past on reboot: 'resync' (read the source again) | 'resume' (continue its journal) | 'reset' (wipe and replay from the seed). It has no default — a twin cannot exist without the declaration.\"\n })\n async importFromReference(\n @Arg('source') source: string,\n @Arg('restartPolicy') restartPolicy: string,\n @Ctx() context: ResolverContext,\n @Arg('start', { nullable: true }) start?: boolean\n ): Promise<any> {\n const master = getReference(source)\n if (!master) return { ok: false, error: `unknown reference source: ${source}` }\n const domainId = context.state.domain.id\n try {\n /* 어디서 왔는지 남긴다 — 이것이 없으면 이 트윈은 두 번 다시 읽을 수 없다.\n 이 경로는 **메모리에 등록된 마스터 하나**를 그대로 쓰므로 사이트 서술자가 없다(사이트 정체를\n 적을 것이 없다). 다시 읽기도 같은 등록본을 집으므로 사이트를 찾을 필요가 없다. */\n const res = await TwinEngine.ingestMaster(\n domainId,\n { ...master, origin: { kind: 'reference', source } },\n readRestartPolicy(restartPolicy, 'importFromReference'),\n undefined,\n context.state.user\n )\n if (start) await TwinEngine.startFromRegistry(domainId, res.instanceId)\n return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings: res.warnings }\n } catch (e: any) {\n return refusal(context, e, 'ingest failed')\n }\n }\n\n /**\n * **원본에서 다시 읽는다** — 이 트윈의 구조를 지금의 원본 모습으로 갱신한다.\n *\n * ── 왜 진입점이 하나여야 하나 ──────────────────────────────────────────────\n * 지금까지 다시 읽기는 **만드는 경로에 얹혀 있었다**(`importFromReference`·`createFromTemplate`).\n * 그래서 이미 있는 트윈을 갱신하려면 만들 때 무엇을 골랐는지 사람이 기억해 같은 화면을 다시\n * 거쳐야 했고, 템플릿으로 세운 트윈은 노브를 어디에도 안 남겨서 **아예 갱신할 방법이 없었다.**\n * 원천이 무엇이든 트윈 자신이 기억하게 하고(`TwinInstance.origin`), 여기 한 곳에서 그것을 따른다.\n *\n * ── 무엇이 일어나나 ────────────────────────────────────────────────────────\n * 원본에서 마스터를 다시 얻어 인제스트에 그대로 태운다. 그다음은 인제스트가 아는 일이다 —\n * 구조가 달라졌으면 새 리비전이 남고, 구조 행이 다시 그려지고, **실행 중인 미러는 멈추지 않고\n * 전환한다.** 실행 중인 시뮬레이션은 거절된다(조건이 바뀐 실험은 다른 실험이다).\n *\n * ── 못 할 때는 못 한다고 한다 ──────────────────────────────────────────────\n * `origin` 이 없는 트윈(이 자리가 생기기 전에 만들어진 것)은 다시 읽을 수 없다. 짐작으로\n * 템플릿을 고르거나 첫 레퍼런스를 집지 않는다 — 엉뚱한 원본으로 현장을 덮는 것이 훨씬 나쁘다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n \"Re-read a twin's structure from the source it remembers (TwinInstance.origin). Works for both reference- and template-born twins. A running mirror adopts the new structure without stopping; a running simulation is refused.\"\n })\n async resyncTwin(@Arg('instanceId') instanceId: string, @Ctx() context: ResolverContext): Promise<any> {\n const domainId = context.state.domain.id\n const inst = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!inst) return { ok: false, error: `unknown twin: ${instanceId}` }\n\n const origin = inst.origin as any\n if (!origin?.kind)\n return {\n ok: false,\n error: `twin \"${instanceId}\" does not remember where it came from — it cannot be re-read. Re-create it from its template or reference so the origin is recorded.`\n }\n\n try {\n const master = await this.masterFromOrigin(domainId, origin, instanceId)\n /*\n * **어느 현장의 트윈이었나를 지킨다** — 다시 읽기는 구조만 새로 그리는 일이고, 현장 소속은 그때\n * 사람이 고른 것이다. 기억이 없는 옛 트윈은 **지금 있는 현장**을 그대로 쓴다(빈손으로 두면 템플릿\n * 기본 공간으로 옮겨 간다 — 조용히 현장을 떠나고 그 현장의 값도 잃는다).\n */\n const keepSpace = origin.spaceId || inst.spaceId\n /* 다시 읽기는 **구조만** 새로 그린다 — 재기동 정책은 그 트윈의 선언이므로 그대로 지킨다. */\n const res = await TwinEngine.ingestMaster(\n domainId,\n master,\n readRestartPolicy(inst.restartPolicy, `resync of twin \"${instanceId}\"`),\n keepSpace ? { spaceId: keepSpace } : undefined,\n context.state.user\n )\n return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings: res.warnings }\n } catch (e: any) {\n return refusal(context, e, 'resync failed')\n }\n }\n\n /** 기억해 둔 원천에서 마스터를 다시 얻는다 — 어댑터든 템플릿이든 이 한 곳에서 갈린다. */\n private async masterFromOrigin(domainId: string, origin: any, instanceId: string): Promise<any> {\n if (origin.kind === 'template') {\n const tpl = getTemplate(origin.templateId)\n if (!tpl) throw new Error(`unknown template: ${origin.templateId} — this twin cannot be rebuilt`)\n /* 저장해 둔 노브 그대로 다시 짓는다. 기본값을 다시 입히지 않는다 — 그 사이 템플릿의 기본값이\n 바뀌었다면, 사용자가 고르지 않은 값이 조용히 현장을 바꾸게 된다. */\n const { master } = tpl.build(origin.params ?? {})\n master.origin = origin\n return master\n }\n\n /* 레퍼런스 — 메모리 등록본이 있으면 그것, 없으면 저장된 어댑터 연결로 다시 가져온다.\n (부팅 뒤에는 메모리 등록본이 비어 있으므로 어댑터 경로가 실제로 쓰이는 길이다.) */\n const inMemory = getReference(origin.source)\n if (inMemory) return { ...inMemory, origin }\n\n const ref = await getRepository(TwinReference).findOne({ where: { domain: { id: domainId }, source: origin.source } })\n if (!ref) throw new Error(`reference \"${origin.source}\" is no longer registered — nothing to re-read from`)\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) throw new Error(`no adapter for type: ${ref.adapterType}`)\n const cfg = ref.connectionConfig ?? {}\n const sites = await adapter.discoverSites(cfg)\n\n /*\n * ── 무엇을 무엇과 견주나 (2026-08-18 실측으로 고침) ────────────────────────\n *\n * 예전에는 `master.source === origin.source` 로 사이트를 찾았다. 그런데 `origin.source` 는 **레퍼런스\n * 등록 이름**이고(그 참조의 사이트 전부에 같다) `master.source` 는 **사이트별 인스턴스 id** 다 —\n * 서로 다른 것을 견줬으니 사이트가 멀쩡히 있어도 「더 이상 보고하지 않는다」로 거절했다. 사이트가\n * 여럿인 참조에서 온 트윈은 그래서 **전부** 재동기가 불가했고, 오류 문장은 원인을 참조 쪽으로\n * 잘못 가리켰다.\n *\n * 이제 ① 기억해 둔 사이트로 곧장 간다(`origin.siteId`) ② 기억이 없는 옛 트윈은 사이트를 살펴\n * **마스터의 정체(=이 인스턴스 id)** 와 견준다. 어느 쪽도 못 찾으면 **첫 사이트로 때우지 않는다** —\n * 다른 현장의 구조를 이 트윈에 덮는 것은 오류가 아니라 조용히 틀린 공장으로 나타난다.\n */\n const picked = pickOriginSite(sites, origin)\n if (picked.site) return { ...(await adapter.fetchMaster(cfg, picked.site)), origin }\n if (picked.reason === 'site-gone')\n throw new Error(\n `reference \"${origin.source}\" no longer reports site \"${origin.siteId}\" — refusing to overwrite this twin with a different site`\n )\n\n for (const site of sites) {\n const master = await adapter.fetchMaster(cfg, site)\n if (master.source === instanceId) return { ...master, origin: { ...origin, siteId: site.siteId } }\n }\n throw new Error(\n `reference \"${origin.source}\" does not report a site that rebuilds twin \"${instanceId}\" ` +\n `(this twin was imported before the site identity was recorded, and no site's master carries its id) — refusing to overwrite it with a different site`\n )\n }\n\n /** 등록된 트윈 템플릿(파라미터화 아키타입) 목록 — 노브 스키마 포함(클라이언트 폼용). */\n @Query(returns => [ScalarObject], { description: 'List registered twin templates (parameterized archetypes) with their knob schema.' })\n async twinTemplates(@Ctx() _context: ResolverContext): Promise<any[]> {\n return listTemplates().map(t => ({ id: t.id, label: t.label, system: t.system, description: t.description, detail: t.detail, knobs: t.knobs }))\n }\n\n /** 템플릿 + 노브 → 합성 마스터 → 인제스트(+기동+시나리오). 레퍼런스 import 와 같은 경로, 원천만 합성. */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n \"Instantiate a twin template with params → synthetic master → ingest (+start+scenario). restartPolicy declares how the new twin treats its own past on reboot ('resync' | 'resume' | 'reset') — there is no default. Returns {ok, instanceId, spaceId}.\"\n })\n async createFromTemplate(\n @Arg('templateId') templateId: string,\n @Arg('params', type => ScalarObject) params: any,\n @Arg('restartPolicy') restartPolicy: string,\n @Ctx() context: ResolverContext,\n @Arg('start', { nullable: true }) start?: boolean,\n @Arg('spaceId', { nullable: true, description: 'Existing space to co-locate this twin into (add a lens to a site). Omit to create its own space.' }) spaceId?: string\n ): Promise<any> {\n const tpl = getTemplate(templateId)\n if (!tpl) return { ok: false, error: `unknown template: ${templateId}` }\n const domainId = context.state.domain.id\n try {\n /*\n * **빠진 노브를 서버가 채운다.** 기본값을 아는 곳은 노브 스키마(계약)인데 그것을 적용하는 곳이\n * 위자드뿐이었다 — 그래서 화면을 거치지 않는 호출자(AI·스크립트·API)가 파라미터를 일부만 주면\n * 템플릿 안에서 발생률이 0 이 되고 **아무것도 하지 않는 트윈**이 조용히 만들어졌다.\n * 채운 노브 이름은 경고로 함께 돌려준다 — 조용히 채우는 것도 조용히 비우는 것만큼 위험하다.\n */\n const filled = filledKnobKeys(tpl.knobs, params)\n const effective = applyKnobDefaults(tpl.knobs, params)\n /*\n * **이 현장에 이미 있는 설비를 노브 값으로 확정한다** (`siteEquipmentIds`).\n *\n * 에너지 트윈이 「공장이 돌면 전기가 오른다」를 말하려면 부하를 **이웃 트윈의 설비 id 로**\n * 선언해야 한다(설비 하나에 사실 둘). 그 목록을 빌드할 때마다 현장에서 다시 읽으면, 사이에\n * 설비가 늘거나 준 만큼 **다시 지을 때 다른 트윈**이 된다. 그래서 여기서 한 번 해석하고\n * 그 결과를 노브 값으로 남긴다(아래 `origin.params` 에 그대로 저장된다).\n */\n const adopted = await resolveSiteEquipmentKnobs(tpl.knobs, effective, domainId, spaceId)\n const { master, scenario } = tpl.build(effective)\n /* **무엇으로 지었는지 남긴다.** 합성은 결정적이므로 같은 노브면 같은 마스터가 다시 나온다 —\n 그래서 템플릿 트윈도 어댑터 트윈과 똑같이 다시 읽을 수 있다. 남기지 않으면 그 트윈은\n 첫날의 모습에 영원히 머문다(원본을 잃은 트윈). */\n /* 고른 현장도 남긴다 — 없으면 다시 읽기가 트윈을 템플릿 기본 공간으로 옮겨 버린다(현장 값도 잃는다). */\n master.origin = { kind: 'template', templateId, params: effective, ...(spaceId ? { spaceId } : {}) }\n /* 공간 선택은 템플릿을 거치지 않는다 — 템플릿마다 이 노브를 알고 있어야 한다면 새 템플릿이\n 조용히 무시하게 된다. 합성된 마스터에 한 곳에서 얹는다(레퍼런스 인제스트와 같은 경로). */\n const res = await TwinEngine.ingestMaster(\n domainId,\n master,\n readRestartPolicy(restartPolicy, `createFromTemplate(\"${templateId}\")`),\n { spaceId },\n context.state.user\n )\n if (start !== false) {\n await TwinEngine.startFromRegistry(domainId, res.instanceId)\n if (scenario) {\n const runtime = TwinEngine.runtime(domainId, res.instanceId)\n if (runtime) {\n runtime.scenario.load(scenario)\n runtime.scenario.start()\n }\n }\n }\n const warnings = [\n ...(filled.length ? [knobDefaultsFilled(filled)] : []),\n ...adopted.filter(a => a.count > 0).map(a => siteEquipmentAdopted(a.key, a.count)),\n ...res.warnings\n ]\n return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings }\n } catch (e: any) {\n return refusal(context, e, 'template instantiation failed')\n }\n }\n\n /* ── 레퍼런스 관리(엔티티 기반·테넌트 스코프) — reference-management P1 ────────\n * 전역 인메모리(referenceSources/importFromReference)와 공존. 이쪽은 TwinReference 행 + 어댑터 레지스트리.\n */\n\n @Query(returns => [ScalarObject], { description: 'List tenant-scoped persisted twin references (adapter-backed).' })\n async twinReferences(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const rows = await getRepository(TwinReference).find({ where: { domain: { id: domainId } } })\n // provenance 라이브 대조 — 지워진 트윈은 producedCount 에서 자동 제외(상태 동기의 lazy 방식).\n const liveIds = new Set((await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId))\n return rows.map(r => {\n const produced = (((r.scopeSpec as any)?.produced ?? []) as any[]).filter(p => liveIds.has(p.instanceId))\n return {\n source: r.source, system: r.system, siteName: r.siteName, description: r.description,\n adapterType: r.adapterType, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError,\n producedCount: produced.length, produced\n }\n })\n }\n\n @Query(returns => [String], { description: 'List registered reference adapter type keys.' })\n referenceAdapterTypes(): string[] {\n return listAdapterTypes()\n }\n\n /**\n * 인티그레이션 그룹핑 (reference-management §2.3·D11) — 산출물을 커넥터 타입 ▸ Connection ▸ 인스턴스 2단으로.\n * 트윈-네이티브 온톨로지(integration 무의존): TwinReference 가 그룹핑 노드(source=connectionName),\n * scopeSpec.connectorType 로 상위 분류. producedCount 는 라이브 인스턴스로 대조(지워진 트윈 제외).\n */\n @Query(returns => [ScalarObject], { description: 'Group integration items 2-tier: connector type ▸ connection ▸ produced twins. (reference-management §2.3)' })\n async twinConnections(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const rows = await getRepository(TwinReference).find({ where: { domain: { id: domainId } } })\n const liveIds = new Set((await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId))\n const groups = new Map<string, any[]>()\n for (const r of rows) {\n const connectorType = (r.scopeSpec as any)?.connectorType ?? r.adapterType\n const producedCount = (((r.scopeSpec as any)?.produced ?? []) as any[]).filter(p => liveIds.has(p.instanceId)).length\n const conn = { source: r.source, name: r.siteName, status: r.status, adapterType: r.adapterType, producedCount, lastSyncedAt: r.lastSyncedAt }\n if (!groups.has(connectorType)) groups.set(connectorType, [])\n groups.get(connectorType)!.push(conn)\n }\n return [...groups.entries()].map(([connectorType, connections]) => ({\n connectorType,\n connectionCount: connections.length,\n instanceCount: connections.reduce((s, c) => s + c.producedCount, 0),\n connections\n }))\n }\n\n /** 한 Connection 그룹 노드 상세 — 그 아래 생성된 트윈 인스턴스(라이브 대조·상태·기동여부). */\n @Query(returns => ScalarObject, { nullable: true, description: 'One connection grouping location with its produced twin instances (live-checked). (reference-management §2.3)' })\n async twinConnection(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const domainId = context.state.domain.id\n const r = await getRepository(TwinReference).findOne({ where: { domain: { id: domainId }, source } })\n if (!r) return null\n const produced = ((r.scopeSpec as any)?.produced ?? []) as any[]\n const instMap = new Map((await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => [i.instanceId, i]))\n const instances = produced\n .filter(p => instMap.has(p.instanceId))\n .map(p => {\n const inst = instMap.get(p.instanceId) as any\n return { instanceId: p.instanceId, spaceId: p.spaceId, siteId: p.siteId, kind: inst.kind, status: inst.status, running: TwinEngine.owns(domainId, p.instanceId) }\n })\n return {\n source: r.source,\n connectorType: (r.scopeSpec as any)?.connectorType ?? r.adapterType,\n name: r.siteName,\n status: r.status,\n system: r.system,\n lastSyncedAt: r.lastSyncedAt,\n instanceCount: instances.length,\n instances\n }\n }\n\n /** 단건 상세(뷰/편집) — connectionConfig 포함, 어댑터 스키마의 secret 필드는 마스킹(있으면 '••••••'). */\n @Query(returns => ScalarObject, { nullable: true, description: 'Get one tenant-scoped reference with its connection config (secret fields masked) for view/edit.' })\n async twinReference(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const r = await getRepository(TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } })\n if (!r) return null\n const secretKeys = new Set((getAdapter(r.adapterType)?.meta?.configSchema ?? []).filter(f => f.secret).map(f => f.key))\n const cfg: any = {}\n for (const [k, v] of Object.entries((r.connectionConfig as any) ?? {})) cfg[k] = secretKeys.has(k) ? (v ? '••••••' : '') : v\n return {\n source: r.source, system: r.system, siteName: r.siteName, description: r.description,\n adapterType: r.adapterType, connectionConfig: cfg, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError\n }\n }\n\n @Query(returns => [ScalarObject], { description: 'List reference connector metadata (label, domain, config schema, availability) for the connect UI.' })\n referenceAdapters(): any[] {\n return listAdapters().map(a => ({ type: a.type, ...(a.meta ?? {}) }))\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Create or update a tenant-scoped twin reference (persisted).' })\n async saveTwinReference(\n @Arg('source') source: string,\n @Arg('patch', type => ScalarObject) patch: any,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinReference)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, source } })\n const saved = await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n source,\n system: patch.system ?? existing?.system,\n siteName: patch.siteName ?? existing?.siteName,\n description: patch.description ?? existing?.description,\n adapterType: patch.adapterType ?? existing?.adapterType,\n // 필드 단위 병합 — 편집 시 생략된 키(예: 마스킹된 secret)는 기존 값 유지.\n connectionConfig: patch.connectionConfig\n ? { ...((existing?.connectionConfig as any) ?? {}), ...patch.connectionConfig }\n : existing?.connectionConfig,\n mappingSpec: patch.mappingSpec ?? existing?.mappingSpec,\n scopeSpec: patch.scopeSpec ?? existing?.scopeSpec,\n status: patch.status ?? existing?.status ?? 'draft'\n })\n )\n return { ok: true, source: saved.source }\n }\n\n /** 연결 해제 — removeTwins=true 면 이 레퍼런스가 만든 트윈(provenance)도 함께 제거(라이프사이클 연쇄). 기본은 트윈 보존(분리). */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a tenant-scoped reference. If removeTwins, also remove the twin instances it produced (provenance cascade); otherwise twins are kept (detached).' })\n async deleteTwinReference(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('removeTwins', { nullable: true }) removeTwins?: boolean\n ): Promise<boolean> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: domainId }, source } })\n if (removeTwins && ref) {\n for (const p of (((ref.scopeSpec as any)?.produced ?? []) as any[])) {\n try {\n await TwinEngine.remove(domainId, p.instanceId)\n } catch {\n /* 이미 없거나 실패 — 연쇄는 best-effort. */\n }\n }\n }\n await repo.delete({ domain: { id: domainId } as any, source })\n return true\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Test a reference connection via its adapter; updates status.' })\n async testReferenceConnection(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any> {\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: context.state.domain.id }, source } })\n if (!ref) return { ok: false, error: `unknown reference: ${source}` }\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) return { ok: false, error: `no adapter for type: ${ref.adapterType}` }\n try {\n const res = await adapter.testConnection(ref.connectionConfig ?? {})\n await repo.update({ id: ref.id }, { status: res.ok ? 'connected' : 'error', lastError: res.error ?? null } as any)\n return res\n } catch (e: any) {\n return { ok: false, error: e?.message ?? 'test failed' }\n }\n }\n\n /**\n * 어댑터 기반 인제스트 — discoverSites → 사이트별 fetchMaster → ingestMaster (fan-out, §2.2·§4.2).\n * P1 은 대개 N=1(virtual/단일). start 면 각 인스턴스 기동. 라이브 피드·mode 는 face2-inbound-live 소유.\n */\n /** 레퍼런스가 노출하는 사이트/공장 발견 — 트윈 생성 시 \"어느 공장\" 선택용(§2.2). */\n @Query(returns => ScalarObject, { description: 'Discover sites/factories exposed by a reference. Returns { sites, error? } — an empty list with no error means the system genuinely has none, which is different from a failure.' })\n async discoverReferenceSites(@Arg('source') source: string, @Ctx() context: ResolverContext): Promise<any> {\n /*\n * **\"못 찾았다\" 와 \"없다\" 를 구분한다.** 예전에는 넷을 빈 배열 하나로 접었고(레퍼런스 없음·어댑터\n * 미상·조회 실패·정말 0건), 화면은 그 모두를 \"사이트를 찾지 못했습니다\" 라고만 말했다. 실 시스템\n * 연결에서 가장 자주 막히는 자리인데 자격이 틀렸는지 주소가 틀렸는지 알 수 없었다.\n * 판정과 문장 형태는 `discovery-result`(순수)가 갖는다.\n */\n const ref = await getRepository(TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } })\n if (!ref) return failed(referenceNotFound(source))\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) return failed(adapterUnknown(ref.adapterType, source))\n try {\n /*\n * **기다려도 답이 없으면 사유를 준다.** 어댑터 계약에 시간 제한이 없어서, 주소가 틀린 엔드포인트는\n * 화면을 무한히 돌게 만들었다 — 무한히 도는 화면은 조용한 실패의 다른 얼굴이다.\n * 상한은 여기서 정한다(어댑터마다 다르게 두면 사용자가 어느 것을 기다리는지 알 수 없다).\n */\n const sites = await withTimeout(adapter.discoverSites(ref.connectionConfig ?? {}), DISCOVER_TIMEOUT_MS)\n return discovered(sites)\n } catch (e: any) {\n if (e?.code === TIMEOUT) return failed(discoveryTimedOut(source, DISCOVER_TIMEOUT_MS / 1000))\n return failed(discoveryFailed(source, detailOf(e)))\n }\n }\n\n /**\n * 트윈 생성 — 레퍼런스에서 사이트 발견 → (siteIds 있으면 그 공장만) → fetchMaster → provision. 사이트별 resilient.\n * 여러 공장을 관할하는 소스는 siteIds 로 \"어느 공장\"을 골라 생성(1:N, §2.1·§2.2).\n *\n * ── 현장 선택이 이 경로에도 있다 (2026-08-13) ────────────────────────────\n * 한 현실을 여러 렌즈가 비춘다(WMS·MES·YMS). 그런데 **그 선택이 템플릿 경로에만** 있어서\n * (`createFromTemplate(spaceId)`), 실 시스템에서 가져온 트윈은 어댑터가 파생한 공간 id 가 우연히\n * 일치할 때만 한 현장에 모였다 — 사람이 \"이 MES 와 같은 현장에 넣어라\" 를 말할 방법이 없었다.\n * 데이터로는 가능한 일이 저작으로는 불가능한, `ingest-space` 가 이미 지적한 그 비대칭이다.\n *\n * 판정은 그 순수 모듈이 갖는다: 없는 공간은 거절(`resolveIngestSpace`), 사이트 여럿을 한 공간에\n * 넣는 것도 거절(`refuseImportSpace`) — 서로 다른 현장이 조용히 합쳐지는 것을 막는다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n \"Create twins from a reference: discover sites → filter by siteIds (if given) → fetch master(s) → provision. spaceId co-locates the twin into an existing space (one site only). start=false to only provision; live=true to run as a mirror (adapter openLiveFeed → live projector) instead of sim. restartPolicy declares how each new twin treats its own past on reboot ('resync' | 'resume' | 'reset'); omit it and live=true implies 'resync' — a mirror reads the source again — while a simulation must declare 'resume' or 'reset' for itself.\"\n })\n async importTwinReference(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('siteIds', type => [String], { nullable: true }) siteIds?: string[],\n @Arg('start', { nullable: true }) start?: boolean,\n @Arg('live', { nullable: true }) live?: boolean,\n @Arg('spaceId', { nullable: true, description: 'Existing space to co-locate this twin into (add a lens to a site). Only when importing a single site. Omit to give each site its own space.' }) spaceId?: string,\n @Arg('restartPolicy', { nullable: true, description: \"How each new twin treats its own past on reboot: 'resync' | 'resume' | 'reset'. Required unless live=true (a mirror is 'resync' by definition).\" }) restartPolicy?: string\n ): Promise<any> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinReference)\n const ref = await repo.findOne({ where: { domain: { id: domainId }, source } })\n if (!ref) return { ok: false, error: `unknown reference: ${source}` }\n const adapter = getAdapter(ref.adapterType)\n if (!adapter) return { ok: false, error: `no adapter for type: ${ref.adapterType}` }\n const cfg = ref.connectionConfig ?? {}\n try {\n let sites = await adapter.discoverSites(cfg)\n if (siteIds?.length) sites = sites.filter(s => siteIds.includes(s.siteId))\n /* 아무것도 쓰기 전에 거절한다 — 한 사이트를 넘으면 \"이 현장에 더한다\" 가 성립하지 않는다. */\n const refusal = refuseImportSpace(sites.length, spaceId)\n if (refusal) return { ok: false, error: refusal.message, errorCode: refusal.code, errorParams: refusal.params }\n const instances: any[] = []\n const failed: any[] = []\n for (const site of sites) {\n try {\n const master = await adapter.fetchMaster(cfg, site)\n /* 어느 레퍼런스의 **어느 사이트**에서 왔는지 남긴다 — 다시 읽기가 같은 어댑터·같은 사이트로 돌아오려면\n 사이트 정체가 있어야 한다(`source` 는 참조 이름이라 사이트 전부에 같다). */\n /*\n * 정책은 **선언이거나 의도에서 곧바로 따라오는 것**이다: `live=true` 는 미러를 띄우겠다는 뜻이고\n * 미러는 정의상 `resync` 다(외부가 진실이므로 우리 과거를 이어 붙이지 않는다). 시뮬로 띄우려면\n * 스스로 선언해야 한다 — 그 자리에서 우리가 고르면 재기동마다 이력을 지우는 트윈이 조용히 생긴다.\n */\n const policy = readRestartPolicy(restartPolicy ?? (live ? 'resync' : undefined), `importTwinReference(\"${source}\")`)\n const res = await TwinEngine.ingestMaster(\n domainId,\n { ...master, origin: { kind: 'reference', source, siteId: site.siteId, ...(spaceId ? { spaceId } : {}) } },\n policy,\n { spaceId },\n context.state.user\n )\n if (start !== false) {\n // live=true + 어댑터가 openLiveFeed 지원 → mirror(실 이벤트 미러). 아니면 sim 기동(fallback).\n const wentLive = live ? await startReferenceLiveFeed(domainId, ref.adapterType, cfg, site, res.instanceId) : false\n if (!wentLive) await TwinEngine.startFromRegistry(domainId, res.instanceId)\n instances.push({ siteId: site.siteId, instanceId: res.instanceId, spaceId: res.spaceId, mode: wentLive ? 'live' : 'sim', warnings: res.warnings })\n } else {\n instances.push({ siteId: site.siteId, instanceId: res.instanceId, spaceId: res.spaceId, mode: 'provisioned', warnings: res.warnings })\n }\n } catch (e: any) {\n failed.push({ siteId: site.siteId, error: e?.message ?? 'failed' })\n }\n }\n // provenance — 이 레퍼런스가 만든 인스턴스 추적(scopeSpec.produced). 삭제 연쇄·상태 동기·네비게이션 근거.\n const producedNew = instances.map(i => ({ siteId: i.siteId, instanceId: i.instanceId, spaceId: i.spaceId }))\n const prev: any[] = ((ref.scopeSpec as any)?.produced ?? []).filter((p: any) => !producedNew.some(n => n.instanceId === p.instanceId))\n await repo.update(\n { id: ref.id },\n {\n status: 'connected',\n lastSyncedAt: new Date().toISOString(),\n /*\n * **영어 canonical 로 남긴다.** 이 값은 DB 에 저장되고 연결 화면이 그대로 뿌린다 — 예전에는\n * 한글 산문(`N개 사이트 실패`)이라 다섯 언어 화면에 한글이 새어 나갔다. 어댑터가 주는 사유도\n * 같은 필드에 들어오므로(그것은 원 시스템의 말이다) 키가 아니라 영어 문장으로 통일한다.\n * 어느 사이트가 왜 실패했는지는 `failed[]` 가 답한다 — 화면이 그것을 보여 준다.\n */\n lastError: failed.length ? `${failed.length} of ${sites.length} site(s) failed: ${failed.map((f: any) => f.siteId).join(', ')}` : null,\n scopeSpec: { ...((ref.scopeSpec as any) ?? {}), produced: [...prev, ...producedNew] }\n } as any\n )\n return { ok: instances.length > 0, instances, failed }\n } catch (e: any) {\n /* 레퍼런스 행에는 **영어 canonical** 을 남긴다 — 저장되는 값은 언어중립이어야 다시 읽을 수 있다. */\n await repo.update({ id: ref.id }, { status: 'error', lastError: e?.message ?? 'ingest failed' } as any)\n return refusal(context, e, 'ingest failed')\n }\n }\n}\n"]}
@@ -8,6 +8,23 @@ export type CommandAuditInput = {
8
8
  errorCode?: string;
9
9
  error?: string;
10
10
  };
11
+ /**
12
+ * **원본(어댑터)이 준 답** — 허락과 일어남 사이에 끼어 있는 것을 같은 기록에 닫는다 (ADR-0029 §1 결정 C).
13
+ *
14
+ * ── 왜 이 칸이 필요한가 ──────────────────────────────────────────────────
15
+ * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 조용히 실패하면 원장에는 승인만
16
+ * 남는다. 그래서 어댑터의 답을 **같은 행**에 되적는다.
17
+ *
18
+ * 셋을 구별한다:
19
+ * · 없음(`undefined`) — **원본에 묻지 않았다**(커널이 받은 명령이다). 「모른다」와 다르다.
20
+ * · `{ answered: false }` — 물었는데 **답을 못 받았다** → `unknown` 으로 남긴다. 성공으로 적지 않는다.
21
+ * · `{ answered: true, ok, code? }` — 원본이 답했다(적용·거절 모두 사실이다).
22
+ */
23
+ source?: {
24
+ answered: boolean;
25
+ ok?: boolean;
26
+ code?: string;
27
+ };
11
28
  /** 세션이 아는 사용자 — **서버만 채운다.** */
12
29
  actor?: {
13
30
  id?: string;
@@ -29,9 +46,26 @@ export type CommandAuditRow = {
29
46
  actorName?: string;
30
47
  accepted: boolean;
31
48
  errorCode?: string;
49
+ /**
50
+ * 원본이 그래서 어떻게 했나 — `applied` · `refused` · `unknown`(물었지만 답이 없다).
51
+ * **없으면 묻지 않은 것이다**(커널이 받은 명령). 0 이나 성공으로 채우지 않는다.
52
+ */
53
+ sourceOutcome?: 'applied' | 'refused' | 'unknown';
54
+ /** 원본이 준 사유 코드 — 있으면 그대로. 우리가 지어내지 않는다. */
55
+ sourceCode?: string;
32
56
  args?: any;
33
57
  argsTruncated: boolean;
34
58
  };
35
59
  /** 신뢰할 수 있는 출처 표기로 정규화 — 모르는 값은 지어내지 않고 'unknown' 으로 둔다. */
36
60
  export declare function normalizeOrigin(v: unknown): CommandOrigin;
37
61
  export declare function buildCommandAudit(input: CommandAuditInput): CommandAuditRow;
62
+ /**
63
+ * 원본의 답을 세 값으로 — **답이 없으면 `unknown`**(성공으로 적지 않는다).
64
+ *
65
+ * 이 함수가 있는 이유: 「물었지만 답이 없다」를 실패로도 성공으로도 적을 수 없다. 실패로 적으면 일어난 일을
66
+ * 없던 일로 만들고, 성공으로 적으면 없던 일을 일어난 일로 만든다. 셋째 값이 사실이다.
67
+ */
68
+ export declare function sourceOutcomeOf(source: {
69
+ answered: boolean;
70
+ ok?: boolean;
71
+ }): 'applied' | 'refused' | 'unknown';
@@ -13,6 +13,7 @@
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.normalizeOrigin = normalizeOrigin;
15
15
  exports.buildCommandAudit = buildCommandAudit;
16
+ exports.sourceOutcomeOf = sourceOutcomeOf;
16
17
  /** 신뢰할 수 있는 출처 표기로 정규화 — 모르는 값은 지어내지 않고 'unknown' 으로 둔다. */
17
18
  function normalizeOrigin(v) {
18
19
  return v === 'user' || v === 'ai' || v === 'automation' ? v : 'unknown';
@@ -20,7 +21,7 @@ function normalizeOrigin(v) {
20
21
  /** args 직렬화 상한(문자). 넘으면 자르되 잘랐다고 표시한다. */
21
22
  const ARGS_MAX = 4000;
22
23
  function buildCommandAudit(input) {
23
- const { command, ack, actor, at } = input;
24
+ const { command, ack, actor, at, source } = input;
24
25
  const argsText = safeJson(command?.args);
25
26
  const truncated = argsText !== null && argsText.length > ARGS_MAX;
26
27
  return {
@@ -29,6 +30,8 @@ function buildCommandAudit(input) {
29
30
  commandType: str(command?.type),
30
31
  origin: normalizeOrigin(command?.origin),
31
32
  reason: str(command?.reason),
33
+ /* 원본의 답 — 묻지 않았으면 칸을 만들지 않는다(모름과 구별한다). */
34
+ ...(source ? { sourceOutcome: sourceOutcomeOf(source), ...(source.code ? { sourceCode: source.code } : {}) } : {}),
32
35
  /* 신원 — 세션 값만. 커맨드에 실려 온 신원 주장은 쳐다보지 않는다. */
33
36
  actorId: str(actor?.id),
34
37
  actorEmail: str(actor?.email),
@@ -50,4 +53,15 @@ function safeJson(v) {
50
53
  return null; /* 순환 참조 등 — 못 재면 자르지 않는다(원본을 그대로 둔다) */
51
54
  }
52
55
  }
56
+ /**
57
+ * 원본의 답을 세 값으로 — **답이 없으면 `unknown`**(성공으로 적지 않는다).
58
+ *
59
+ * 이 함수가 있는 이유: 「물었지만 답이 없다」를 실패로도 성공으로도 적을 수 없다. 실패로 적으면 일어난 일을
60
+ * 없던 일로 만들고, 성공으로 적으면 없던 일을 일어난 일로 만든다. 셋째 값이 사실이다.
61
+ */
62
+ function sourceOutcomeOf(source) {
63
+ if (!source.answered || typeof source.ok !== 'boolean')
64
+ return 'unknown';
65
+ return source.ok ? 'applied' : 'refused';
66
+ }
53
67
  //# sourceMappingURL=command-audit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-audit.js","sourceRoot":"","sources":["../../../server/service/twin-audit/command-audit.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAgCH,0CAEC;AAKD,8CAqBC;AA7BD,4DAA4D;AAC5D,SAAgB,eAAe,CAAC,CAAU;IACxC,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACzE,CAAC;AAED,0CAA0C;AAC1C,MAAM,QAAQ,GAAG,IAAI,CAAA;AAErB,SAAgB,iBAAiB,CAAC,KAAwB;IACxD,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,KAAK,CAAA;IACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACxC,MAAM,SAAS,GAAG,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAA;IACjE,OAAO;QACL,SAAS,EAAE,EAAE;QACb,SAAS,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC;QAClC,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC;QAC/B,MAAM,EAAE,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC;QACxC,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC;QAC5B,4CAA4C;QAC5C,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;QACvB,UAAU,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;QAC7B,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC;QAC3B,uDAAuD;QACvD,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ;QACzB,SAAS,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC;QAC9B,4CAA4C;QAC5C,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,QAAS,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,SAAS;QAC3E,aAAa,EAAE,SAAS;KACzB,CAAA;AACH,CAAC;AAED,MAAM,GAAG,GAAG,CAAC,CAAU,EAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;AAE5F,SAAS,QAAQ,CAAC,CAAU;IAC1B,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA,CAAC,wCAAwC;IACtD,CAAC;AACH,CAAC","sourcesContent":["/*\n * 커맨드 감사 기록 만들기 (순수) — **누가 무엇을 허락했고, 그래서 어떻게 됐나.**\n *\n * 승인 게이트가 앞을 막고, 이 기록이 뒤를 설명한다. 둘 다 있어야 \"사람 손을 거쳤다\" 를 증명할 수 있다.\n *\n * 무엇을 믿는가가 이 기록의 전부다:\n * · **신원·시각은 서버가 준다.** 클라이언트가 말한 신원을 그대로 적으면 위조가 자유로워 아무것도\n * 증명하지 못한다. 세션이 아는 사용자와 서버 시각만 쓴다.\n * · **의도는 클라이언트가 준다** — 출처(origin)·근거(reason). 서버가 알 수 없는 정보이고,\n * 위조되더라도 신원 증명을 훼손하지 않는다.\n */\n\nexport type CommandOrigin = 'user' | 'ai' | 'automation' | 'unknown'\n\nexport type CommandAuditInput = {\n /** 클라이언트가 실어 보낸 커맨드(신뢰하지 않는 부분을 포함한 원본). */\n command: any\n /** 커널 판정. */\n ack: { accepted?: boolean; errorCode?: string; error?: string }\n /** 세션이 아는 사용자 — **서버만 채운다.** */\n actor?: { id?: string; email?: string; name?: string }\n /** 서버 시각. 호출부가 주입해 테스트가 시간을 고정할 수 있게 한다. */\n at: Date\n}\n\n/** `TwinAuditEvent` 에 그대로 넣을 수 있는 모양(엔티티를 몰라도 되게 순수하게 둔다). */\nexport type CommandAuditRow = {\n eventTime: Date\n commandId?: string\n commandType?: string\n origin: CommandOrigin\n reason?: string\n actorId?: string\n actorEmail?: string\n actorName?: string\n accepted: boolean\n errorCode?: string\n args?: any\n argsTruncated: boolean\n}\n\n/** 신뢰할 수 있는 출처 표기로 정규화 — 모르는 값은 지어내지 않고 'unknown' 으로 둔다. */\nexport function normalizeOrigin(v: unknown): CommandOrigin {\n return v === 'user' || v === 'ai' || v === 'automation' ? v : 'unknown'\n}\n\n/** args 직렬화 상한(문자). 넘으면 자르되 잘랐다고 표시한다. */\nconst ARGS_MAX = 4000\n\nexport function buildCommandAudit(input: CommandAuditInput): CommandAuditRow {\n const { command, ack, actor, at } = input\n const argsText = safeJson(command?.args)\n const truncated = argsText !== null && argsText.length > ARGS_MAX\n return {\n eventTime: at,\n commandId: str(command?.commandId),\n commandType: str(command?.type),\n origin: normalizeOrigin(command?.origin),\n reason: str(command?.reason),\n /* 신원 — 세션 값만. 커맨드에 실려 온 신원 주장은 쳐다보지 않는다. */\n actorId: str(actor?.id),\n actorEmail: str(actor?.email),\n actorName: str(actor?.name),\n /* 결과 — 승인했는데 커널이 거절한 것도 감사 대상이다(무엇을 시도했는지가 남아야 한다). */\n accepted: !!ack?.accepted,\n errorCode: str(ack?.errorCode),\n /* 인자는 원형 그대로. 너무 크면 잘린 문자열로 두되 잘랐다고 말한다. */\n args: truncated ? argsText!.slice(0, ARGS_MAX) : command?.args ?? undefined,\n argsTruncated: truncated\n }\n}\n\nconst str = (v: unknown): string | undefined => (typeof v === 'string' && v ? v : undefined)\n\nfunction safeJson(v: unknown): string | null {\n try {\n return v === undefined ? null : JSON.stringify(v)\n } catch {\n return null /* 순환 참조 등 — 못 재면 자르지 않는다(원본을 그대로 둔다) */\n }\n}\n"]}
1
+ {"version":3,"file":"command-audit.js","sourceRoot":"","sources":["../../../server/service/twin-audit/command-audit.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAoDH,0CAEC;AAKD,8CAuBC;AAkBD,0CAGC;AApDD,4DAA4D;AAC5D,SAAgB,eAAe,CAAC,CAAU;IACxC,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AACzE,CAAC;AAED,0CAA0C;AAC1C,MAAM,QAAQ,GAAG,IAAI,CAAA;AAErB,SAAgB,iBAAiB,CAAC,KAAwB;IACxD,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACxC,MAAM,SAAS,GAAG,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAA;IACjE,OAAO;QACL,SAAS,EAAE,EAAE;QACb,SAAS,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC;QAClC,WAAW,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC;QAC/B,MAAM,EAAE,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC;QACxC,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC;QAC5B,2CAA2C;QAC3C,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClH,4CAA4C;QAC5C,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;QACvB,UAAU,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;QAC7B,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC;QAC3B,uDAAuD;QACvD,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ;QACzB,SAAS,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC;QAC9B,4CAA4C;QAC5C,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,QAAS,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,SAAS;QAC3E,aAAa,EAAE,SAAS;KACzB,CAAA;AACH,CAAC;AAED,MAAM,GAAG,GAAG,CAAC,CAAU,EAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;AAE5F,SAAS,QAAQ,CAAC,CAAU;IAC1B,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA,CAAC,wCAAwC;IACtD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,MAA2C;IACzE,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACxE,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1C,CAAC","sourcesContent":["/*\n * 커맨드 감사 기록 만들기 (순수) — **누가 무엇을 허락했고, 그래서 어떻게 됐나.**\n *\n * 승인 게이트가 앞을 막고, 이 기록이 뒤를 설명한다. 둘 다 있어야 \"사람 손을 거쳤다\" 를 증명할 수 있다.\n *\n * 무엇을 믿는가가 이 기록의 전부다:\n * · **신원·시각은 서버가 준다.** 클라이언트가 말한 신원을 그대로 적으면 위조가 자유로워 아무것도\n * 증명하지 못한다. 세션이 아는 사용자와 서버 시각만 쓴다.\n * · **의도는 클라이언트가 준다** — 출처(origin)·근거(reason). 서버가 알 수 없는 정보이고,\n * 위조되더라도 신원 증명을 훼손하지 않는다.\n */\n\nexport type CommandOrigin = 'user' | 'ai' | 'automation' | 'unknown'\n\nexport type CommandAuditInput = {\n /** 클라이언트가 실어 보낸 커맨드(신뢰하지 않는 부분을 포함한 원본). */\n command: any\n /** 커널 판정. */\n ack: { accepted?: boolean; errorCode?: string; error?: string }\n /**\n * **원본(어댑터)이 준 답** — 허락과 일어남 사이에 끼어 있는 것을 같은 기록에 닫는다 (ADR-0029 §1 결정 C).\n *\n * ── 왜 이 칸이 필요한가 ──────────────────────────────────────────────────\n * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 조용히 실패하면 원장에는 승인만\n * 남는다. 그래서 어댑터의 답을 **같은 행**에 되적는다.\n *\n * 셋을 구별한다:\n * · 없음(`undefined`) — **원본에 묻지 않았다**(커널이 받은 명령이다). 「모른다」와 다르다.\n * · `{ answered: false }` — 물었는데 **답을 못 받았다** → `unknown` 으로 남긴다. 성공으로 적지 않는다.\n * · `{ answered: true, ok, code? }` — 원본이 답했다(적용·거절 모두 사실이다).\n */\n source?: { answered: boolean; ok?: boolean; code?: string }\n /** 세션이 아는 사용자 — **서버만 채운다.** */\n actor?: { id?: string; email?: string; name?: string }\n /** 서버 시각. 호출부가 주입해 테스트가 시간을 고정할 수 있게 한다. */\n at: Date\n}\n\n/** `TwinAuditEvent` 에 그대로 넣을 수 있는 모양(엔티티를 몰라도 되게 순수하게 둔다). */\nexport type CommandAuditRow = {\n eventTime: Date\n commandId?: string\n commandType?: string\n origin: CommandOrigin\n reason?: string\n actorId?: string\n actorEmail?: string\n actorName?: string\n accepted: boolean\n errorCode?: string\n /**\n * 원본이 그래서 어떻게 했나 — `applied` · `refused` · `unknown`(물었지만 답이 없다).\n * **없으면 묻지 않은 것이다**(커널이 받은 명령). 0 이나 성공으로 채우지 않는다.\n */\n sourceOutcome?: 'applied' | 'refused' | 'unknown'\n /** 원본이 준 사유 코드 — 있으면 그대로. 우리가 지어내지 않는다. */\n sourceCode?: string\n args?: any\n argsTruncated: boolean\n}\n\n/** 신뢰할 수 있는 출처 표기로 정규화 — 모르는 값은 지어내지 않고 'unknown' 으로 둔다. */\nexport function normalizeOrigin(v: unknown): CommandOrigin {\n return v === 'user' || v === 'ai' || v === 'automation' ? v : 'unknown'\n}\n\n/** args 직렬화 상한(문자). 넘으면 자르되 잘랐다고 표시한다. */\nconst ARGS_MAX = 4000\n\nexport function buildCommandAudit(input: CommandAuditInput): CommandAuditRow {\n const { command, ack, actor, at, source } = input\n const argsText = safeJson(command?.args)\n const truncated = argsText !== null && argsText.length > ARGS_MAX\n return {\n eventTime: at,\n commandId: str(command?.commandId),\n commandType: str(command?.type),\n origin: normalizeOrigin(command?.origin),\n reason: str(command?.reason),\n /* 원본의 답 — 묻지 않았으면 칸을 만들지 않는다(모름과 구별한다). */\n ...(source ? { sourceOutcome: sourceOutcomeOf(source), ...(source.code ? { sourceCode: source.code } : {}) } : {}),\n /* 신원 — 세션 값만. 커맨드에 실려 온 신원 주장은 쳐다보지 않는다. */\n actorId: str(actor?.id),\n actorEmail: str(actor?.email),\n actorName: str(actor?.name),\n /* 결과 — 승인했는데 커널이 거절한 것도 감사 대상이다(무엇을 시도했는지가 남아야 한다). */\n accepted: !!ack?.accepted,\n errorCode: str(ack?.errorCode),\n /* 인자는 원형 그대로. 너무 크면 잘린 문자열로 두되 잘랐다고 말한다. */\n args: truncated ? argsText!.slice(0, ARGS_MAX) : command?.args ?? undefined,\n argsTruncated: truncated\n }\n}\n\nconst str = (v: unknown): string | undefined => (typeof v === 'string' && v ? v : undefined)\n\nfunction safeJson(v: unknown): string | null {\n try {\n return v === undefined ? null : JSON.stringify(v)\n } catch {\n return null /* 순환 참조 등 — 못 재면 자르지 않는다(원본을 그대로 둔다) */\n }\n}\n\n/**\n * 원본의 답을 세 값으로 — **답이 없으면 `unknown`**(성공으로 적지 않는다).\n *\n * 이 함수가 있는 이유: 「물었지만 답이 없다」를 실패로도 성공으로도 적을 수 없다. 실패로 적으면 일어난 일을\n * 없던 일로 만들고, 성공으로 적으면 없던 일을 일어난 일로 만든다. 셋째 값이 사실이다.\n */\nexport function sourceOutcomeOf(source: { answered: boolean; ok?: boolean }): 'applied' | 'refused' | 'unknown' {\n if (!source.answered || typeof source.ok !== 'boolean') return 'unknown'\n return source.ok ? 'applied' : 'refused'\n}\n"]}
@@ -9,6 +9,9 @@ export declare class TwinAuditEvent {
9
9
  commandType?: string;
10
10
  origin?: string;
11
11
  reason?: string;
12
+ sourceOutcome?: string;
13
+ /** 원본이 준 사유 코드 — 있으면 그대로 적는다(우리가 지어내지 않는다). */
14
+ sourceCode?: string;
12
15
  actorId?: string;
13
16
  actorEmail?: string;
14
17
  actorName?: string;
@@ -5,6 +5,12 @@ const tslib_1 = require("tslib");
5
5
  const typeorm_1 = require("typeorm");
6
6
  const type_graphql_1 = require("type-graphql");
7
7
  const shell_1 = require("@things-factory/shell");
8
+ const env_1 = require("@things-factory/env");
9
+ /*
10
+ * 긴 글의 컬럼 타입은 **드라이버마다 이름이 다르다** — 이 레포의 정본 관행대로 여기서 고른다
11
+ * (board-service 의 `Board.model` 과 같은 방식). `text` 를 그대로 적었더니 Oracle 이 모르는 이름이었다.
12
+ */
13
+ const DATABASE_TYPE = env_1.config.get('ormconfig', {}).type;
8
14
  /*
9
15
  * TwinAuditEvent — **사람이 무엇을 허락했는가.**
10
16
  *
@@ -48,7 +54,7 @@ tslib_1.__decorate([
48
54
  tslib_1.__metadata("design:type", String)
49
55
  ], TwinAuditEvent.prototype, "instanceId", void 0);
50
56
  tslib_1.__decorate([
51
- (0, typeorm_1.Column)({ type: 'datetime' }),
57
+ (0, typeorm_1.Column)(),
52
58
  (0, type_graphql_1.Field)({ description: 'Server time when the command was dispatched.' }),
53
59
  tslib_1.__metadata("design:type", Date)
54
60
  ], TwinAuditEvent.prototype, "eventTime", void 0);
@@ -68,10 +74,30 @@ tslib_1.__decorate([
68
74
  tslib_1.__metadata("design:type", String)
69
75
  ], TwinAuditEvent.prototype, "origin", void 0);
70
76
  tslib_1.__decorate([
71
- (0, typeorm_1.Column)({ type: 'text', nullable: true }),
77
+ (0, typeorm_1.Column)({
78
+ nullable: true,
79
+ type: DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
80
+ ? 'longtext'
81
+ : DATABASE_TYPE == 'oracle'
82
+ ? 'clob'
83
+ : DATABASE_TYPE == 'mssql'
84
+ ? 'nvarchar'
85
+ : 'text',
86
+ length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined
87
+ }),
72
88
  (0, type_graphql_1.Field)({ nullable: true, description: 'Why this action — the rationale shown on the approval card.' }),
73
89
  tslib_1.__metadata("design:type", String)
74
90
  ], TwinAuditEvent.prototype, "reason", void 0);
91
+ tslib_1.__decorate([
92
+ (0, typeorm_1.Column)({ nullable: true }),
93
+ (0, type_graphql_1.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." }),
94
+ tslib_1.__metadata("design:type", String)
95
+ ], TwinAuditEvent.prototype, "sourceOutcome", void 0);
96
+ tslib_1.__decorate([
97
+ (0, typeorm_1.Column)({ nullable: true }),
98
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Reason code the source returned, as it gave it.' }),
99
+ tslib_1.__metadata("design:type", String)
100
+ ], TwinAuditEvent.prototype, "sourceCode", void 0);
75
101
  tslib_1.__decorate([
76
102
  (0, typeorm_1.Column)({ nullable: true }),
77
103
  (0, type_graphql_1.Field)({ nullable: true, description: 'Approving user id, stamped by the server from the session.' }),
@@ -1 +1 @@
1
- {"version":3,"file":"twin-audit-event.js","sourceRoot":"","sources":["../../../server/service/twin-audit/twin-audit-event.ts"],"names":[],"mappings":"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","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'\nimport { ObjectType, Field, ID } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\n\n/*\n * TwinAuditEvent — **사람이 무엇을 허락했는가.**\n *\n * ── 왜 저널(TwinEvent)이 아닌가 ───────────────────────────────────────────────\n * 처음에는 저널에 함께 넣었다. \"감사는 원장에서 하니까\" 라는 이유였는데, 그건 **화면의 편의**였고\n * 저장 구조를 정할 근거가 못 됐다. 넣자마자 예외가 넷 생겼다 — 리플레이에서 빼고, 백필에서 빼고,\n * 원장 거래 분류에서 빼고, 원장 렌더에서 갈랐다. **예외가 넷이면 설계가 \"여기 아니다\" 라고 말하는 것이다.**\n *\n * 갈라 두면 예외가 0 이고, 오히려 얻는다:\n * · 행위자가 **컬럼**이 된다 — \"누가 승인한 것 전부\" 는 감사의 기본 질문인데 payload 안에서는 못 찾았다\n * · revision 이 없다. 저널에서는 그 칸을 비워 \"상태가 아님\" 을 뜻하게 썼는데, 없음을 종류 표시로\n * 쓰는 것이 여러 번 문제를 냈다(백필의 `bizStep IS NULL = 옛 행` 전제가 이것 때문에 깨졌다)\n * · bizStep 오염이 없다 — 저널의 키 추출기는 값이 없으면 이벤트 타입으로 대체하므로,\n * 감사 행을 태우면 CBV 표준 어휘 컬럼에 `governance.command` 가 박힌다\n *\n * ── 무엇을 믿는가 ────────────────────────────────────────────────────────────\n * **신원·시각은 서버가 각인한다.** 클라이언트가 말한 신원을 그대로 적으면 위조가 자유로워 그 기록은\n * 아무것도 증명하지 못한다. 세션이 아는 사용자와 서버 시각만 신뢰한다.\n * 클라이언트에서 받는 것은 **의도**뿐이다 — 어디서 시작됐나(origin), 왜 하나(reason).\n */\n@Entity()\n/* 목록 기본 정렬 — 최근 것부터. 감사는 \"요즘 무슨 일이 있었나\" 로 시작한다. */\n@Index('ix_twin_audit_0', (e: TwinAuditEvent) => [e.domain, e.instanceId, e.eventTime], { unique: false })\n/* 행위자로 찾기 — 저널에 있을 때는 불가능했던 질문(\"김현장이 승인한 것 전부\"). */\n@Index('ix_twin_audit_1', (e: TwinAuditEvent) => [e.domain, e.actorEmail, e.eventTime], { unique: false })\n@ObjectType({ description: 'Audit record of a twin command: who approved what, and what the kernel answered.' })\nexport class TwinAuditEvent {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the audit record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })\n domain?: Domain\n\n @RelationId((e: TwinAuditEvent) => e.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Twin runtime instance the command was aimed at.' })\n instanceId: string\n\n /*\n * 서버 시각. 클라이언트 시계를 믿지 않는다 — 기록의 시간축이 단말 설정에 좌우되면 안 된다.\n *\n * `datetime` 을 쓴다. `timestamp` 는 **sqlite 가 지원하지 않아** 5개 드라이버 공통이 아니다\n * (실제로 그렇게 썼다가 DB 를 쓰는 검사 33개가 한꺼번에 터졌다).\n */\n @Column({ type: 'datetime' })\n @Field({ description: 'Server time when the command was dispatched.' })\n eventTime: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Client-supplied command id, for correlating with kernel logs.' })\n commandId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Command type (e.g. order.hold, equipment.repair).' })\n commandType?: string\n\n /* 'user' | 'ai' | 'automation' | 'unknown'. 모르면 unknown 이지 사람이 한 것으로 치지 않는다. */\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"Where the command originated: 'user' | 'ai' | 'automation' | 'unknown'.\" })\n origin?: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Why this action — the rationale shown on the approval card.' })\n reason?: string\n\n /* ── 신원: 세션에서만 온다 ── */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user id, stamped by the server from the session.' })\n actorId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user email, stamped by the server from the session.' })\n actorEmail?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user name, stamped by the server from the session.' })\n actorName?: string\n\n /* ── 결과: 거절도 남긴다 ── */\n @Column({ default: false })\n @Field({ description: 'Whether the kernel accepted the command.' })\n accepted: boolean\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Language-neutral rejection code when the kernel refused.' })\n errorCode?: string\n\n /**\n * 명령 인자 — **원형 그대로.** 무엇에 대한 명령이었는지가 감사의 핵심이라 요약하지 않는다.\n * 지나치게 크면 자르되 `argsTruncated` 로 잘랐다는 사실을 남긴다(조용히 버리지 않는다).\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'Command arguments as given.' })\n args?: any\n\n @Column({ default: false })\n @Field({ description: 'True when args were too large and stored truncated.' })\n argsTruncated: boolean\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when the audit row was written.' })\n createdAt?: Date\n}\n"]}
1
+ {"version":3,"file":"twin-audit-event.js","sourceRoot":"","sources":["../../../server/service/twin-audit/twin-audit-event.ts"],"names":[],"mappings":"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","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'\nimport { ObjectType, Field, ID } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\nimport { config } from '@things-factory/env'\n\n/*\n * 긴 글의 컬럼 타입은 **드라이버마다 이름이 다르다** — 이 레포의 정본 관행대로 여기서 고른다\n * (board-service 의 `Board.model` 과 같은 방식). `text` 를 그대로 적었더니 Oracle 이 모르는 이름이었다.\n */\nconst DATABASE_TYPE = config.get('ormconfig', {}).type\n\n/*\n * TwinAuditEvent — **사람이 무엇을 허락했는가.**\n *\n * ── 왜 저널(TwinEvent)이 아닌가 ───────────────────────────────────────────────\n * 처음에는 저널에 함께 넣었다. \"감사는 원장에서 하니까\" 라는 이유였는데, 그건 **화면의 편의**였고\n * 저장 구조를 정할 근거가 못 됐다. 넣자마자 예외가 넷 생겼다 — 리플레이에서 빼고, 백필에서 빼고,\n * 원장 거래 분류에서 빼고, 원장 렌더에서 갈랐다. **예외가 넷이면 설계가 \"여기 아니다\" 라고 말하는 것이다.**\n *\n * 갈라 두면 예외가 0 이고, 오히려 얻는다:\n * · 행위자가 **컬럼**이 된다 — \"누가 승인한 것 전부\" 는 감사의 기본 질문인데 payload 안에서는 못 찾았다\n * · revision 이 없다. 저널에서는 그 칸을 비워 \"상태가 아님\" 을 뜻하게 썼는데, 없음을 종류 표시로\n * 쓰는 것이 여러 번 문제를 냈다(백필의 `bizStep IS NULL = 옛 행` 전제가 이것 때문에 깨졌다)\n * · bizStep 오염이 없다 — 저널의 키 추출기는 값이 없으면 이벤트 타입으로 대체하므로,\n * 감사 행을 태우면 CBV 표준 어휘 컬럼에 `governance.command` 가 박힌다\n *\n * ── 무엇을 믿는가 ────────────────────────────────────────────────────────────\n * **신원·시각은 서버가 각인한다.** 클라이언트가 말한 신원을 그대로 적으면 위조가 자유로워 그 기록은\n * 아무것도 증명하지 못한다. 세션이 아는 사용자와 서버 시각만 신뢰한다.\n * 클라이언트에서 받는 것은 **의도**뿐이다 — 어디서 시작됐나(origin), 왜 하나(reason).\n */\n@Entity()\n/* 목록 기본 정렬 — 최근 것부터. 감사는 \"요즘 무슨 일이 있었나\" 로 시작한다. */\n@Index('ix_twin_audit_0', (e: TwinAuditEvent) => [e.domain, e.instanceId, e.eventTime], { unique: false })\n/* 행위자로 찾기 — 저널에 있을 때는 불가능했던 질문(\"김현장이 승인한 것 전부\"). */\n@Index('ix_twin_audit_1', (e: TwinAuditEvent) => [e.domain, e.actorEmail, e.eventTime], { unique: false })\n@ObjectType({ description: 'Audit record of a twin command: who approved what, and what the kernel answered.' })\nexport class TwinAuditEvent {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the audit record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })\n domain?: Domain\n\n @RelationId((e: TwinAuditEvent) => e.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Twin runtime instance the command was aimed at.' })\n instanceId: string\n\n /*\n * 서버 시각. 클라이언트 시계를 믿지 않는다 — 기록의 시간축이 단말 설정에 좌우되면 안 된다.\n *\n * **타입 이름은 적지 않는다** (2026-08-19 Postgres 부팅 실패로 고침).\n * `datetime` 은 sqlite·MySQL 의 이름이고 Postgres 는 `timestamp` 만 안다 — 거꾸로 `timestamp` 는\n * sqlite 가 모른다. **다섯 드라이버에 다 통하는 이름이 없다.** 그래서 이름 고르는 일을 TypeORM 에\n * 맡긴다(`emitDecoratorMetadata` 가 켜져 있어 `Date` 에서 드라이버별 타입을 고른다).\n */\n @Column()\n @Field({ description: 'Server time when the command was dispatched.' })\n eventTime: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Client-supplied command id, for correlating with kernel logs.' })\n commandId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Command type (e.g. order.hold, equipment.repair).' })\n commandType?: string\n\n /* 'user' | 'ai' | 'automation' | 'unknown'. 모르면 unknown 이지 사람이 한 것으로 치지 않는다. */\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"Where the command originated: 'user' | 'ai' | 'automation' | 'unknown'.\" })\n origin?: string\n\n /*\n * 승인 사유 — 사람이 쓰는 글이라 길이를 미리 자르지 않는다.\n *\n * 이름을 드라이버별로 고른다(2026-08-19): `text` 는 Oracle 이 모르고(그쪽은 `clob`), MySQL 계열은\n * 긴 글에 `longtext` 를, MSSQL 은 `nvarchar(MAX)` 를 쓴다. 다중 DB 를 지키는 이 레포의 관행이 그렇다.\n */\n @Column({\n nullable: true,\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'text',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined\n })\n @Field({ nullable: true, description: 'Why this action — the rationale shown on the approval card.' })\n reason?: string\n\n /* ── 신원: 세션에서만 온다 ── */\n /*\n * **원본이 그래서 어떻게 했나** — 허락과 일어남 사이에 끼어 있는 것을 같은 행에 닫는다\n * (ADR-0029 §1 결정 C, 2026-08-19).\n *\n * 명령이 원본으로 가면 감사는 「허락했다」까지만 증명한다 — 어댑터가 조용히 실패하면 원장에는 승인만\n * 남는다. 그래서 어댑터의 답을 되적는다.\n *\n * · 비어 있음 — **원본에 묻지 않았다**(커널이 받은 명령이다). 「모른다」와 다르다.\n * · `unknown` — 물었는데 **답을 못 받았다**. 성공으로 적지 않는다.\n * · `applied` · `refused` — 원본이 답했다(둘 다 사실이다).\n */\n @Column({ nullable: true })\n @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.\" })\n sourceOutcome?: string\n\n /** 원본이 준 사유 코드 — 있으면 그대로 적는다(우리가 지어내지 않는다). */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Reason code the source returned, as it gave it.' })\n sourceCode?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user id, stamped by the server from the session.' })\n actorId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user email, stamped by the server from the session.' })\n actorEmail?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user name, stamped by the server from the session.' })\n actorName?: string\n\n /* ── 결과: 거절도 남긴다 ── */\n @Column({ default: false })\n @Field({ description: 'Whether the kernel accepted the command.' })\n accepted: boolean\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Language-neutral rejection code when the kernel refused.' })\n errorCode?: string\n\n /**\n * 명령 인자 — **원형 그대로.** 무엇에 대한 명령이었는지가 감사의 핵심이라 요약하지 않는다.\n * 지나치게 크면 자르되 `argsTruncated` 로 잘랐다는 사실을 남긴다(조용히 버리지 않는다).\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'Command arguments as given.' })\n args?: any\n\n @Column({ default: false })\n @Field({ description: 'True when args were too large and stored truncated.' })\n argsTruncated: boolean\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when the audit row was written.' })\n createdAt?: Date\n}\n"]}
@@ -6,6 +6,19 @@ export declare class TwinControlMutation {
6
6
  errorCode?: string;
7
7
  errorParams?: Record<string, string | number>;
8
8
  }>;
9
- /** Scenario 채널 — 생성기 시나리오 제어(load/start/pause/setSpeed). */
10
- controlTwinScenario(instanceId: string, action: string, context: ResolverContext, scenario?: any): Promise<boolean>;
9
+ /**
10
+ * 구동 채널 — **원본을 지난다**(ADR-0029 §8).
11
+ *
12
+ * ── 무엇이 바뀌었나 (2026-08-19) ──────────────────────────────────────────
13
+ * 예전에는 이 문이 `TwinEngine.runtime(...).scenario` 를 **직접** 잡았다. 시뮬만 할 수 있는 일(자극·배속·
14
+ * 정지)이 계약 밖의 지름길로 들어온 셈이고, 실 시스템에는 그 자리가 아예 없었다. 이제 길은 하나다:
15
+ * 트윈 → 그 트윈의 원본 → 어댑터가 **선언한** `control` 능력. 선언하지 않은 원본에는 문이 열리지 않고,
16
+ * 그 사실을 사유 코드로 말한다(`not-declared`) — 실 WMS 가 정지되지 않는 것은 결손이 아니다.
17
+ *
18
+ * 반환을 Boolean 에서 객체로 바꿨다: 예전에는 거절 사유를 실을 자리가 없어 **로그로만** 남겼다.
19
+ * 화면은 왜 안 되는지 알 수 없었다.
20
+ */
21
+ controlTwinSource(instanceId: string, action: string, context: ResolverContext, scenario?: any, speed?: number): Promise<any>;
22
+ /** 이 트윈의 원본이 **무엇을 받을 수 있나** — 화면이 버튼을 열기 전에 묻는 자리. */
23
+ twinSourceCapability(instanceId: string, context: ResolverContext): Promise<any>;
11
24
  }