fleetmesh-node 0.2.0__py3-none-any.whl

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 (338) hide show
  1. fleetmesh_node-0.2.0.dist-info/METADATA +57 -0
  2. fleetmesh_node-0.2.0.dist-info/RECORD +338 -0
  3. fleetmesh_node-0.2.0.dist-info/WHEEL +5 -0
  4. fleetmesh_node-0.2.0.dist-info/entry_points.txt +2 -0
  5. fleetmesh_node-0.2.0.dist-info/licenses/LICENSE +121 -0
  6. fleetmesh_node-0.2.0.dist-info/top_level.txt +2 -0
  7. node/RELEASE +1 -0
  8. node/__init__.py +35 -0
  9. node/app/__init__.py +49 -0
  10. node/app/commands.py +265 -0
  11. node/app/config.py +131 -0
  12. node/app/control.py +670 -0
  13. node/app/core.py +867 -0
  14. node/app/plugins.py +76 -0
  15. node/app/router.py +83 -0
  16. node/app/socket.py +431 -0
  17. node/app/systemd.py +36 -0
  18. node/app/views.py +204 -0
  19. node/channels/__init__.py +378 -0
  20. node/channels/bus.py +331 -0
  21. node/channels/journal.py +46 -0
  22. node/commands/__init__.py +140 -0
  23. node/commands/adapter.py +210 -0
  24. node/commands/base.py +278 -0
  25. node/commands/cluster_cmds.py +183 -0
  26. node/commands/compute_cmds.py +401 -0
  27. node/commands/core.py +474 -0
  28. node/commands/gossip_cmds.py +106 -0
  29. node/commands/nsite_cmds.py +141 -0
  30. node/commands/peering.py +402 -0
  31. node/commands/plugin_cmds.py +135 -0
  32. node/commands/sidecar_cmds.py +120 -0
  33. node/commands/sync.py +388 -0
  34. node/commands/transport_cmds.py +451 -0
  35. node/commands/video_cmds.py +99 -0
  36. node/compartment/__init__.py +124 -0
  37. node/compartment/base.py +868 -0
  38. node/compartment/command.py +458 -0
  39. node/compartment/context.py +163 -0
  40. node/compartment/every.py +108 -0
  41. node/compartment/handler.py +131 -0
  42. node/compartment/lifecycle.py +460 -0
  43. node/compartment/lint.py +388 -0
  44. node/compartment/need.py +158 -0
  45. node/compartment/problem.py +521 -0
  46. node/compartment/refusals.py +120 -0
  47. node/compartment/registry.py +790 -0
  48. node/compartment/schema.py +290 -0
  49. node/compartment/sidecar.py +499 -0
  50. node/compartment/stores.py +662 -0
  51. node/compartment/wire.py +225 -0
  52. node/compartment/worker.py +61 -0
  53. node/config/__init__.py +43 -0
  54. node/config/base.py +116 -0
  55. node/config/change.py +441 -0
  56. node/config/changestore.py +201 -0
  57. node/config/compartments.py +1144 -0
  58. node/config/node.py +318 -0
  59. node/config/parameter.py +563 -0
  60. node/config/protocols.py +274 -0
  61. node/config/records.py +171 -0
  62. node/examples/__init__.py +1 -0
  63. node/examples/demo.py +226 -0
  64. node/examples/follower.py +46 -0
  65. node/interfaces.py +235 -0
  66. node/keystore/__init__.py +27 -0
  67. node/keystore/core.py +103 -0
  68. node/keystore/enclave.py +688 -0
  69. node/meshnode.py +111 -0
  70. node/metrics/__init__.py +396 -0
  71. node/metrics/adapters.py +102 -0
  72. node/metrics/face.py +110 -0
  73. node/planes/__init__.py +21 -0
  74. node/planes/identity/__init__.py +20 -0
  75. node/planes/identity/announce/__init__.py +9 -0
  76. node/planes/identity/announce/compartment.py +447 -0
  77. node/planes/identity/announce/types.py +26 -0
  78. node/planes/identity/discovery/__init__.py +9 -0
  79. node/planes/identity/discovery/compartment.py +522 -0
  80. node/planes/identity/discovery/types.py +13 -0
  81. node/planes/identity/linked/__init__.py +1 -0
  82. node/planes/identity/linked/compartment.py +270 -0
  83. node/planes/identity/linked/types.py +25 -0
  84. node/planes/identity/presence/__init__.py +7 -0
  85. node/planes/identity/presence/compartment.py +409 -0
  86. node/planes/identity/presence/types.py +14 -0
  87. node/planes/operations/__init__.py +13 -0
  88. node/planes/operations/scheduler/__init__.py +9 -0
  89. node/planes/operations/scheduler/compartment.py +353 -0
  90. node/planes/operations/scheduler/types.py +21 -0
  91. node/planes/operations/updates/__init__.py +17 -0
  92. node/planes/operations/updates/core.py +310 -0
  93. node/planes/operations/updates/store.py +79 -0
  94. node/planes/operations/updates/types.py +20 -0
  95. node/planes/peering/__init__.py +28 -0
  96. node/planes/peering/budget/__init__.py +43 -0
  97. node/planes/peering/budget/chain.py +43 -0
  98. node/planes/peering/budget/core.py +537 -0
  99. node/planes/peering/budget/evaluation.py +80 -0
  100. node/planes/peering/budget/meter.py +100 -0
  101. node/planes/peering/budget/receipts.py +439 -0
  102. node/planes/peering/budget/shape.py +101 -0
  103. node/planes/peering/budget/tick.py +110 -0
  104. node/planes/peering/budget/types.py +67 -0
  105. node/planes/peering/budget/windows.py +346 -0
  106. node/planes/peering/capacity/__init__.py +7 -0
  107. node/planes/peering/capacity/compartment.py +342 -0
  108. node/planes/peering/capacity/types.py +24 -0
  109. node/planes/peering/peering/__init__.py +25 -0
  110. node/planes/peering/peering/core.py +464 -0
  111. node/planes/peering/peering/envelope.py +142 -0
  112. node/planes/peering/peering/handshake.py +198 -0
  113. node/planes/peering/peering/shape.py +80 -0
  114. node/planes/peering/peering/types.py +39 -0
  115. node/planes/peering/reporter/__init__.py +42 -0
  116. node/planes/peering/reporter/constants.py +29 -0
  117. node/planes/peering/reporter/core.py +299 -0
  118. node/planes/peering/reporter/finding.py +74 -0
  119. node/planes/peering/reporter/findings.py +171 -0
  120. node/planes/peering/reporter/publish.py +285 -0
  121. node/planes/peering/reporter/reading.py +193 -0
  122. node/planes/peering/reporter/shape.py +86 -0
  123. node/planes/peering/reporter/types.py +50 -0
  124. node/planes/peering/strain/__init__.py +9 -0
  125. node/planes/peering/strain/compartment.py +204 -0
  126. node/planes/peering/strain/types.py +21 -0
  127. node/planes/peering/trust/__init__.py +9 -0
  128. node/planes/peering/trust/compartment.py +239 -0
  129. node/planes/peering/trust/types.py +30 -0
  130. node/planes/services/__init__.py +33 -0
  131. node/planes/services/compute/__init__.py +160 -0
  132. node/planes/services/compute/common.py +134 -0
  133. node/planes/services/compute/compartment.py +681 -0
  134. node/planes/services/compute/executors/__init__.py +121 -0
  135. node/planes/services/compute/executors/agent.py +840 -0
  136. node/planes/services/compute/executors/bacalhau.py +605 -0
  137. node/planes/services/compute/executors/base.py +127 -0
  138. node/planes/services/compute/executors/harness.py +439 -0
  139. node/planes/services/compute/executors/mcp.py +454 -0
  140. node/planes/services/compute/executors/media.py +898 -0
  141. node/planes/services/compute/executors/nondet.py +283 -0
  142. node/planes/services/compute/executors/providers.py +499 -0
  143. node/planes/services/compute/executors/registry.py +140 -0
  144. node/planes/services/compute/executors/wasm.py +244 -0
  145. node/planes/services/compute/executors/zk.py +604 -0
  146. node/planes/services/compute/jobs.py +227 -0
  147. node/planes/services/compute/load.py +180 -0
  148. node/planes/services/compute/market.py +433 -0
  149. node/planes/services/compute/sandbox.py +282 -0
  150. node/planes/services/compute/types.py +84 -0
  151. node/planes/services/compute_wire/__init__.py +58 -0
  152. node/planes/services/compute_wire/compartment.py +256 -0
  153. node/planes/services/compute_wire/messages.py +320 -0
  154. node/planes/services/compute_wire/sealing.py +147 -0
  155. node/planes/services/compute_wire/session.py +572 -0
  156. node/planes/services/compute_wire/types.py +49 -0
  157. node/planes/services/compute_wire/verify.py +331 -0
  158. node/planes/services/dvm/__init__.py +24 -0
  159. node/planes/services/dvm/gateway.py +526 -0
  160. node/planes/services/dvm/protocol.py +35 -0
  161. node/planes/services/dvm/translate.py +15 -0
  162. node/planes/services/dvm/types.py +25 -0
  163. node/planes/services/gateway/__init__.py +40 -0
  164. node/planes/services/gateway/settle.py +279 -0
  165. node/planes/services/gateway/translate.py +644 -0
  166. node/planes/services/gossip/__init__.py +22 -0
  167. node/planes/services/gossip/core.py +929 -0
  168. node/planes/services/gossip/envelope.py +154 -0
  169. node/planes/services/gossip/mesh.py +127 -0
  170. node/planes/services/gossip/types.py +50 -0
  171. node/planes/services/nsite/__init__.py +7 -0
  172. node/planes/services/nsite/client.py +62 -0
  173. node/planes/services/nsite/compartment.py +752 -0
  174. node/planes/services/nsite/types.py +44 -0
  175. node/planes/services/paidfetch/__init__.py +7 -0
  176. node/planes/services/paidfetch/compartment.py +862 -0
  177. node/planes/services/paidfetch/types.py +99 -0
  178. node/planes/services/settle/__init__.py +27 -0
  179. node/planes/services/settle/compartment.py +384 -0
  180. node/planes/services/settle/engine.py +456 -0
  181. node/planes/services/settle/gateways.py +541 -0
  182. node/planes/services/settle/payment.py +512 -0
  183. node/planes/services/settle/store.py +74 -0
  184. node/planes/services/settle/types.py +58 -0
  185. node/planes/services/sidecars/__init__.py +8 -0
  186. node/planes/services/sidecars/compartment.py +461 -0
  187. node/planes/services/sidecars/manifest.py +304 -0
  188. node/planes/services/sidecars/manifests/10-grasp.json +37 -0
  189. node/planes/services/sidecars/manifests/20-ncontainer.json +31 -0
  190. node/planes/services/sidecars/manifests/30-magpie.json +28 -0
  191. node/planes/services/sidecars/types.py +43 -0
  192. node/planes/services/video/__init__.py +106 -0
  193. node/planes/services/video/barter.py +407 -0
  194. node/planes/services/video/cli.py +158 -0
  195. node/planes/services/video/compartment.py +932 -0
  196. node/planes/services/video/ingest.py +524 -0
  197. node/planes/services/video/ledger.py +705 -0
  198. node/planes/services/video/packager.py +847 -0
  199. node/planes/services/video/player.py +456 -0
  200. node/planes/services/video/timed_segments.py +124 -0
  201. node/planes/services/video/transit.py +478 -0
  202. node/planes/store/__init__.py +24 -0
  203. node/planes/store/blob_replication/__init__.py +7 -0
  204. node/planes/store/blob_replication/compartment.py +496 -0
  205. node/planes/store/blob_replication/types.py +35 -0
  206. node/planes/store/blob_wire/__init__.py +48 -0
  207. node/planes/store/blob_wire/client.py +57 -0
  208. node/planes/store/blob_wire/core.py +359 -0
  209. node/planes/store/blob_wire/intake.py +74 -0
  210. node/planes/store/blob_wire/messages.py +85 -0
  211. node/planes/store/projected/__init__.py +7 -0
  212. node/planes/store/projected/compartment.py +258 -0
  213. node/planes/store/projected/types.py +29 -0
  214. node/planes/store/retention/__init__.py +7 -0
  215. node/planes/store/retention/compartment.py +214 -0
  216. node/planes/store/retention/types.py +12 -0
  217. node/planes/store/sync/__init__.py +35 -0
  218. node/planes/store/sync/core.py +311 -0
  219. node/planes/store/sync/envelope.py +106 -0
  220. node/planes/store/sync/handover.py +206 -0
  221. node/planes/store/sync/initiator.py +128 -0
  222. node/planes/store/sync/responder.py +114 -0
  223. node/planes/store/sync/rules.py +179 -0
  224. node/planes/store/sync/shape.py +80 -0
  225. node/planes/store/sync/types.py +51 -0
  226. node/planes/transport/__init__.py +23 -0
  227. node/planes/transport/bridge/__init__.py +13 -0
  228. node/planes/transport/bridge/compartment.py +785 -0
  229. node/planes/transport/bridge/ratelimit.py +44 -0
  230. node/planes/transport/bridge/types.py +43 -0
  231. node/planes/transport/lan/__init__.py +9 -0
  232. node/planes/transport/lan/compartment.py +446 -0
  233. node/planes/transport/lan/types.py +25 -0
  234. node/planes/transport/link/__init__.py +7 -0
  235. node/planes/transport/link/compartment.py +257 -0
  236. node/planes/transport/link/types.py +27 -0
  237. node/planes/transport/mediation/__init__.py +45 -0
  238. node/planes/transport/mediation/compartment.py +238 -0
  239. node/planes/transport/mediation/leaf.py +107 -0
  240. node/planes/transport/mediation/messages.py +302 -0
  241. node/planes/transport/mediation/service.py +233 -0
  242. node/planes/transport/mediation/store.py +37 -0
  243. node/planes/transport/mediation/types.py +20 -0
  244. node/planes/transport/p2p/__init__.py +7 -0
  245. node/planes/transport/p2p/compartment.py +349 -0
  246. node/planes/transport/p2p/types.py +22 -0
  247. node/protocols/__init__.py +277 -0
  248. node/protocols/activitypub/__init__.py +56 -0
  249. node/protocols/activitypub/actor.py +230 -0
  250. node/protocols/activitypub/federation.py +490 -0
  251. node/protocols/activitypub/media.py +145 -0
  252. node/protocols/activitypub/models.py +286 -0
  253. node/protocols/activitypub/package.py +271 -0
  254. node/protocols/activitypub/store.py +564 -0
  255. node/protocols/arcade/__init__.py +26 -0
  256. node/protocols/atproto/__init__.py +13 -0
  257. node/protocols/atproto/firehose.py +126 -0
  258. node/protocols/atproto/metering.py +165 -0
  259. node/protocols/atproto/package.py +155 -0
  260. node/protocols/atproto/repo.py +250 -0
  261. node/protocols/atproto/xrpc.py +285 -0
  262. node/protocols/base.py +109 -0
  263. node/protocols/circles/__init__.py +29 -0
  264. node/protocols/dm/__init__.py +50 -0
  265. node/protocols/grasp/__init__.py +22 -0
  266. node/protocols/isotime.py +15 -0
  267. node/protocols/nostr/__init__.py +51 -0
  268. node/protocols/nostr/blobstore.py +383 -0
  269. node/protocols/nostr/blossom.py +627 -0
  270. node/protocols/nostr/client.py +377 -0
  271. node/protocols/nostr/descriptor.py +211 -0
  272. node/protocols/nostr/eventstore.py +304 -0
  273. node/protocols/nostr/package.py +182 -0
  274. node/protocols/nostr/peers.py +109 -0
  275. node/protocols/nostr/relayserver.py +656 -0
  276. node/protocols/p2panda/__init__.py +22 -0
  277. node/protocols/p2panda/identity.py +19 -0
  278. node/protocols/p2panda/package.py +236 -0
  279. node/protocols/p2panda/rung.py +152 -0
  280. node/protocols/p2panda/store.py +273 -0
  281. node/protocols/rhio/__init__.py +33 -0
  282. node/protocols/rhio/package.py +275 -0
  283. node/protocols/rhio/rung.py +136 -0
  284. node/protocols/rhio/store.py +1423 -0
  285. node/protocols/ssb/muxrpc.py +256 -0
  286. node/protocols/ssb/package.py +267 -0
  287. node/protocols/textile/__init__.py +111 -0
  288. node/protocols/textile/transducers.py +259 -0
  289. node/release.py +119 -0
  290. node/storage/__init__.py +88 -0
  291. node/storage/accounts.py +305 -0
  292. node/storage/adapter.py +161 -0
  293. node/storage/base.py +385 -0
  294. node/storage/dialect.py +209 -0
  295. node/storage/grants.py +317 -0
  296. node/storage/locator.py +150 -0
  297. node/storage/postgres.py +294 -0
  298. node/storage/projected.py +953 -0
  299. node/storage/sharding.py +448 -0
  300. node/storage/standing.py +568 -0
  301. node/testnet/__init__.py +9 -0
  302. node/testnet/cluster.py +731 -0
  303. node/testnet/fips_daemon.py +230 -0
  304. node/transport/__init__.py +94 -0
  305. node/transport/const.py +110 -0
  306. node/transport/didcomm_inbound.py +251 -0
  307. node/transport/dnstxt.py +169 -0
  308. node/transport/fips_rung/__init__.py +67 -0
  309. node/transport/fips_rung/core.py +666 -0
  310. node/transport/fips_rung/listener.py +96 -0
  311. node/transport/fips_rung/types.py +12 -0
  312. node/transport/host.py +334 -0
  313. node/transport/iroh_rung/__init__.py +29 -0
  314. node/transport/iroh_rung/core.py +477 -0
  315. node/transport/iroh_rung/quic.py +942 -0
  316. node/transport/iroh_rung/types.py +22 -0
  317. node/transport/ladder.py +145 -0
  318. node/transport/lineproto.py +49 -0
  319. node/transport/mdns.py +303 -0
  320. node/transport/netfetch.py +283 -0
  321. node/transport/relay_rung/__init__.py +23 -0
  322. node/transport/relay_rung/cooldown.py +87 -0
  323. node/transport/relay_rung/core.py +138 -0
  324. node/transport/relay_rung/inbound.py +161 -0
  325. node/transport/relay_rung/ledger.py +104 -0
  326. node/transport/relay_rung/listen.py +121 -0
  327. node/transport/relay_rung/outbound.py +181 -0
  328. node/transport/relay_rung/shape.py +71 -0
  329. node/transport/relay_rung/types.py +58 -0
  330. node/transport/relay_rung/wire.py +63 -0
  331. node/transport/router.py +761 -0
  332. node/transport/rung.py +276 -0
  333. node/transport/ssb_rung.py +166 -0
  334. node/transport/ws.py +502 -0
  335. sidecar/fleetmesh_announce.py +338 -0
  336. sidecar/fleetmesh_p2p.py +373 -0
  337. sidecar/fleetmesh_rhio.py +352 -0
  338. sidecar/fleetmesh_ssb.py +603 -0
