@quolu/lattice 0.52.0 → 0.52.2

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 (182) hide show
  1. package/LICENSE +147 -147
  2. package/README.ja.md +355 -355
  3. package/README.md +258 -258
  4. package/bin/lattice-mcp.mjs +0 -0
  5. package/bin/lattice-scripted-adapter.mjs +0 -0
  6. package/bin/lattice-scripted-worker.mjs +0 -0
  7. package/bin/lattice-work-order-adapter.mjs +0 -0
  8. package/bin/lattice.mjs +0 -0
  9. package/docs/bridge-setup.md +132 -132
  10. package/docs/schemas/lattice.executor_packet.v1.schema.json +57 -57
  11. package/docs/schemas/lattice.executor_receipt.v1.schema.json +66 -66
  12. package/docs/schemas/lattice.phase_todo_revision.v3.schema.json +360 -360
  13. package/docs/schemas/lattice.plan_create_input.v1.schema.json +56 -56
  14. package/docs/schemas/lattice.plan_create_input.v2.schema.json +72 -72
  15. package/docs/schemas/lattice.plan_create_input.v3.schema.json +81 -81
  16. package/docs/schemas/lattice.plan_create_input.v4.schema.json +85 -85
  17. package/docs/schemas/lattice.run_request.v1.schema.json +238 -238
  18. package/docs/schemas/lattice.runtime_adapter_capabilities.v2.schema.json +55 -55
  19. package/docs/schemas/lattice.runtime_adapter_registration_input.v1.schema.json +78 -78
  20. package/docs/schemas/lattice.runtime_adapter_registration_input.v2.schema.json +86 -86
  21. package/docs/schemas/lattice.todo_extraction.v2.schema.json +298 -298
  22. package/docs/schemas/lattice.todo_extraction.v3.schema.json +146 -146
  23. package/docs/schemas/lattice.todo_revision.v2.schema.json +260 -260
  24. package/docs/schemas/lattice.todo_revision_set.v3.schema.json +363 -363
  25. package/package.json +103 -103
  26. package/sensor/LICENSE +21 -21
  27. package/sensor/NOTICE +19 -19
  28. package/sensor/dist/bin/lattice-sensor.js +9 -9
  29. package/sensor/dist/db/index.js +24 -24
  30. package/sensor/dist/db/migrations.js +41 -41
  31. package/sensor/dist/db/queries.js +164 -164
  32. package/sensor/dist/db/schema.sql +205 -205
  33. package/sensor/dist/directory.js +5 -5
  34. package/sensor/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  35. package/sensor/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  36. package/sensor/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  37. package/sensor/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  38. package/sensor/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  39. package/sensor/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  40. package/sensor/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
  41. package/sensor/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
  42. package/sensor/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
  43. package/sensor/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  44. package/sensor/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  45. package/sensor/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
  46. package/sensor/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
  47. package/sensor/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
  48. package/sensor/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  49. package/sensor/dist/mcp/liveness-watchdog.js +53 -53
  50. package/sensor/dist/mcp/server-instructions.js +95 -95
  51. package/sensor/package.json +56 -56
  52. package/src/artifact-contracts-v2.mjs +325 -325
  53. package/src/artifact-contracts.mjs +895 -895
  54. package/src/boundary-compiler.mjs +712 -712
  55. package/src/boundary-observation-compiler-v2.mjs +344 -344
  56. package/src/bounded-seam.mjs +230 -230
  57. package/src/bridge-address.mjs +107 -107
  58. package/src/bridge-cli.mjs +297 -297
  59. package/src/bridge-config.mjs +346 -346
  60. package/src/bridge-daemon.mjs +378 -378
  61. package/src/bridge-launch-agent.mjs +323 -323
  62. package/src/bridge-registrar.mjs +102 -102
  63. package/src/bridge-server.mjs +376 -376
  64. package/src/cli-help.mjs +308 -308
  65. package/src/cli-stdio.mjs +40 -40
  66. package/src/control-compiler.mjs +532 -532
  67. package/src/dag-chain.mjs +261 -261
  68. package/src/factory-diagnostics.mjs +188 -188
  69. package/src/hash-chain.mjs +76 -76
  70. package/src/hooks-cli.mjs +1057 -1053
  71. package/src/isolation-runner.mjs +409 -409
  72. package/src/node-version-guard.mjs +44 -44
  73. package/src/project-cli.mjs +697 -697
  74. package/src/project-identity.mjs +130 -130
  75. package/src/rc1-black-box-oracle.mjs +906 -906
  76. package/src/rc1-comparison.mjs +154 -154
  77. package/src/rc1-evidence-bundle.mjs +456 -456
  78. package/src/rc1-v4-campaign.mjs +708 -708
  79. package/src/rc1-v4-transform.mjs +467 -467
  80. package/src/rc1-v5-artifact-set.mjs +855 -855
  81. package/src/rc1-v5-behavior-evidence.mjs +594 -594
  82. package/src/rc1-v5-campaign.mjs +797 -797
  83. package/src/rc1-v5-transform.mjs +421 -421
  84. package/src/rc1-v6-artifact-set.mjs +807 -807
  85. package/src/rc1-v6-behavior-evidence.mjs +273 -273
  86. package/src/rc1-v6-campaign.mjs +623 -623
  87. package/src/rc1-v6-causal-binding.mjs +473 -473
  88. package/src/rc1-v6-measurement.mjs +313 -313
  89. package/src/rc2-artifact-set.mjs +1584 -1584
  90. package/src/rc2-campaign.mjs +1506 -1502
  91. package/src/rc2-delivery-policy-front-end.mjs +1079 -1079
  92. package/src/rc2-delivery-policy-oracle.mjs +134 -134
  93. package/src/rc2-delivery-policy-transform.mjs +1127 -1127
  94. package/src/rc2-rc1-transfer-front-end.mjs +511 -511
  95. package/src/rc3-actual-dogfood.mjs +652 -652
  96. package/src/rc3-dogfood-scaffold.mjs +315 -315
  97. package/src/rc3-scripted-campaign.mjs +1383 -1383
  98. package/src/rc4-stage1-dogfood.mjs +673 -673
  99. package/src/runtime-adapter-registry.mjs +524 -520
  100. package/src/runtime-cli.mjs +4588 -4584
  101. package/src/runtime-contracts.mjs +824 -824
  102. package/src/runtime-control-store.mjs +604 -600
  103. package/src/runtime-controller-protocol.mjs +587 -587
  104. package/src/runtime-decision-verifier.mjs +701 -701
  105. package/src/runtime-diff-observer.mjs +361 -361
  106. package/src/runtime-direct-os-observer.mjs +301 -301
  107. package/src/runtime-driver-state.mjs +166 -162
  108. package/src/runtime-engine.mjs +779 -779
  109. package/src/runtime-errors.mjs +356 -356
  110. package/src/runtime-event-store.mjs +189 -189
  111. package/src/runtime-front-end.mjs +925 -925
  112. package/src/runtime-gate-store.mjs +481 -477
  113. package/src/runtime-hold-recompile.mjs +916 -916
  114. package/src/runtime-io-sentinel.mjs +391 -391
  115. package/src/runtime-lifecycle-lock.mjs +294 -290
  116. package/src/runtime-managed-supervisor.mjs +1490 -1490
  117. package/src/runtime-multi-epoch-store.mjs +838 -834
  118. package/src/runtime-projection.mjs +269 -269
  119. package/src/runtime-pull-intake.mjs +1192 -1188
  120. package/src/runtime-scripted-adapter-controller.mjs +1160 -1156
  121. package/src/runtime-scripted-executor.mjs +163 -163
  122. package/src/runtime-scripted-worktree.mjs +104 -104
  123. package/src/runtime-seam-resolve.mjs +428 -428
  124. package/src/runtime-seam-treatment.mjs +173 -173
  125. package/src/runtime-socket-owner.mjs +125 -125
  126. package/src/runtime-work-order-contracts.mjs +91 -91
  127. package/src/runtime-work-order-controller.mjs +1171 -1167
  128. package/src/runtime-worktree-executor.mjs +199 -199
  129. package/src/schedulability-compiler-v2.mjs +303 -303
  130. package/src/schedulability-verifier-v2.mjs +317 -317
  131. package/src/seam-apply.mjs +549 -549
  132. package/src/seam-commit-shared.mjs +22 -22
  133. package/src/seam-commit-transform.mjs +81 -81
  134. package/src/seam-commit.mjs +18 -18
  135. package/src/seam-cost.mjs +322 -322
  136. package/src/seam-derivation.mjs +188 -188
  137. package/src/seam-gate.mjs +146 -146
  138. package/src/seam-proposal-contracts.mjs +446 -446
  139. package/src/seam-proposal-queries.mjs +521 -521
  140. package/src/seam-proposal.mjs +2011 -2011
  141. package/src/seam-ref.mjs +33 -33
  142. package/src/seam-rewrite.mjs +286 -286
  143. package/src/seam-transform.mjs +554 -554
  144. package/src/seam-verification.mjs +260 -260
  145. package/src/sensor-adapter.mjs +432 -432
  146. package/src/sensor-cli.mjs +139 -139
  147. package/src/sensor-diff.mjs +661 -661
  148. package/src/sensor-node-runtime.mjs +53 -53
  149. package/src/sensor-runtime.mjs +52 -52
  150. package/src/timestamp-contract.mjs +8 -8
  151. package/src/todo-audit-pending.mjs +91 -91
  152. package/src/todo-chain.mjs +178 -178
  153. package/src/todo-cli.mjs +3141 -3126
  154. package/src/todo-contracts.mjs +728 -728
  155. package/src/todo-dashboard-registry.mjs +573 -573
  156. package/src/todo-dispatch-shape.mjs +190 -190
  157. package/src/todo-gantt-html-independence.mjs +239 -239
  158. package/src/todo-gantt-html-shared.mjs +226 -226
  159. package/src/todo-gantt-html-style.mjs +131 -131
  160. package/src/todo-gantt-html.mjs +248 -248
  161. package/src/todo-gantt-layout.mjs +974 -974
  162. package/src/todo-gantt-live.mjs +361 -361
  163. package/src/todo-gantt-nested.mjs +263 -263
  164. package/src/todo-gantt-presentation.mjs +217 -217
  165. package/src/todo-gantt-scope.mjs +123 -123
  166. package/src/todo-gantt-svg.mjs +353 -353
  167. package/src/todo-independence-contracts.mjs +595 -595
  168. package/src/todo-independence-guidance.mjs +322 -322
  169. package/src/todo-independence.mjs +640 -640
  170. package/src/todo-markdown-renderer.mjs +260 -260
  171. package/src/todo-migration.mjs +448 -448
  172. package/src/todo-narrative-anchor.mjs +130 -130
  173. package/src/todo-note-store.mjs +629 -625
  174. package/src/todo-parallel-candidates.mjs +114 -114
  175. package/src/todo-revision.mjs +995 -995
  176. package/src/todo-split.mjs +472 -472
  177. package/src/todo-status.mjs +690 -690
  178. package/src/todo-store-git-transaction.mjs +418 -418
  179. package/src/todo-store.mjs +4322 -4314
  180. package/src/treatment-compiler.mjs +728 -728
  181. package/src/treatment-runner.mjs +656 -656
  182. package/src/witness-scaffold.mjs +180 -180
@@ -1,132 +1,132 @@
1
- # Optional network bridge
2
-
3
- Latticeのproject dashboardは既定でloopbackだけにbindし、bridge用socketや設定を作らない。
4
- LAN上のreverse proxyなどから閲覧する時だけ、利用者がlisten IPを明示してbridgeを有効化する。
5
- `postinstall`では質問やnetwork公開を行わない。
6
-
7
- TTYでは`lattice bridge setup`で安全側既定の対話wizardを開始できる。最初の公開確認は既定で無効を選び、
8
- cancelした場合は設定を変更しない。非TTYではhangせず、次の非対話commandを案内する。
9
- portを省略するか`auto`にすると、49152–65535から候補を重複なく選び、
10
- 実際のexclusive bindとhealth確認に成功したportだけを保存する。
11
-
12
- ```bash
13
- lattice bridge setup --listen 192.168.1.50 --port auto --dashboard --allow-host lattice.example.com --json
14
- ```
15
-
16
- `--dashboard`は現在のlocal dashboard descriptorをrequestごとに解決するため、dashboard再起動でportが変わっても
17
- bridge設定はstaleにならない。固定upstreamを使う場合だけ`--upstream http://127.0.0.1:4318`を指定する。
18
- listen IPは常に許可Hostへ入り、reverse proxyで公開するhostnameは`--allow-host`を反復して追加する。
19
- 許可されていないHostは421となるため、DNS rebinding originへ工程情報を返さない。
20
-
21
- ```bash
22
- lattice bridge status --json
23
- lattice bridge reconfigure --listen 192.168.1.50 --port auto --dashboard --json
24
- lattice bridge disable --json
25
- ```
26
-
27
- 設定は`~/.lattice/bridge.json`へmode 0600でatomic保存する。`setup`/`reconfigure`は実bridge daemonが
28
- 選択socketをexclusive bindしhealthを返すまで成功にしない。起動に失敗した場合は旧設定へ戻す。
29
- `disable`もbridge socketの停止確認後に成功し、loopbackのlocal dashboardは停止しない。
30
- configまたはdaemon descriptorが壊れている場合、`disable`は公開socketのfail-closed停止を優先して破損control
31
- fileを除去し、JSON結果の`recovery`へ処置を明示する。その後は`setup`で再設定できる。
32
-
33
- 自動化・隔離testではabsoluteな`LATTICE_CONFIG_DIR`で設定rootを変更できる。無効な設定、低いport、
34
- 使用中の明示port、危険なrequest target、到達不能upstreamはsilent fallbackせずtyped errorを返す。
35
-
36
- ## listen IPがDHCPで動く場合
37
-
38
- 設定したlisten IPがホストから消えると、古いsocketは死んだアドレスへ取り残され、LANから到達できなくなる。
39
- daemonは各reconcileで実効アドレスを解決し直し、同一subnet(IPv4 /24、IPv6 /64)に生きたアドレスがあれば
40
- そこへbindし直す。VPNや別NICなど異なるnetworkのアドレスは採用せず、候補が無ければ
41
- `BRIDGE_LISTEN_ADDRESS_ABSENT`で公開socketをfail-closedにする。再bind先は許可Hostへ自動で加わる。
42
-
43
- `LATTICE_BRIDGE_REGISTRAR_SSH_HOST`と`LATTICE_BRIDGE_REGISTRAR_SCRIPT`を両方設定すると、新しいbindingを
44
- 張るたびに`ssh <host> <script> <port>`でreverse proxy hostへ自己登録する。アドレスは送らず、remote側が
45
- ssh送信元から決めるため、各hostは自分自身しか登録できない。登録の失敗はbridgeを落とさずstderrへ
46
- typedに報告する。この配線が無いと、Caddy等が持つリテラルはlease変更のたびに黙って陳腐化する。
47
-
48
- ## reverse proxyへ逆トンネルで繋ぐ(LAN bindを使わない)
49
-
50
- reverse proxy hostへsshで到達できるなら、LANへbindせずloopbackだけで公開できる。bridgeが動くhostから
51
- 接続しに行くため、そのhostのLAN addressはreverse proxyのどこにも現れず、追従も自己登録も不要になる。
52
-
53
- ```bash
54
- lattice bridge setup --listen 127.0.0.1 --port 53939 --dashboard --allow-host lattice.example.com --json
55
- ssh -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 \
56
- -R 172.18.0.1:53939:127.0.0.1:53939 proxy-host
57
- ```
58
-
59
- reverse proxyはこの固定endpointだけを見る。転送口のbind先は、reverse proxyが到達できるaddressにする。
60
- Docker上のreverse proxyでは、containerの`127.0.0.1`はcontainer自身のloopbackでありhostのそれではないため、
61
- hostのloopbackへ開いた口には届かない。対象networkのgateway(`docker network inspect`の`Gateway`)へbindする。
62
-
63
- sshdは既定の`GatewayPorts no`だと`127.0.0.1`にしかbindできない。`clientspecified`にすると、clientが明示した
64
- addressだけにbindする(`yes`と違い全interfaceへは晒さない)。host firewallがINPUTをDROPしている場合は、
65
- その1 portだけを許可する。`ExitOnForwardFailure=yes`は、転送口を開けないまま接続だけ生かす状態を防ぐ。
66
- 常駐はprocess supervisorのKeepAliveに任せ、切断時は張り直す。
67
-
68
- ## Docker Caddy/Cloudflare Tunnelへ接続する
69
-
70
- bridgeを有効化したMacとreverse proxy hostの間で、まず許可Hostを付けたLAN到達を確認する。
71
- この段階が失敗している時はDNSやTunnelを追加しない。
72
-
73
- ```bash
74
- curl --fail --header 'Host: lattice.example.com' \
75
- http://MAC_LAN_IP:BRIDGE_PORT/projects/
76
- ```
77
-
78
- Caddyは既存のDocker networkと証明書運用を維持し、Lattice用siteだけを追加する。
79
-
80
- ```caddyfile
81
- lattice.example.com {
82
- reverse_proxy MAC_LAN_IP:BRIDGE_PORT {
83
- flush_interval -1
84
- }
85
- }
86
- ```
87
-
88
- 本番反映はcontainer内で`caddy validate`を通してから`caddy reload`する。Caddyfileを単一ファイルで
89
- bind mountしている構成では、atomic renameでhost側fileを置換するとcontainerが旧inodeを参照し続ける。
90
- 更新前backupを残し、inodeを維持するin-place更新を使うか、directory bind mountへ変更する。
91
-
92
- remote-managed Cloudflare Tunnelでは、Tunnel実行tokenを設定APIの代用にしない。Cloudflareの正規管理面で
93
- public hostname `lattice.kitepon.dev` を次のoriginへ対応付ける。
94
-
95
- - Service: `https://caddy:443`
96
- - TLS Origin Server Name: `lattice.kitepon.dev`(管理面に同等の設定がある場合は`Match SNI to Host`でもよい)
97
-
98
- `http://caddy:80`は選ばない。CaddyのHTTPからHTTPSへのredirectをTunnelがorigin応答として返す構成は、
99
- 外部requestが同じ公開URLへ戻るredirect loopになり得るためである。外部gateではredirectを追って200にせず、
100
- 最初の応答がHTTPSの200であることを確認する。
101
-
102
- 受入は次の3 gateを独立して記録し、後段の成功で前段を代用しない。
103
-
104
- 1. **LAN bridge**: reverse proxy hostから許可Host付きで`http://MAC_LAN_IP:BRIDGE_PORT/projects/`が200。
105
- 2. **Docker Caddy**: Caddyへ`Host: lattice.kitepon.dev`を付けたHTTPS requestが200。証明書検証を省略する
106
- 内部probeを外部公開成功の証拠にはしない。
107
- 3. **Cloudflare public HTTPS**: `https://lattice.kitepon.dev/projects/`がredirectなしで200となり、一覧から開いた
108
- `/projects/<project_id>/`のHTML titleが`Lattice — <project名> 依存工程図`である。
109
-
110
- 公開viewerの404も、ブラウザとAPIの両契約を別々に確認する。未知URLへ`Accept: text/html`を
111
- 付けたrequestはHTTP 404かつ`Content-Type: text/html`で、`noindex, nofollow`と
112
- `/projects/`、`https://kitepon.dev/`への戻り先を持つ。`Accept: application/json`では
113
- HTTP 404かつ`Content-Type: application/json`で、既存の
114
- `lattice.todo_gantt_http_error.v1`を返す。
115
-
116
- ```bash
117
- curl --silent --show-error --include --header 'Accept: text/html' \
118
- https://lattice.kitepon.dev/unknown
119
- curl --silent --show-error --include --header 'Accept: application/json' \
120
- https://lattice.kitepon.dev/unknown
121
- ```
122
-
123
- 外部gateはHTMLだけで閉じず、各projectの
124
- `https://lattice.kitepon.dev/projects/<project_id>/events`も確認する。応答は200かつ
125
- `Content-Type: text/event-stream`で、接続直後に`event: state`と現在の`head_digest`を返さなければならない。
126
- 接続を開いたまま正規のTodo更新を行い、新しい`state`が同じstreamへ届くことを確認する。切断後に再接続しても
127
- 再び初回`state`が届き、そのdigestが最新headと一致することまでを継続・再接続gateとする。
128
-
129
- ```bash
130
- curl --fail --show-error --include --no-buffer --max-time 15 \
131
- https://lattice.kitepon.dev/projects/PROJECT_ID/events
132
- ```
1
+ # Optional network bridge
2
+
3
+ Latticeのproject dashboardは既定でloopbackだけにbindし、bridge用socketや設定を作らない。
4
+ LAN上のreverse proxyなどから閲覧する時だけ、利用者がlisten IPを明示してbridgeを有効化する。
5
+ `postinstall`では質問やnetwork公開を行わない。
6
+
7
+ TTYでは`lattice bridge setup`で安全側既定の対話wizardを開始できる。最初の公開確認は既定で無効を選び、
8
+ cancelした場合は設定を変更しない。非TTYではhangせず、次の非対話commandを案内する。
9
+ portを省略するか`auto`にすると、49152–65535から候補を重複なく選び、
10
+ 実際のexclusive bindとhealth確認に成功したportだけを保存する。
11
+
12
+ ```bash
13
+ lattice bridge setup --listen 192.168.1.50 --port auto --dashboard --allow-host lattice.example.com --json
14
+ ```
15
+
16
+ `--dashboard`は現在のlocal dashboard descriptorをrequestごとに解決するため、dashboard再起動でportが変わっても
17
+ bridge設定はstaleにならない。固定upstreamを使う場合だけ`--upstream http://127.0.0.1:4318`を指定する。
18
+ listen IPは常に許可Hostへ入り、reverse proxyで公開するhostnameは`--allow-host`を反復して追加する。
19
+ 許可されていないHostは421となるため、DNS rebinding originへ工程情報を返さない。
20
+
21
+ ```bash
22
+ lattice bridge status --json
23
+ lattice bridge reconfigure --listen 192.168.1.50 --port auto --dashboard --json
24
+ lattice bridge disable --json
25
+ ```
26
+
27
+ 設定は`~/.lattice/bridge.json`へmode 0600でatomic保存する。`setup`/`reconfigure`は実bridge daemonが
28
+ 選択socketをexclusive bindしhealthを返すまで成功にしない。起動に失敗した場合は旧設定へ戻す。
29
+ `disable`もbridge socketの停止確認後に成功し、loopbackのlocal dashboardは停止しない。
30
+ configまたはdaemon descriptorが壊れている場合、`disable`は公開socketのfail-closed停止を優先して破損control
31
+ fileを除去し、JSON結果の`recovery`へ処置を明示する。その後は`setup`で再設定できる。
32
+
33
+ 自動化・隔離testではabsoluteな`LATTICE_CONFIG_DIR`で設定rootを変更できる。無効な設定、低いport、
34
+ 使用中の明示port、危険なrequest target、到達不能upstreamはsilent fallbackせずtyped errorを返す。
35
+
36
+ ## listen IPがDHCPで動く場合
37
+
38
+ 設定したlisten IPがホストから消えると、古いsocketは死んだアドレスへ取り残され、LANから到達できなくなる。
39
+ daemonは各reconcileで実効アドレスを解決し直し、同一subnet(IPv4 /24、IPv6 /64)に生きたアドレスがあれば
40
+ そこへbindし直す。VPNや別NICなど異なるnetworkのアドレスは採用せず、候補が無ければ
41
+ `BRIDGE_LISTEN_ADDRESS_ABSENT`で公開socketをfail-closedにする。再bind先は許可Hostへ自動で加わる。
42
+
43
+ `LATTICE_BRIDGE_REGISTRAR_SSH_HOST`と`LATTICE_BRIDGE_REGISTRAR_SCRIPT`を両方設定すると、新しいbindingを
44
+ 張るたびに`ssh <host> <script> <port>`でreverse proxy hostへ自己登録する。アドレスは送らず、remote側が
45
+ ssh送信元から決めるため、各hostは自分自身しか登録できない。登録の失敗はbridgeを落とさずstderrへ
46
+ typedに報告する。この配線が無いと、Caddy等が持つリテラルはlease変更のたびに黙って陳腐化する。
47
+
48
+ ## reverse proxyへ逆トンネルで繋ぐ(LAN bindを使わない)
49
+
50
+ reverse proxy hostへsshで到達できるなら、LANへbindせずloopbackだけで公開できる。bridgeが動くhostから
51
+ 接続しに行くため、そのhostのLAN addressはreverse proxyのどこにも現れず、追従も自己登録も不要になる。
52
+
53
+ ```bash
54
+ lattice bridge setup --listen 127.0.0.1 --port 53939 --dashboard --allow-host lattice.example.com --json
55
+ ssh -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 \
56
+ -R 172.18.0.1:53939:127.0.0.1:53939 proxy-host
57
+ ```
58
+
59
+ reverse proxyはこの固定endpointだけを見る。転送口のbind先は、reverse proxyが到達できるaddressにする。
60
+ Docker上のreverse proxyでは、containerの`127.0.0.1`はcontainer自身のloopbackでありhostのそれではないため、
61
+ hostのloopbackへ開いた口には届かない。対象networkのgateway(`docker network inspect`の`Gateway`)へbindする。
62
+
63
+ sshdは既定の`GatewayPorts no`だと`127.0.0.1`にしかbindできない。`clientspecified`にすると、clientが明示した
64
+ addressだけにbindする(`yes`と違い全interfaceへは晒さない)。host firewallがINPUTをDROPしている場合は、
65
+ その1 portだけを許可する。`ExitOnForwardFailure=yes`は、転送口を開けないまま接続だけ生かす状態を防ぐ。
66
+ 常駐はprocess supervisorのKeepAliveに任せ、切断時は張り直す。
67
+
68
+ ## Docker Caddy/Cloudflare Tunnelへ接続する
69
+
70
+ bridgeを有効化したMacとreverse proxy hostの間で、まず許可Hostを付けたLAN到達を確認する。
71
+ この段階が失敗している時はDNSやTunnelを追加しない。
72
+
73
+ ```bash
74
+ curl --fail --header 'Host: lattice.example.com' \
75
+ http://MAC_LAN_IP:BRIDGE_PORT/projects/
76
+ ```
77
+
78
+ Caddyは既存のDocker networkと証明書運用を維持し、Lattice用siteだけを追加する。
79
+
80
+ ```caddyfile
81
+ lattice.example.com {
82
+ reverse_proxy MAC_LAN_IP:BRIDGE_PORT {
83
+ flush_interval -1
84
+ }
85
+ }
86
+ ```
87
+
88
+ 本番反映はcontainer内で`caddy validate`を通してから`caddy reload`する。Caddyfileを単一ファイルで
89
+ bind mountしている構成では、atomic renameでhost側fileを置換するとcontainerが旧inodeを参照し続ける。
90
+ 更新前backupを残し、inodeを維持するin-place更新を使うか、directory bind mountへ変更する。
91
+
92
+ remote-managed Cloudflare Tunnelでは、Tunnel実行tokenを設定APIの代用にしない。Cloudflareの正規管理面で
93
+ public hostname `lattice.kitepon.dev` を次のoriginへ対応付ける。
94
+
95
+ - Service: `https://caddy:443`
96
+ - TLS Origin Server Name: `lattice.kitepon.dev`(管理面に同等の設定がある場合は`Match SNI to Host`でもよい)
97
+
98
+ `http://caddy:80`は選ばない。CaddyのHTTPからHTTPSへのredirectをTunnelがorigin応答として返す構成は、
99
+ 外部requestが同じ公開URLへ戻るredirect loopになり得るためである。外部gateではredirectを追って200にせず、
100
+ 最初の応答がHTTPSの200であることを確認する。
101
+
102
+ 受入は次の3 gateを独立して記録し、後段の成功で前段を代用しない。
103
+
104
+ 1. **LAN bridge**: reverse proxy hostから許可Host付きで`http://MAC_LAN_IP:BRIDGE_PORT/projects/`が200。
105
+ 2. **Docker Caddy**: Caddyへ`Host: lattice.kitepon.dev`を付けたHTTPS requestが200。証明書検証を省略する
106
+ 内部probeを外部公開成功の証拠にはしない。
107
+ 3. **Cloudflare public HTTPS**: `https://lattice.kitepon.dev/projects/`がredirectなしで200となり、一覧から開いた
108
+ `/projects/<project_id>/`のHTML titleが`Lattice — <project名> 依存工程図`である。
109
+
110
+ 公開viewerの404も、ブラウザとAPIの両契約を別々に確認する。未知URLへ`Accept: text/html`を
111
+ 付けたrequestはHTTP 404かつ`Content-Type: text/html`で、`noindex, nofollow`と
112
+ `/projects/`、`https://kitepon.dev/`への戻り先を持つ。`Accept: application/json`では
113
+ HTTP 404かつ`Content-Type: application/json`で、既存の
114
+ `lattice.todo_gantt_http_error.v1`を返す。
115
+
116
+ ```bash
117
+ curl --silent --show-error --include --header 'Accept: text/html' \
118
+ https://lattice.kitepon.dev/unknown
119
+ curl --silent --show-error --include --header 'Accept: application/json' \
120
+ https://lattice.kitepon.dev/unknown
121
+ ```
122
+
123
+ 外部gateはHTMLだけで閉じず、各projectの
124
+ `https://lattice.kitepon.dev/projects/<project_id>/events`も確認する。応答は200かつ
125
+ `Content-Type: text/event-stream`で、接続直後に`event: state`と現在の`head_digest`を返さなければならない。
126
+ 接続を開いたまま正規のTodo更新を行い、新しい`state`が同じstreamへ届くことを確認する。切断後に再接続しても
127
+ 再び初回`state`が届き、そのdigestが最新headと一致することまでを継続・再接続gateとする。
128
+
129
+ ```bash
130
+ curl --fail --show-error --include --no-buffer --max-time 15 \
131
+ https://lattice.kitepon.dev/projects/PROJECT_ID/events
132
+ ```
@@ -1,57 +1,57 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.executor_packet.v1.schema.json",
4
- "title": "lattice.executor_packet.v1",
5
- "description": "The single context packet issued at dispatch. It is the machine record of the context an executor received.",
6
- "$comment": "Runtime validation additionally enforces canonical JSON bytes, the self-digest rule for `packet_digest`, and that `context_content_digest` equals the SHA-256 of the canonical JSON projection of exactly {todo_id, task_ref, scope, base_sha, verifier_refs, forbidden_operations} — plan attribution fields are excluded so that an epoch rebind is provably content-preserving.",
7
- "type": "object",
8
- "additionalProperties": false,
9
- "required": [
10
- "schema",
11
- "packet_id",
12
- "todo_id",
13
- "task_ref",
14
- "scope",
15
- "base_sha",
16
- "plan_ref",
17
- "plan_epoch",
18
- "verifier_refs",
19
- "forbidden_operations",
20
- "context_content_digest",
21
- "packet_digest"
22
- ],
23
- "properties": {
24
- "schema": { "const": "lattice.executor_packet.v1" },
25
- "packet_id": { "$ref": "#/$defs/identifier" },
26
- "todo_id": {
27
- "$ref": "#/$defs/identifier",
28
- "$comment": "Carried through from `run_request.v1`. It is not qualified by any TODO store project/plan/revision identity."
29
- },
30
- "task_ref": { "$ref": "#/$defs/identifier" },
31
- "scope": { "type": "object" },
32
- "base_sha": { "$ref": "#/$defs/gitSha" },
33
- "plan_ref": { "$ref": "#/$defs/identifier" },
34
- "plan_epoch": { "type": "integer", "minimum": 0 },
35
- "verifier_refs": {
36
- "type": "array",
37
- "maxItems": 256,
38
- "items": { "type": "string" }
39
- },
40
- "forbidden_operations": {
41
- "type": "array",
42
- "minItems": 1,
43
- "maxItems": 256,
44
- "items": { "type": "string" }
45
- },
46
- "context_content_digest": { "$ref": "#/$defs/digest" },
47
- "packet_digest": { "$ref": "#/$defs/digest" }
48
- },
49
- "$defs": {
50
- "identifier": {
51
- "type": "string",
52
- "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$"
53
- },
54
- "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
55
- "gitSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" }
56
- }
57
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.executor_packet.v1.schema.json",
4
+ "title": "lattice.executor_packet.v1",
5
+ "description": "The single context packet issued at dispatch. It is the machine record of the context an executor received.",
6
+ "$comment": "Runtime validation additionally enforces canonical JSON bytes, the self-digest rule for `packet_digest`, and that `context_content_digest` equals the SHA-256 of the canonical JSON projection of exactly {todo_id, task_ref, scope, base_sha, verifier_refs, forbidden_operations} — plan attribution fields are excluded so that an epoch rebind is provably content-preserving.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": [
10
+ "schema",
11
+ "packet_id",
12
+ "todo_id",
13
+ "task_ref",
14
+ "scope",
15
+ "base_sha",
16
+ "plan_ref",
17
+ "plan_epoch",
18
+ "verifier_refs",
19
+ "forbidden_operations",
20
+ "context_content_digest",
21
+ "packet_digest"
22
+ ],
23
+ "properties": {
24
+ "schema": { "const": "lattice.executor_packet.v1" },
25
+ "packet_id": { "$ref": "#/$defs/identifier" },
26
+ "todo_id": {
27
+ "$ref": "#/$defs/identifier",
28
+ "$comment": "Carried through from `run_request.v1`. It is not qualified by any TODO store project/plan/revision identity."
29
+ },
30
+ "task_ref": { "$ref": "#/$defs/identifier" },
31
+ "scope": { "type": "object" },
32
+ "base_sha": { "$ref": "#/$defs/gitSha" },
33
+ "plan_ref": { "$ref": "#/$defs/identifier" },
34
+ "plan_epoch": { "type": "integer", "minimum": 0 },
35
+ "verifier_refs": {
36
+ "type": "array",
37
+ "maxItems": 256,
38
+ "items": { "type": "string" }
39
+ },
40
+ "forbidden_operations": {
41
+ "type": "array",
42
+ "minItems": 1,
43
+ "maxItems": 256,
44
+ "items": { "type": "string" }
45
+ },
46
+ "context_content_digest": { "$ref": "#/$defs/digest" },
47
+ "packet_digest": { "$ref": "#/$defs/digest" }
48
+ },
49
+ "$defs": {
50
+ "identifier": {
51
+ "type": "string",
52
+ "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$"
53
+ },
54
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
55
+ "gitSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" }
56
+ }
57
+ }
@@ -1,66 +1,66 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.executor_receipt.v1.schema.json",
4
- "title": "lattice.executor_receipt.v1",
5
- "description": "The receipt an executor returns for one dispatched packet. `packet_digest` is what attributes it to the packet it received.",
6
- "$comment": "Runtime validation additionally enforces canonical JSON bytes and the self-digest rule for `receipt_digest`. Acceptance is decided by event order, not by the receipt's own claims: the binding is checked against the `executor_dispatched` / `epoch_rebound` event that recorded the handle, worktree and packet digest for that TODO.",
7
- "type": "object",
8
- "additionalProperties": false,
9
- "required": [
10
- "schema",
11
- "receipt_id",
12
- "executor_handle",
13
- "worktree_id",
14
- "base_sha",
15
- "plan_epoch",
16
- "packet_digest",
17
- "todo_id",
18
- "checkpoint_digest",
19
- "observed_diff",
20
- "receipt_digest"
21
- ],
22
- "properties": {
23
- "schema": { "const": "lattice.executor_receipt.v1" },
24
- "receipt_id": { "$ref": "#/$defs/identifier" },
25
- "executor_handle": { "$ref": "#/$defs/identifier" },
26
- "worktree_id": { "$ref": "#/$defs/identifier" },
27
- "base_sha": { "$ref": "#/$defs/gitSha" },
28
- "plan_epoch": { "type": "integer", "minimum": 0 },
29
- "packet_digest": {
30
- "$ref": "#/$defs/digest",
31
- "$comment": "Attribution to the received `executor_packet.v1`. This is the only link back to the dispatch."
32
- },
33
- "todo_id": {
34
- "$ref": "#/$defs/identifier",
35
- "$comment": "Carried through from `run_request.v1`. It is not qualified by any TODO store project/plan/revision identity, so a receipt alone does not prove which TODO store task it belongs to."
36
- },
37
- "checkpoint_digest": { "$ref": "#/$defs/digest" },
38
- "observed_diff": {
39
- "type": "array",
40
- "maxItems": 256,
41
- "items": {
42
- "type": "object",
43
- "additionalProperties": false,
44
- "required": ["path", "change"],
45
- "properties": {
46
- "path": { "$ref": "#/$defs/repoRelativePath" },
47
- "change": { "enum": ["added", "modified", "deleted"] }
48
- }
49
- }
50
- },
51
- "receipt_digest": { "$ref": "#/$defs/digest" }
52
- },
53
- "$defs": {
54
- "identifier": {
55
- "type": "string",
56
- "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$"
57
- },
58
- "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
59
- "gitSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
60
- "repoRelativePath": {
61
- "type": "string",
62
- "minLength": 1,
63
- "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.?(?:/|$))[^\\u0000-\\u001f\\u007f\\\\]+$"
64
- }
65
- }
66
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/kitepon-rgb/Lattice/blob/main/docs/schemas/lattice.executor_receipt.v1.schema.json",
4
+ "title": "lattice.executor_receipt.v1",
5
+ "description": "The receipt an executor returns for one dispatched packet. `packet_digest` is what attributes it to the packet it received.",
6
+ "$comment": "Runtime validation additionally enforces canonical JSON bytes and the self-digest rule for `receipt_digest`. Acceptance is decided by event order, not by the receipt's own claims: the binding is checked against the `executor_dispatched` / `epoch_rebound` event that recorded the handle, worktree and packet digest for that TODO.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": [
10
+ "schema",
11
+ "receipt_id",
12
+ "executor_handle",
13
+ "worktree_id",
14
+ "base_sha",
15
+ "plan_epoch",
16
+ "packet_digest",
17
+ "todo_id",
18
+ "checkpoint_digest",
19
+ "observed_diff",
20
+ "receipt_digest"
21
+ ],
22
+ "properties": {
23
+ "schema": { "const": "lattice.executor_receipt.v1" },
24
+ "receipt_id": { "$ref": "#/$defs/identifier" },
25
+ "executor_handle": { "$ref": "#/$defs/identifier" },
26
+ "worktree_id": { "$ref": "#/$defs/identifier" },
27
+ "base_sha": { "$ref": "#/$defs/gitSha" },
28
+ "plan_epoch": { "type": "integer", "minimum": 0 },
29
+ "packet_digest": {
30
+ "$ref": "#/$defs/digest",
31
+ "$comment": "Attribution to the received `executor_packet.v1`. This is the only link back to the dispatch."
32
+ },
33
+ "todo_id": {
34
+ "$ref": "#/$defs/identifier",
35
+ "$comment": "Carried through from `run_request.v1`. It is not qualified by any TODO store project/plan/revision identity, so a receipt alone does not prove which TODO store task it belongs to."
36
+ },
37
+ "checkpoint_digest": { "$ref": "#/$defs/digest" },
38
+ "observed_diff": {
39
+ "type": "array",
40
+ "maxItems": 256,
41
+ "items": {
42
+ "type": "object",
43
+ "additionalProperties": false,
44
+ "required": ["path", "change"],
45
+ "properties": {
46
+ "path": { "$ref": "#/$defs/repoRelativePath" },
47
+ "change": { "enum": ["added", "modified", "deleted"] }
48
+ }
49
+ }
50
+ },
51
+ "receipt_digest": { "$ref": "#/$defs/digest" }
52
+ },
53
+ "$defs": {
54
+ "identifier": {
55
+ "type": "string",
56
+ "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$"
57
+ },
58
+ "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
59
+ "gitSha": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
60
+ "repoRelativePath": {
61
+ "type": "string",
62
+ "minLength": 1,
63
+ "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.?(?:/|$))[^\\u0000-\\u001f\\u007f\\\\]+$"
64
+ }
65
+ }
66
+ }