@@ -0,0 +1,451 @@
1
+ """Transport CLI subcommands: FIPS native, Iroh QUIC, and Hardware Enclave."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import os
7
+ import time
8
+ from typing import Any, Mapping, TypedDict
9
+
10
+ from node.interfaces import DIDCommMessage
11
+ from node.config.parameter import Parameter
12
+ from .adapter import CommandDispatcher
13
+ from .base import add_command, emit, fail, load_json_arg, resolve_peer_or_raw
14
+
15
+
16
+ class FipsFlowInfo(TypedDict):
17
+ flow: str
18
+ fileno: int
19
+ status: str
20
+
21
+
22
+ def _message_arg(a: argparse.Namespace) -> DIDCommMessage | Mapping[str, Any]:
23
+ """--message as a DIDComm-ish body: JSON (inline or @file) when it parses,
24
+ otherwise wrapped as a raw string. Default is a ping."""
25
+ msg_str = getattr(a, 'message', None) or '{"type":"fleetmesh/ping"}'
26
+ return load_json_arg(msg_str, '--message', on_error=lambda raw: {'type': 'fleetmesh/raw', 'content': raw})
27
+
28
+
29
+ # ---- 1. Hardware Enclave ---------------------------------------------------
30
+
31
+ def _enclave_status(det: dict) -> None:
32
+ print('Hardware Enclave Status:')
33
+ print(' Platform: %s' % det['platform'])
34
+ print(' Hardware Tier: %s' % det['hardware_tier'])
35
+ print(' Apple Secure Enclave: %s' % ('present' if det['has_secure_enclave'] else 'absent'))
36
+ print(' Biometrics/TouchID: %s' % ('supported' if det['has_biometrics'] else 'absent'))
37
+ print(' Supported Curves: %s' % ', '.join(det['supported_curves']))
38
+
39
+
40
+ def _cmd_enclave_status(a: argparse.Namespace) -> int:
41
+ from node.keystore import enclave as enclave_mod
42
+ return emit(a, enclave_mod.detect_hardware_enclave(), _enclave_status)
43
+
44
+
45
+ def _cmd_enclave_generate(a: argparse.Namespace) -> int:
46
+ from node.keystore import enclave as enclave_mod
47
+ ktype = getattr(a, 'type', 'p256') or 'p256'
48
+ key = enclave_mod.EnclaveKey.generate(key_type=ktype)
49
+ res = {
50
+ 'key_id': key.key_id,
51
+ 'key_type': key.key_type,
52
+ 'hardware_tier': key.hardware_tier,
53
+ 'public_key_hex': key.public_key_hex,
54
+ 'multikey': key.multikey,
55
+ }
56
+
57
+ def generated(_: dict) -> None:
58
+ print('Generated Enclave Key:')
59
+ print(' ID: %s' % key.key_id)
60
+ print(' Type: %s (%s)' % (key.key_type, key.hardware_tier))
61
+ print(' Multikey: %s' % key.multikey)
62
+ return emit(a, res, generated)
63
+
64
+
65
+ def _cmd_enclave_sign(a: argparse.Namespace) -> int:
66
+ from node.keystore import enclave as enclave_mod
67
+ if not getattr(a, 'message', None):
68
+ fail('sign requires --message <text>')
69
+ key = enclave_mod.EnclaveKey.generate(key_type=getattr(a, 'type', 'p256') or 'p256')
70
+ msg = a.message.encode('utf-8')
71
+ sig = key.sign(msg)
72
+ res = {
73
+ 'message': a.message,
74
+ 'multikey': key.multikey,
75
+ 'signature_raw': sig.raw_signature.hex(),
76
+ 'attestation': sig.attestation,
77
+ }
78
+
79
+ def signed(_: dict) -> None:
80
+ print('Enclave Signature:')
81
+ print(' Multikey: %s' % key.multikey)
82
+ print(' Signature: %s' % sig.raw_signature.hex())
83
+ print(' Tier: %s' % sig.attestation.get('hardware_tier'))
84
+ return emit(a, res, signed)
85
+
86
+
87
+ def _cmd_enclave_verify(a: argparse.Namespace) -> int:
88
+ from node.keystore import enclave as enclave_mod
89
+ if not getattr(a, 'message', None) or not getattr(a, 'sig', None) or not getattr(a, 'pub', None):
90
+ fail('verify requires --message, --sig (hex), and --pub (multikey)')
91
+ msg = a.message.encode('utf-8')
92
+ try:
93
+ sig_bytes = bytes.fromhex(a.sig)
94
+ except Exception:
95
+ fail('sig must be a valid hex string')
96
+ ok_v, reason = enclave_mod.verify_signature(msg, a.pub, sig_bytes)
97
+ emit(a, {'valid': ok_v, 'reason': reason},
98
+ lambda _: print('Enclave Verification: %s (%s)' % ('VALID' if ok_v else 'INVALID', reason)), indent=None)
99
+ return 0 if ok_v else 1
100
+
101
+
102
+ enclave_dispatcher = CommandDispatcher('enclave', default_action='status')
103
+ enclave_dispatcher.add_custom('status', _cmd_enclave_status)
104
+ enclave_dispatcher.add_custom('generate', _cmd_enclave_generate, parameters=(
105
+ Parameter(key='type', name='type', description='enclave curve', type=str, default='p256', choices=('p256', 'secp256k1')),
106
+ ))
107
+ enclave_dispatcher.add_custom('sign', _cmd_enclave_sign, parameters=(
108
+ Parameter(key='type', name='type', description='enclave curve', type=str, default='p256', choices=('p256', 'secp256k1')),
109
+ Parameter(key='message', name='message', description='message string to sign or verify', type=str, default=''),
110
+ ))
111
+ enclave_dispatcher.add_custom('verify', _cmd_enclave_verify, parameters=(
112
+ Parameter(key='message', name='message', description='message string to sign or verify', type=str, default=''),
113
+ Parameter(key='sig', name='sig', description='hex signature to verify', type=str, default=''),
114
+ Parameter(key='pub', name='pub', description='public multikey string to verify', type=str, default=''),
115
+ ))
116
+
117
+
118
+ def cmd_enclave(a: argparse.Namespace) -> int:
119
+ return enclave_dispatcher.dispatch(a)
120
+
121
+
122
+ # ---- 2. Iroh QUIC Transport -------------------------------------------------
123
+
124
+ def _iroh_status(st: dict) -> None:
125
+ print('Iroh QUIC Engine Status:')
126
+ print(' Node ID: %s' % st['node_id'])
127
+ print(' Endpoint: %s' % st['endpoint'])
128
+ print(' Ticket: %s' % st['ticket'])
129
+ print(' ALPN: %s' % st['alpn'])
130
+ print(' Running: %s' % st['running'])
131
+
132
+
133
+ def _cmd_iroh_status(a: argparse.Namespace) -> int:
134
+ from node import keystore
135
+ from node.transport.iroh_rung import quic as iroh_live
136
+ ks = keystore.Keystore.load(a.dir)
137
+ host = getattr(a, 'host', '127.0.0.1') or '127.0.0.1'
138
+ port = getattr(a, 'port', 0) or 0
139
+ eng = iroh_live.IrohLiveEngine(node_id=ks.node_pk, host=host, port=port)
140
+ eng.start()
141
+ try:
142
+ return emit(a, eng.status(), _iroh_status)
143
+ finally:
144
+ eng.stop()
145
+
146
+
147
+ def _cmd_iroh_probe(a: argparse.Namespace) -> int:
148
+ from node import keystore
149
+ from node.transport.iroh_rung import quic as iroh_live
150
+ ks = keystore.Keystore.load(a.dir)
151
+ host = getattr(a, 'host', '127.0.0.1') or '127.0.0.1'
152
+ port = getattr(a, 'port', 9012) or 9012
153
+ eng = iroh_live.IrohLiveEngine(node_id=ks.node_pk, host='127.0.0.1', port=0)
154
+ eng.start()
155
+ try:
156
+ res = eng.probe_nat(host, port, timeout=2.0)
157
+
158
+ def probed(_: dict) -> None:
159
+ if res:
160
+ print('NAT Probe Successful:')
161
+ print(' Target: %s:%d' % (host, port))
162
+ print(' Reflexive: %s:%d' % (res[0], res[1]))
163
+ else:
164
+ print('NAT Probe Timeout: no response from %s:%d' % (host, port))
165
+ emit(a, {'probed': f"{host}:{port}", 'reflexive': f"{res[0]}:{res[1]}" if res else None}, probed, indent=None)
166
+ return 0 if res else 1
167
+ finally:
168
+ eng.stop()
169
+
170
+
171
+ def _cmd_iroh_punch(a: argparse.Namespace) -> int:
172
+ from node import keystore
173
+ from node.transport.iroh_rung import quic as iroh_live
174
+ ks = keystore.Keystore.load(a.dir)
175
+ host = getattr(a, 'host', '127.0.0.1') or '127.0.0.1'
176
+ port = getattr(a, 'port', 9012) or 9012
177
+ cnt = getattr(a, 'count', 5) or 5
178
+ eng = iroh_live.IrohLiveEngine(node_id=ks.node_pk, host='127.0.0.1', port=0)
179
+ eng.start()
180
+ try:
181
+ eng.punch_hole(host, port, count=cnt, interval=0.05)
182
+ return emit(a, {'punched': f"{host}:{port}", 'count': cnt},
183
+ lambda _: print('Punched %d UDP pinhole packets to %s:%d' % (cnt, host, port)), indent=None)
184
+ finally:
185
+ eng.stop()
186
+
187
+
188
+ def _cmd_iroh_send(a: argparse.Namespace) -> int:
189
+ from node import keystore
190
+ from node.transport.iroh_rung import quic as iroh_live
191
+ ks = keystore.Keystore.load(a.dir)
192
+ target = getattr(a, 'ticket', None) or getattr(a, 'to', None)
193
+ if not target:
194
+ fail('send requires --ticket <iroh_ticket> or --to <ticket/pubkey>')
195
+ msg_obj = _message_arg(a)
196
+
197
+ eng = iroh_live.IrohLiveEngine(node_id=ks.node_pk, host='127.0.0.1', port=0)
198
+ eng.start()
199
+ try:
200
+ conn = eng.get_or_connect(target)
201
+ raw = json.dumps(msg_obj).encode('utf-8')
202
+ sid = eng.send_stream(conn, raw)
203
+ return emit(a, {'ok': True, 'stream_id': sid, 'peer': f"{conn.remote_addr[0]}:{conn.remote_addr[1]}"},
204
+ lambda _: print('Sent QUIC stream %d to %s:%d (%d bytes)' % (sid, conn.remote_addr[0], conn.remote_addr[1], len(raw))),
205
+ indent=None)
206
+ finally:
207
+ eng.stop()
208
+
209
+
210
+ iroh_dispatcher = CommandDispatcher('iroh', default_action='status')
211
+ iroh_dispatcher.add_custom('status', _cmd_iroh_status, parameters=(
212
+ Parameter(key='host', name='host', description='remote host for probe/punch', type=str, default='127.0.0.1'),
213
+ Parameter(key='port', name='port', description='remote port for probe/punch', type=int, default=0),
214
+ ))
215
+ iroh_dispatcher.add_custom('probe', _cmd_iroh_probe, parameters=(
216
+ Parameter(key='host', name='host', description='remote host for probe/punch', type=str, default='127.0.0.1'),
217
+ Parameter(key='port', name='port', description='remote port for probe/punch', type=int, default=9012),
218
+ ))
219
+ iroh_dispatcher.add_custom('punch', _cmd_iroh_punch, parameters=(
220
+ Parameter(key='host', name='host', description='remote host for probe/punch', type=str, default='127.0.0.1'),
221
+ Parameter(key='port', name='port', description='remote port for probe/punch', type=int, default=9012),
222
+ Parameter(key='count', name='count', description='probe/punch packet count', type=int, default=5),
223
+ ))
224
+ iroh_dispatcher.add_custom('send', _cmd_iroh_send, parameters=(
225
+ Parameter(key='ticket', name='ticket', description='remote peer iroh ticket', type=str, default=''),
226
+ Parameter(key='to', name='to', description='recipient pubkey or ticket', type=str, default=''),
227
+ Parameter(key='message', name='message', description='message payload to transmit (JSON, @file, or raw text)', type=str, default=''),
228
+ ))
229
+
230
+
231
+ def cmd_iroh(a: argparse.Namespace) -> int:
232
+ return iroh_dispatcher.dispatch(a)
233
+
234
+
235
+ # ---- 3. FIPS Native Datagram Transport --------------------------------------
236
+
237
+ def _fips_status(info: dict) -> None:
238
+ print('FIPS Native Transport Status:')
239
+ print(' Socket Path: %s' % (info['socket_path'] or 'None'))
240
+ print(' Available: %s' % ('YES' if info['available'] else 'NO'))
241
+ print(' Connected: %s' % ('YES' if info.get('connected') else 'NO'))
242
+ print(' Default Port: %d' % info['default_port'])
243
+ if info.get('node_pk'):
244
+ print(' Node ID: %s' % info['node_pk'])
245
+ if info.get('error'):
246
+ print(' Error: %s' % info['error'])
247
+ elif not info['available']:
248
+ print(' Note: %s' % info['note'])
249
+
250
+
251
+ def _fips_flows(r: dict) -> None:
252
+ flows_info = r['flows']
253
+ print('Active FIPS Datagram Flows (%d):' % len(flows_info))
254
+ if not flows_info:
255
+ print(' (no active flows)')
256
+ else:
257
+ for f in flows_info:
258
+ print(' Flow %s [fd %d]: %s' % (f['flow'], f['fileno'], f['status']))
259
+
260
+
261
+ def _fips_context(a: argparse.Namespace) -> tuple[Any, str | None, int, Any]:
262
+ from node import keystore
263
+ from node.transport import fips_rung
264
+ sock_path = getattr(a, 'sock', None) or fips_rung.find_api_socket()
265
+ port = getattr(a, 'port', 11801) or 11801
266
+ ks = keystore.Keystore.load(a.dir) if hasattr(a, 'dir') and os.path.exists(os.path.join(a.dir, 'keys.json')) else None
267
+ return fips_rung, sock_path, port, ks
268
+
269
+
270
+ def _cmd_fips_status(a: argparse.Namespace) -> int:
271
+ fips_rung, sock_path, port, ks = _fips_context(a)
272
+ is_avail = bool(sock_path and os.path.exists(sock_path))
273
+ info = {
274
+ 'socket_path': sock_path,
275
+ 'available': is_avail,
276
+ 'default_port': port,
277
+ 'node_pk': ks.node_pk if ks else None,
278
+ 'active_flows': 0,
279
+ 'listeners': 0,
280
+ }
281
+ if is_avail:
282
+ try:
283
+ client = fips_rung.FipsNativeTransport(sock_path=sock_path)
284
+ client.connect()
285
+ info['connected'] = True
286
+ info['active_flows'] = len(client.open_flows)
287
+ info['listeners'] = len(client.listeners)
288
+ client.close()
289
+ except Exception as e:
290
+ info['connected'] = False
291
+ info['error'] = str(e)
292
+ else:
293
+ info['connected'] = False
294
+ info['note'] = 'FIPS control socket not found or daemon not running'
295
+ emit(a, info, _fips_status)
296
+ return 0 if info.get('connected') or info['available'] else 1
297
+
298
+
299
+ def _cmd_fips_flows(a: argparse.Namespace) -> int:
300
+ fips_rung, sock_path, _port, _ks = _fips_context(a)
301
+ sock_p = sock_path or fips_rung.find_api_socket()
302
+ flows_info: list[FipsFlowInfo] = []
303
+ if sock_p and os.path.exists(sock_p):
304
+ try:
305
+ client = fips_rung.FipsNativeTransport(sock_path=sock_p)
306
+ client.connect()
307
+ for key, sock in client.open_flows.items():
308
+ flows_info.append({'flow': key, 'fileno': sock.fileno(), 'status': 'open'})
309
+ client.close()
310
+ except Exception:
311
+ pass
312
+ return emit(a, {'flows': flows_info, 'count': len(flows_info)}, _fips_flows)
313
+
314
+
315
+ def _cmd_fips_connect(a: argparse.Namespace) -> int:
316
+ fips_rung, sock_path, port, _ks = _fips_context(a)
317
+ peer = getattr(a, 'peer', None)
318
+ if not peer:
319
+ fail('connect requires --peer <pubkey|npub|did>')
320
+ peer_pk = resolve_peer_or_raw(a, peer)
321
+ if not sock_path:
322
+ fail('FIPS control socket not found; pass --sock <path>')
323
+ client = fips_rung.FipsNativeTransport(sock_path=sock_path)
324
+ client.connect()
325
+ try:
326
+ flow_sock = client.open_flow(peer_pk, port=port)
327
+ res = {'ok': True, 'peer': peer_pk, 'port': port, 'fileno': flow_sock.fileno()}
328
+ return emit(a, res, lambda _: print('Connected FSP flow to %s:%d (fd %d)' % (peer_pk[:16], port, flow_sock.fileno())))
329
+ finally:
330
+ client.close()
331
+
332
+
333
+ def _cmd_fips_listen(a: argparse.Namespace) -> int:
334
+ fips_rung, sock_path, port, _ks = _fips_context(a)
335
+ if not sock_path:
336
+ fail('FIPS control socket not found; pass --sock <path>')
337
+ client = fips_rung.FipsNativeTransport(sock_path=sock_path)
338
+ client.connect()
339
+ try:
340
+ list_sock = client.listen_port(port=port)
341
+ res = {'ok': True, 'port': port, 'fileno': list_sock.fileno(), 'status': 'listening'}
342
+ return emit(a, res, lambda _: print('Bound FSP listener on port %d (fd %d)' % (port, list_sock.fileno())))
343
+ finally:
344
+ client.close()
345
+
346
+
347
+ def _cmd_fips_send(a: argparse.Namespace) -> int:
348
+ fips_rung, sock_path, port, ks = _fips_context(a)
349
+ peer = getattr(a, 'peer', None)
350
+ if not peer:
351
+ fail('send requires --peer <pubkey|npub|did>')
352
+ peer_pk = resolve_peer_or_raw(a, peer)
353
+ if not sock_path:
354
+ fail('FIPS control socket not found; pass --sock <path>')
355
+ msg_obj = dict(_message_arg(a))
356
+ msg_obj.setdefault('from', ks.did if ks else f'did:nostr:{peer_pk}')
357
+ msg_obj.setdefault('to', [f'did:nostr:{peer_pk}'])
358
+ msg_obj.setdefault('created_time', int(time.time()))
359
+ raw = json.dumps(msg_obj, separators=(',', ':'), sort_keys=True).encode('utf-8')
360
+
361
+ client = fips_rung.FipsNativeTransport(sock_path=sock_path)
362
+ client.connect()
363
+ try:
364
+ flow_sock = client.open_flow(peer_pk, port=port)
365
+ n_sent = client.send_framed(
366
+ flow_sock,
367
+ payload=raw,
368
+ flags=fips_rung.FLAG_DIDCOMM | fips_rung.FLAG_FINAL,
369
+ )
370
+ res = {'ok': True, 'peer': peer_pk, 'port': port, 'bytes_sent': n_sent}
371
+ time.sleep(0.02)
372
+ return emit(a, res, lambda _: print('Sent %d bytes over FSP flow to %s:%d' % (n_sent, peer_pk[:16], port)))
373
+ finally:
374
+ client.close()
375
+
376
+
377
+ def _cmd_fips_probe(a: argparse.Namespace) -> int:
378
+ fips_rung, sock_path, port, _ks = _fips_context(a)
379
+ t0 = time.time()
380
+ if not sock_path or not os.path.exists(sock_path):
381
+ emit(a, {'ok': False, 'error': f'control socket not found at {sock_path}'},
382
+ lambda _: print('FIPS Probe FAILED: control socket not accessible at %s' % sock_path))
383
+ return 1
384
+ try:
385
+ client = fips_rung.FipsNativeTransport(sock_path=sock_path)
386
+ client.connect()
387
+ rtt_ms = round((time.time() - t0) * 1000, 2)
388
+
389
+ def probed(_: dict) -> None:
390
+ print('FIPS Probe SUCCESSFUL:')
391
+ print(' Control Socket: %s' % sock_path)
392
+ print(' Probe RTT: %.2f ms' % rtt_ms)
393
+ print(' Status: ready')
394
+ emit(a, {'ok': True, 'rtt_ms': rtt_ms, 'sock': sock_path, 'port': port}, probed)
395
+ client.close()
396
+ return 0
397
+ except Exception as e:
398
+ err = str(e)
399
+ emit(a, {'ok': False, 'error': err}, lambda _: print('FIPS Probe FAILED: %s' % err))
400
+ return 1
401
+
402
+
403
+ fips_dispatcher = CommandDispatcher('fips', default_action='status')
404
+ fips_dispatcher.add_custom('status', _cmd_fips_status, parameters=(
405
+ Parameter(key='sock', name='sock', description='path to FIPS Unix control socket', type=str, default=''),
406
+ Parameter(key='port', name='port', description='FSP service port (default: 11801)', type=int, default=11801),
407
+ ))
408
+ fips_dispatcher.add_custom('flows', _cmd_fips_flows, parameters=(
409
+ Parameter(key='sock', name='sock', description='path to FIPS Unix control socket', type=str, default=''),
410
+ ))
411
+ fips_dispatcher.add_custom('connect', _cmd_fips_connect, parameters=(
412
+ Parameter(key='sock', name='sock', description='path to FIPS Unix control socket', type=str, default=''),
413
+ Parameter(key='port', name='port', description='FSP service port (default: 11801)', type=int, default=11801),
414
+ Parameter(key='peer', name='peer', description='peer pubkey, npub, or did:nostr', type=str, default=''),
415
+ ))
416
+ fips_dispatcher.add_custom('listen', _cmd_fips_listen, parameters=(
417
+ Parameter(key='sock', name='sock', description='path to FIPS Unix control socket', type=str, default=''),
418
+ Parameter(key='port', name='port', description='FSP service port (default: 11801)', type=int, default=11801),
419
+ ))
420
+ fips_dispatcher.add_custom('send', _cmd_fips_send, parameters=(
421
+ Parameter(key='sock', name='sock', description='path to FIPS Unix control socket', type=str, default=''),
422
+ Parameter(key='port', name='port', description='FSP service port (default: 11801)', type=int, default=11801),
423
+ Parameter(key='peer', name='peer', description='peer pubkey, npub, or did:nostr', type=str, default=''),
424
+ Parameter(key='message', name='message', description='message payload to transmit (JSON, @file, or raw text)', type=str, default=''),
425
+ ))
426
+ fips_dispatcher.add_custom('probe', _cmd_fips_probe, parameters=(
427
+ Parameter(key='sock', name='sock', description='path to FIPS Unix control socket', type=str, default=''),
428
+ Parameter(key='port', name='port', description='FSP service port (default: 11801)', type=int, default=11801),
429
+ Parameter(key='timeout', name='timeout', description='timeout in seconds', type=float, default=5.0),
430
+ ))
431
+
432
+
433
+ def cmd_fips(a: argparse.Namespace) -> int:
434
+ return fips_dispatcher.dispatch(a)
435
+
436
+
437
+ # ---- 4. Provider Registration -----------------------------------------------
438
+
439
+ class TransportCommandProvider:
440
+ """Registers transport diagnostic and control commands."""
441
+
442
+ @classmethod
443
+ def register(cls, sub: argparse._SubParsersAction) -> None:
444
+ en = add_command(sub, 'enclave', cmd_enclave, 'inspect and interact with hardware enclaves and passkeys', js=True)
445
+ enclave_dispatcher.register_arguments(en, action_choices=('status', 'generate', 'sign', 'verify'))
446
+
447
+ ir = add_command(sub, 'iroh', cmd_iroh, 'iroh P2P QUIC transport diagnostics and control', js=True)
448
+ iroh_dispatcher.register_arguments(ir, action_choices=('status', 'probe', 'punch', 'send'))
449
+
450
+ fp = add_command(sub, 'fips', cmd_fips, 'FIPS Native Datagram API transport diagnostics and control', js=True)
451
+ fips_dispatcher.register_arguments(fp, action_choices=('status', 'flows', 'connect', 'listen', 'send', 'probe'))
@@ -0,0 +1,99 @@
1
+ """video: live CMAF / LL-HLS video streams, Transit Reflector handovers, and barter settlement."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ from typing import Any, Mapping
6
+
7
+ from node.planes.services.video.compartment import VideoTransitCompartment
8
+ from .adapter import CommandDispatcher
9
+ from .base import add_command
10
+
11
+
12
+ def _show_status(r: Mapping[str, Any]) -> None:
13
+ print(
14
+ 'video streaming: %d active stream(s), %d reflector session(s)'
15
+ % (int(r.get('active_streams', 0)), len(r.get('reflector_sessions') or {}))
16
+ )
17
+ for s in r.get('streams') or []:
18
+ print(
19
+ ' stream %-24s segments=%d handover=%s'
20
+ % (
21
+ s.get('stream_id', ''),
22
+ int(s.get('segments_count', 0)),
23
+ 'engaged' if s.get('handover_active') else 'origin',
24
+ )
25
+ )
26
+ for d in r.get('debts') or []:
27
+ state_str = 'audio-only' if d.get('degraded_audio_only') else 'full'
28
+ print(
29
+ ' peer %-18s unsettled=%d B barter=%d B state=%s'
30
+ % (
31
+ str(d.get('debtor') or d.get('peer') or '')[:16],
32
+ int(d.get('unsettled_bytes', 0)),
33
+ int(d.get('bartered_bytes', 0)),
34
+ state_str,
35
+ )
36
+ )
37
+
38
+
39
+ def _show_started(r: Mapping[str, Any]) -> None:
40
+ print('started stream %s (%s)' % (r.get('stream_id', ''), r.get('title', '')))
41
+ print(' genesis op: %s (seq %s)' % (r.get('genesis_op_id', ''), r.get('seq_num', 0)))
42
+ print(' announced: %s' % ', '.join(r.get('announcements') or []))
43
+
44
+
45
+ def _show_settled(r: Mapping[str, Any]) -> None:
46
+ debt = r.get('debt_after') or {}
47
+ state_str = 'audio-only' if debt.get('degraded_audio_only') else 'full'
48
+ print(
49
+ 'credited %d transit bytes for %s via %s (%s units) -> state=%s'
50
+ % (
51
+ int(r.get('credited_bytes', 0)),
52
+ str(r.get('peer', ''))[:16],
53
+ r.get('utility_kind', ''),
54
+ r.get('units', 0),
55
+ state_str,
56
+ )
57
+ )
58
+
59
+
60
+ def _show_solicited(r: Mapping[str, Any]) -> None:
61
+ sol = r.get('solicitation') or {}
62
+ print(
63
+ 'transit solicitation for %s (mode=%s, sent=%s)'
64
+ % (sol.get('stream_id', ''), sol.get('mode', ''), bool(r.get('sent')))
65
+ )
66
+
67
+
68
+ _cmd_map = {c.key: c for c in VideoTransitCompartment.COMMANDS}
69
+ dispatcher = CommandDispatcher('video', default_action='status')
70
+ dispatcher.add_command('status', _cmd_map['status'], human=_show_status, timeout=10)
71
+ dispatcher.add_command('start', _cmd_map['start_stream'], human=lambda r, _a: _show_started(r), timeout=15)
72
+ dispatcher.add_command('settle', _cmd_map['settle'], human=lambda r, _a: _show_settled(r), timeout=15)
73
+ dispatcher.add_command('solicit', _cmd_map['solicit_transit'], human=lambda r, _a: _show_solicited(r), timeout=15)
74
+
75
+
76
+ def cmd_video(a: argparse.Namespace) -> int:
77
+ return dispatcher.dispatch(a)
78
+
79
+
80
+ class VideoCommandProvider:
81
+ """Registers the video streaming and transit reflector CLI commands."""
82
+
83
+ @classmethod
84
+ def register(cls, sub: argparse._SubParsersAction) -> None:
85
+ p = add_command(
86
+ sub,
87
+ 'stream',
88
+ cmd_video,
89
+ 'live CMAF/LL-HLS video streams, Transit Reflector handovers, and barter settlement',
90
+ js=True,
91
+ )
92
+ dispatcher.register_arguments(p, action_choices=('status', 'start', 'settle', 'solicit'))
93
+
94
+
95
+ __all__ = [
96
+ 'VideoCommandProvider',
97
+ 'cmd_video',
98
+ 'dispatcher',
99
+ ]
@@ -0,0 +1,124 @@
1
+ """The contract every mechanism in this node keeps, so that it can be watched.
2
+
3
+ A mechanism used to be wired in eight places: constructed in `NodeApp.start`,
4
+ hooked into `_tick`, given a key in `health`, a branch in the control dispatch,
5
+ a row in the control table, a function in the CLI, a registration beside it, and
6
+ a line in the README. Eight chances to forget one, and forgetting is silent.
7
+
8
+ There was a ninth place that did not exist, and its absence cost a night. When
9
+ `on_receipt` refused every receipt on a four-node mesh because the two ends
10
+ named different grants, it recorded nothing at all: every other divergent branch
11
+ counted a reason and that one did not, so an operator saw a window with no claim
12
+ and no explanation for it. A refusal that is not recorded is indistinguishable
13
+ from silence, and silence is the one thing this protocol is least able to read.
14
+
15
+ So a subsystem here declares what it is rather than being wired into what it is
16
+ part of:
17
+
18
+ name what it is called, on the wire of the control socket and the CLI
19
+ reads/live the config keys it reads, and which of those it re-reads on a tick
20
+ commands its own control surface, dispatched generically
21
+ tick its periodic work, returning what it did
22
+ state what it is, for monitoring
23
+ trouble what an operator should be told without asking
24
+ refusals every no it said, with the reason and enough detail to act
25
+
26
+ `Refusals` is the part that is new. Everything else already existed by
27
+ convention in one subsystem or another; this makes the convention checkable.
28
+
29
+ A package since the sixth surface (STORES) arrived: the abstract base is in
30
+ base.py where it can be read on its own, and the parts it is assembled from
31
+ each have a file -
32
+
33
+ base.py Compartment, the abstract base, and CompartmentProtocol
34
+ command.py Command, BoundCommand: what a compartment can be asked
35
+ refusals.py Refusals: every no it said
36
+ registry.py Registry: the node's compartments, and the verbs over them
37
+
38
+ Everything is re-exported here, so `from node.compartment import X` and
39
+ `compartment_mod.X` read as they always did.
40
+ """
41
+ from __future__ import annotations
42
+
43
+ from .base import Compartment, CompartmentProtocol
44
+ from .command import Alias, BoundCommand, Command, CommandError, CommandRecord, declared, every_command
45
+ from .every import Every
46
+ from .handler import Handler
47
+ from .need import Need
48
+ from .problem import (
49
+ DuplicateProblem,
50
+ IncompatibleProblem,
51
+ InvalidIdentifierProblem,
52
+ Note,
53
+ NoteList,
54
+ Problem,
55
+ Problems,
56
+ ReferenceProblem,
57
+ ShadowingProblem,
58
+ Trouble,
59
+ TroubleList,
60
+ TypeMismatchProblem,
61
+ )
62
+ from .refusals import Refusal, Refusals, why_detail
63
+ from .registry import Registry, T
64
+ from .schema import Column, Index, Migration, SchemaEntry, Table
65
+ from .wire import Outbound, WireClient, WireProtocol
66
+ from .worker import Worker
67
+ from .context import NodeContext, NodeStores
68
+ from . import context, lifecycle, sidecar, stores
69
+ from .lifecycle import (
70
+ CONFIGURED,
71
+ DEGRADED,
72
+ DRAINING,
73
+ FAILED,
74
+ QUARANTINED,
75
+ RETIRED,
76
+ RUNNING,
77
+ STATES,
78
+ WIRED,
79
+ Breaker,
80
+ Lifecycle,
81
+ Tracker,
82
+ Transition,
83
+ )
84
+ from .sidecar import Bridge, Sidecar, SidecarError, jsonline_call
85
+ from .stores import (
86
+ COUNTERS,
87
+ LRU,
88
+ MEMORY,
89
+ OLDEST,
90
+ REFUSE,
91
+ RING,
92
+ SET,
93
+ SNAPSHOT,
94
+ TABLE,
95
+ Counters,
96
+ Holdings,
97
+ Members,
98
+ Ring,
99
+ Store,
100
+ StoreFull,
101
+ Table as StoreTable,
102
+ )
103
+
104
+ __all__ = [
105
+ 'Alias', 'BoundCommand', 'Command', 'CommandError', 'CommandRecord', 'Compartment', 'CompartmentProtocol', 'Every',
106
+ 'Handler', 'Need', 'Refusal', 'Refusals', 'Registry', 'T', 'Worker', 'declared', 'every_command', 'why_detail',
107
+ 'Column', 'Index', 'Table', 'Migration', 'SchemaEntry',
108
+ 'Outbound', 'WireClient', 'WireProtocol',
109
+ 'Problem', 'Problems', 'DuplicateProblem', 'InvalidIdentifierProblem', 'ReferenceProblem',
110
+ 'TypeMismatchProblem', 'ShadowingProblem', 'IncompatibleProblem', 'Trouble', 'TroubleList',
111
+ 'Note', 'NoteList',
112
+ 'context', 'NodeContext', 'NodeStores',
113
+ 'lifecycle', 'stores', 'sidecar',
114
+ 'Breaker', 'Lifecycle', 'Tracker', 'Transition',
115
+ 'CONFIGURED', 'DEGRADED', 'DRAINING', 'FAILED', 'QUARANTINED', 'RETIRED', 'RUNNING', 'STATES', 'WIRED',
116
+ 'Bridge', 'Sidecar', 'SidecarError', 'jsonline_call',
117
+ 'Store', 'Ring', 'Members', 'Counters', 'Holdings', 'StoreFull', 'StoreTable',
118
+ 'RING', 'TABLE', 'SET', 'COUNTERS', 'OLDEST', 'LRU', 'REFUSE', 'MEMORY', 'SNAPSHOT',
119
+ ]
120
+
121
+
122
+
123
+
124
+