@ceralive/modem-control 0.2.0 → 1.1.0

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 (464) hide show
  1. package/README.md +317 -0
  2. package/dist/backend/at-lease.d.ts +57 -0
  3. package/dist/backend/at-lease.js +109 -0
  4. package/dist/backend/cell-info.d.ts +46 -0
  5. package/dist/backend/cell-info.js +124 -0
  6. package/dist/backend/constants.d.ts +24 -0
  7. package/{src/backend/constants.ts → dist/backend/constants.js} +4 -9
  8. package/dist/backend/device-classifier.d.ts +46 -0
  9. package/dist/backend/device-classifier.js +258 -0
  10. package/dist/backend/enrichment.d.ts +28 -0
  11. package/dist/backend/enrichment.js +59 -0
  12. package/dist/backend/features.d.ts +61 -0
  13. package/dist/backend/features.js +109 -0
  14. package/dist/backend/identity-ladder.d.ts +57 -0
  15. package/dist/backend/identity-ladder.js +158 -0
  16. package/dist/backend/identity-registry.d.ts +51 -0
  17. package/dist/backend/identity-registry.js +101 -0
  18. package/dist/backend/index.d.ts +30 -0
  19. package/dist/backend/index.js +35 -0
  20. package/dist/backend/lifecycle-interlock.d.ts +25 -0
  21. package/dist/backend/lifecycle-interlock.js +18 -0
  22. package/dist/backend/managed-objects.d.ts +39 -0
  23. package/dist/backend/managed-objects.js +82 -0
  24. package/dist/backend/mapping.d.ts +11 -0
  25. package/dist/backend/mapping.js +148 -0
  26. package/dist/backend/mm-backend.d.ts +44 -0
  27. package/dist/backend/mm-backend.js +154 -0
  28. package/dist/backend/mm-location.d.ts +21 -0
  29. package/dist/backend/mm-location.js +237 -0
  30. package/dist/backend/mm-mutations.d.ts +42 -0
  31. package/dist/backend/mm-mutations.js +259 -0
  32. package/dist/backend/modem-actor.d.ts +41 -0
  33. package/dist/backend/modem-actor.js +78 -0
  34. package/dist/backend/nm-auto-apn.d.ts +54 -0
  35. package/dist/backend/nm-auto-apn.js +124 -0
  36. package/dist/backend/nm-gsm-fields.d.ts +23 -0
  37. package/dist/backend/nm-gsm-fields.js +107 -0
  38. package/dist/backend/nmcli-nm-port.d.ts +28 -0
  39. package/dist/backend/nmcli-nm-port.js +173 -0
  40. package/dist/backend/nmcli-runner.d.ts +24 -0
  41. package/dist/backend/nmcli-runner.js +35 -0
  42. package/dist/backend/observer.d.ts +37 -0
  43. package/dist/backend/observer.js +219 -0
  44. package/dist/backend/power-contract.d.ts +49 -0
  45. package/dist/backend/power-contract.js +34 -0
  46. package/dist/backend/recovery-attribution.d.ts +32 -0
  47. package/dist/backend/recovery-attribution.js +57 -0
  48. package/dist/backend/recovery-budget.d.ts +45 -0
  49. package/dist/backend/recovery-budget.js +44 -0
  50. package/dist/backend/recovery-ladder.d.ts +94 -0
  51. package/dist/backend/recovery-ladder.js +116 -0
  52. package/dist/backend/router-ethernet.d.ts +19 -0
  53. package/dist/backend/router-ethernet.js +66 -0
  54. package/dist/backend/row-store.d.ts +13 -0
  55. package/dist/backend/row-store.js +82 -0
  56. package/dist/backend/signal-setup.d.ts +30 -0
  57. package/dist/backend/signal-setup.js +92 -0
  58. package/dist/backend/sim-unlock.d.ts +13 -0
  59. package/dist/backend/sim-unlock.js +153 -0
  60. package/dist/backend/transition-preconditions.d.ts +76 -0
  61. package/dist/backend/transition-preconditions.js +64 -0
  62. package/dist/backend/usage/accounting.d.ts +39 -0
  63. package/dist/backend/usage/accounting.js +73 -0
  64. package/dist/backend/usage/billing-cycle.d.ts +11 -0
  65. package/dist/backend/usage/billing-cycle.js +39 -0
  66. package/dist/backend/usage/boot-id.d.ts +6 -0
  67. package/{src/backend/usage/boot-id.ts → dist/backend/usage/boot-id.js} +7 -7
  68. package/dist/backend/usage/index.d.ts +8 -0
  69. package/dist/backend/usage/index.js +11 -0
  70. package/dist/backend/usage/policy-store.d.ts +50 -0
  71. package/dist/backend/usage/policy-store.js +161 -0
  72. package/dist/backend/usage/policy-write.d.ts +65 -0
  73. package/dist/backend/usage/policy-write.js +112 -0
  74. package/dist/backend/usage/proc-net-dev.d.ts +18 -0
  75. package/{src/backend/usage/proc-net-dev.ts → dist/backend/usage/proc-net-dev.js} +39 -47
  76. package/dist/backend/usage/sampler.d.ts +75 -0
  77. package/dist/backend/usage/sampler.js +211 -0
  78. package/dist/backend/usage/store.d.ts +38 -0
  79. package/dist/backend/usage/store.js +126 -0
  80. package/dist/backend/usb-device-snapshot.d.ts +31 -0
  81. package/dist/backend/usb-device-snapshot.js +1 -0
  82. package/dist/backend/usb-enumerator.d.ts +21 -0
  83. package/dist/backend/usb-enumerator.js +153 -0
  84. package/dist/backend/usb-mode-transition.d.ts +29 -0
  85. package/dist/backend/usb-mode-transition.js +196 -0
  86. package/dist/band/band-names.d.ts +42 -0
  87. package/dist/band/band-names.js +150 -0
  88. package/dist/band/certification.d.ts +84 -0
  89. package/dist/band/certification.js +127 -0
  90. package/dist/band/certified-bands.json +4 -0
  91. package/dist/band/index.d.ts +2 -0
  92. package/dist/band/index.js +8 -0
  93. package/dist/capability/detect.d.ts +52 -0
  94. package/dist/capability/detect.js +86 -0
  95. package/dist/capability/five-g-preference.d.ts +104 -0
  96. package/dist/capability/five-g-preference.js +171 -0
  97. package/dist/capability/index.d.ts +3 -0
  98. package/dist/capability/index.js +10 -0
  99. package/dist/capability/support-claim.d.ts +39 -0
  100. package/dist/capability/support-claim.js +81 -0
  101. package/dist/domain/brand.d.ts +10 -0
  102. package/dist/domain/brand.js +21 -0
  103. package/dist/domain/errors.d.ts +32 -0
  104. package/dist/domain/errors.js +48 -0
  105. package/dist/domain/generation.d.ts +8 -0
  106. package/dist/domain/generation.js +12 -0
  107. package/dist/domain/guards.d.ts +6 -0
  108. package/dist/domain/guards.js +127 -0
  109. package/dist/domain/identity.d.ts +109 -0
  110. package/dist/domain/identity.js +86 -0
  111. package/dist/domain/index.d.ts +14 -0
  112. package/dist/domain/index.js +18 -0
  113. package/dist/domain/mm-enums.d.ts +12 -0
  114. package/dist/domain/mm-enums.js +139 -0
  115. package/dist/domain/modem-presentation.d.ts +10 -0
  116. package/dist/domain/modem-presentation.js +39 -0
  117. package/dist/domain/observation.d.ts +39 -0
  118. package/dist/domain/observation.js +4 -0
  119. package/dist/domain/operation.d.ts +118 -0
  120. package/dist/domain/operation.js +85 -0
  121. package/dist/domain/physical-identity.d.ts +43 -0
  122. package/dist/domain/physical-identity.js +113 -0
  123. package/{src/domain/policy.ts → dist/domain/policy.d.ts} +34 -69
  124. package/dist/domain/policy.js +38 -0
  125. package/dist/domain/shadow-divergence.d.ts +27 -0
  126. package/dist/domain/shadow-divergence.js +70 -0
  127. package/dist/domain/snapshot.d.ts +53 -0
  128. package/dist/domain/snapshot.js +75 -0
  129. package/{src/domain/state.ts → dist/domain/state.d.ts} +23 -122
  130. package/dist/domain/state.js +38 -0
  131. package/dist/fcc/coverage.d.ts +63 -0
  132. package/dist/fcc/coverage.js +102 -0
  133. package/dist/fcc/index.d.ts +3 -0
  134. package/dist/fcc/index.js +12 -0
  135. package/dist/fcc/policy-store.d.ts +40 -0
  136. package/dist/fcc/policy-store.js +146 -0
  137. package/dist/fcc/policy-write.d.ts +32 -0
  138. package/dist/fcc/policy-write.js +37 -0
  139. package/dist/hardware/hilink-protocol.d.ts +39 -0
  140. package/dist/hardware/hilink-protocol.js +58 -0
  141. package/dist/hardware/index.d.ts +3 -0
  142. package/dist/hardware/index.js +15 -0
  143. package/dist/hardware/router-parsers.d.ts +89 -0
  144. package/dist/hardware/router-parsers.js +234 -0
  145. package/dist/index.d.ts +19 -0
  146. package/dist/index.js +26 -0
  147. package/dist/journal/codec.d.ts +44 -0
  148. package/dist/journal/codec.js +198 -0
  149. package/dist/journal/engine.d.ts +28 -0
  150. package/dist/journal/engine.js +68 -0
  151. package/dist/journal/entry.d.ts +74 -0
  152. package/dist/journal/entry.js +56 -0
  153. package/dist/journal/index.d.ts +6 -0
  154. package/dist/journal/index.js +6 -0
  155. package/dist/journal/legacy-ceraui.d.ts +73 -0
  156. package/dist/journal/legacy-ceraui.js +227 -0
  157. package/dist/journal/recovery.d.ts +58 -0
  158. package/dist/journal/recovery.js +117 -0
  159. package/dist/journal/store.d.ts +55 -0
  160. package/dist/journal/store.js +150 -0
  161. package/dist/location/fix-state.d.ts +53 -0
  162. package/dist/location/fix-state.js +75 -0
  163. package/dist/location/index.d.ts +2 -0
  164. package/dist/location/index.js +8 -0
  165. package/dist/location/nmea.d.ts +10 -0
  166. package/dist/location/nmea.js +89 -0
  167. package/dist/observations/envelope.d.ts +63 -0
  168. package/dist/observations/envelope.js +77 -0
  169. package/dist/observations/freshness.d.ts +28 -0
  170. package/dist/observations/freshness.js +76 -0
  171. package/dist/observations/index.d.ts +13 -0
  172. package/dist/observations/index.js +24 -0
  173. package/dist/observations/metric.d.ts +47 -0
  174. package/dist/observations/metric.js +73 -0
  175. package/dist/observations/model.d.ts +80 -0
  176. package/dist/observations/model.js +11 -0
  177. package/dist/observations/provenance.d.ts +94 -0
  178. package/dist/observations/provenance.js +67 -0
  179. package/dist/observations/raw.d.ts +42 -0
  180. package/dist/observations/raw.js +146 -0
  181. package/dist/observations/reading.d.ts +51 -0
  182. package/dist/observations/reading.js +65 -0
  183. package/dist/observations/sources/hilink.d.ts +10 -0
  184. package/dist/observations/sources/hilink.js +84 -0
  185. package/dist/observations/sources/modemmanager.d.ts +18 -0
  186. package/dist/observations/sources/modemmanager.js +239 -0
  187. package/dist/observations/sources/router-shared.d.ts +29 -0
  188. package/dist/observations/sources/router-shared.js +68 -0
  189. package/dist/observations/sources/ufi.d.ts +10 -0
  190. package/dist/observations/sources/ufi.js +111 -0
  191. package/dist/observations/sources/zte.d.ts +7 -0
  192. package/dist/observations/sources/zte.js +71 -0
  193. package/dist/observations/state-separation.d.ts +64 -0
  194. package/dist/observations/state-separation.js +52 -0
  195. package/dist/operations/contracts.d.ts +72 -0
  196. package/dist/operations/contracts.js +1 -0
  197. package/dist/operations/index.d.ts +1 -0
  198. package/dist/operations/index.js +1 -0
  199. package/dist/operations/operation-engine.d.ts +16 -0
  200. package/dist/operations/operation-engine.js +194 -0
  201. package/dist/ports/index.d.ts +12 -0
  202. package/{src/ports/index.ts → dist/ports/index.js} +12 -8
  203. package/dist/ports/location.d.ts +87 -0
  204. package/dist/ports/location.js +36 -0
  205. package/dist/ports/modem-manager.d.ts +89 -0
  206. package/dist/ports/modem-manager.js +9 -0
  207. package/dist/ports/mutation-admission.d.ts +27 -0
  208. package/dist/ports/mutation-admission.js +9 -0
  209. package/dist/ports/network-manager.d.ts +68 -0
  210. package/dist/ports/network-manager.js +13 -0
  211. package/{src/ports/observation.ts → dist/ports/observation.d.ts} +16 -27
  212. package/dist/ports/observation.js +7 -0
  213. package/dist/ports/ops.d.ts +44 -0
  214. package/dist/ports/ops.js +16 -0
  215. package/{src/ports/receipts.ts → dist/ports/receipts.d.ts} +5 -27
  216. package/dist/ports/receipts.js +9 -0
  217. package/dist/ports/reconcile.d.ts +33 -0
  218. package/dist/ports/reconcile.js +200 -0
  219. package/dist/ports/resource-ownership.d.ts +29 -0
  220. package/dist/ports/resource-ownership.js +1 -0
  221. package/dist/ports/router.d.ts +19 -0
  222. package/dist/ports/router.js +7 -0
  223. package/dist/ports/sms.d.ts +64 -0
  224. package/dist/ports/sms.js +24 -0
  225. package/dist/ports/uhubctl.d.ts +6 -0
  226. package/dist/ports/uhubctl.js +1 -0
  227. package/dist/providers/contracts.d.ts +124 -0
  228. package/dist/providers/contracts.js +10 -0
  229. package/dist/providers/huawei-hilink/index.d.ts +2 -0
  230. package/dist/providers/huawei-hilink/index.js +2 -0
  231. package/dist/providers/huawei-hilink/operations.d.ts +20 -0
  232. package/dist/providers/huawei-hilink/operations.js +56 -0
  233. package/dist/providers/huawei-hilink/provider.d.ts +52 -0
  234. package/dist/providers/huawei-hilink/provider.js +76 -0
  235. package/dist/providers/huawei-hilink/runtime.d.ts +22 -0
  236. package/dist/providers/huawei-hilink/runtime.js +171 -0
  237. package/dist/providers/huawei-hilink/session.d.ts +28 -0
  238. package/dist/providers/huawei-hilink/session.js +120 -0
  239. package/dist/providers/huawei-hilink/transport.d.ts +19 -0
  240. package/dist/providers/huawei-hilink/transport.js +1 -0
  241. package/dist/providers/index.d.ts +8 -0
  242. package/dist/providers/index.js +8 -0
  243. package/dist/providers/matcher.d.ts +3 -0
  244. package/dist/providers/matcher.js +205 -0
  245. package/dist/providers/modem-manager/errors.d.ts +7 -0
  246. package/dist/providers/modem-manager/errors.js +37 -0
  247. package/dist/providers/modem-manager/generic-operations.d.ts +8 -0
  248. package/dist/providers/modem-manager/generic-operations.js +207 -0
  249. package/dist/providers/modem-manager/index.d.ts +3 -0
  250. package/dist/providers/modem-manager/index.js +3 -0
  251. package/dist/providers/modem-manager/module-operations.d.ts +21 -0
  252. package/dist/providers/modem-manager/module-operations.js +118 -0
  253. package/dist/providers/modem-manager/provider.d.ts +39 -0
  254. package/dist/providers/modem-manager/provider.js +152 -0
  255. package/dist/providers/modem-manager/snapshot.d.ts +5 -0
  256. package/dist/providers/modem-manager/snapshot.js +204 -0
  257. package/dist/providers/modem-manager/types.d.ts +135 -0
  258. package/dist/providers/modem-manager/types.js +1 -0
  259. package/dist/providers/network-manager/adapter.d.ts +71 -0
  260. package/dist/providers/network-manager/adapter.js +348 -0
  261. package/dist/providers/network-manager/index.d.ts +2 -0
  262. package/dist/providers/network-manager/index.js +2 -0
  263. package/dist/providers/network-manager/types.d.ts +163 -0
  264. package/dist/providers/network-manager/types.js +77 -0
  265. package/dist/providers/registry.d.ts +13 -0
  266. package/dist/providers/registry.js +33 -0
  267. package/dist/providers/ufi-himi/index.d.ts +6 -0
  268. package/dist/providers/ufi-himi/index.js +6 -0
  269. package/dist/providers/ufi-himi/operations.d.ts +41 -0
  270. package/dist/providers/ufi-himi/operations.js +66 -0
  271. package/dist/providers/ufi-himi/prohibitions.d.ts +62 -0
  272. package/dist/providers/ufi-himi/prohibitions.js +88 -0
  273. package/dist/providers/ufi-himi/provider.d.ts +41 -0
  274. package/dist/providers/ufi-himi/provider.js +204 -0
  275. package/dist/providers/ufi-himi/qualcomm-evidence.d.ts +32 -0
  276. package/dist/providers/ufi-himi/qualcomm-evidence.js +51 -0
  277. package/dist/providers/ufi-himi/session.d.ts +46 -0
  278. package/dist/providers/ufi-himi/session.js +92 -0
  279. package/dist/providers/ufi-himi/transport.d.ts +29 -0
  280. package/dist/providers/ufi-himi/transport.js +25 -0
  281. package/dist/providers/zte-goform/index.d.ts +2 -0
  282. package/dist/providers/zte-goform/index.js +2 -0
  283. package/dist/providers/zte-goform/provider.d.ts +51 -0
  284. package/dist/providers/zte-goform/provider.js +101 -0
  285. package/dist/providers/zte-goform/session.d.ts +17 -0
  286. package/dist/providers/zte-goform/session.js +133 -0
  287. package/dist/providers/zte-goform/transport.d.ts +16 -0
  288. package/dist/providers/zte-goform/transport.js +1 -0
  289. package/dist/radio/band-truth.d.ts +50 -0
  290. package/dist/radio/band-truth.js +92 -0
  291. package/dist/radio/index.d.ts +3 -0
  292. package/dist/radio/index.js +10 -0
  293. package/dist/radio/mode-combinations.d.ts +78 -0
  294. package/dist/radio/mode-combinations.js +198 -0
  295. package/dist/radio/mode-truth.d.ts +67 -0
  296. package/dist/radio/mode-truth.js +112 -0
  297. package/dist/redact.d.ts +15 -0
  298. package/dist/redact.js +189 -0
  299. package/dist/safety/composition-root.d.ts +28 -0
  300. package/dist/safety/composition-root.js +65 -0
  301. package/dist/safety/flock-resource-ownership.d.ts +11 -0
  302. package/dist/safety/flock-resource-ownership.js +151 -0
  303. package/dist/safety/index.d.ts +2 -0
  304. package/dist/safety/index.js +2 -0
  305. package/dist/sms/dbus-messaging.d.ts +17 -0
  306. package/dist/sms/dbus-messaging.js +185 -0
  307. package/dist/sms/inbox-store.d.ts +10 -0
  308. package/dist/sms/inbox-store.js +82 -0
  309. package/dist/sms/index.d.ts +4 -0
  310. package/dist/sms/index.js +10 -0
  311. package/dist/sms/mmcli-parse.d.ts +54 -0
  312. package/dist/sms/mmcli-parse.js +224 -0
  313. package/dist/sms/normalize.d.ts +42 -0
  314. package/dist/sms/normalize.js +95 -0
  315. package/dist/testing/domain-fakes.d.ts +58 -0
  316. package/dist/testing/domain-fakes.js +98 -0
  317. package/dist/testing/index.d.ts +2 -0
  318. package/dist/testing/index.js +17 -0
  319. package/dist/testing/provider-fakes.d.ts +45 -0
  320. package/dist/testing/provider-fakes.js +64 -0
  321. package/dist/transport/calls.d.ts +9 -0
  322. package/dist/transport/calls.js +88 -0
  323. package/dist/transport/codec.d.ts +3 -0
  324. package/dist/transport/codec.js +207 -0
  325. package/dist/transport/dbus-native.d.ts +57 -0
  326. package/dist/transport/dbus-native.js +17 -0
  327. package/dist/transport/errors.d.ts +21 -0
  328. package/{src/transport/errors.ts → dist/transport/errors.js} +34 -46
  329. package/dist/transport/index.d.ts +4 -0
  330. package/dist/transport/index.js +9 -0
  331. package/dist/transport/signals.d.ts +15 -0
  332. package/dist/transport/signals.js +123 -0
  333. package/dist/transport/signature.d.ts +7 -0
  334. package/dist/transport/signature.js +94 -0
  335. package/dist/transport/transport.d.ts +2 -0
  336. package/dist/transport/transport.js +202 -0
  337. package/dist/transport/types.d.ts +61 -0
  338. package/dist/transport/types.js +19 -0
  339. package/dist/usb-mode/catalog-schema.d.ts +139 -0
  340. package/dist/usb-mode/catalog-schema.js +97 -0
  341. package/dist/usb-mode/catalog.d.ts +21 -0
  342. package/{src/usb-mode/catalog.ts → dist/usb-mode/catalog.js} +10 -32
  343. package/dist/usb-mode/certified-catalog.json +67 -0
  344. package/dist/usb-mode/index.d.ts +5 -0
  345. package/dist/usb-mode/index.js +15 -0
  346. package/dist/usb-mode/ingestion.d.ts +111 -0
  347. package/dist/usb-mode/ingestion.js +187 -0
  348. package/dist/usb-mode/promotion-review.d.ts +21 -0
  349. package/dist/usb-mode/promotion-review.js +87 -0
  350. package/dist/usb-mode/usb-devices-parse.d.ts +36 -0
  351. package/dist/usb-mode/usb-devices-parse.js +157 -0
  352. package/dist/ussd/calls.d.ts +32 -0
  353. package/dist/ussd/calls.js +96 -0
  354. package/dist/ussd/index.d.ts +5 -0
  355. package/dist/ussd/index.js +12 -0
  356. package/dist/ussd/mm-ussd.d.ts +37 -0
  357. package/dist/ussd/mm-ussd.js +205 -0
  358. package/dist/ussd/refusal.d.ts +53 -0
  359. package/dist/ussd/refusal.js +154 -0
  360. package/dist/ussd/registration.d.ts +20 -0
  361. package/dist/ussd/registration.js +101 -0
  362. package/dist/ussd/session.d.ts +84 -0
  363. package/dist/ussd/session.js +163 -0
  364. package/package.json +38 -4
  365. package/src/backend/at-lease.test.ts +0 -106
  366. package/src/backend/at-lease.ts +0 -158
  367. package/src/backend/cell-info.test.ts +0 -154
  368. package/src/backend/cell-info.ts +0 -160
  369. package/src/backend/device-classifier.test.ts +0 -168
  370. package/src/backend/device-classifier.ts +0 -248
  371. package/src/backend/enrichment.ts +0 -96
  372. package/src/backend/features.test.ts +0 -162
  373. package/src/backend/features.ts +0 -179
  374. package/src/backend/identity-ladder.test.ts +0 -117
  375. package/src/backend/identity-ladder.ts +0 -221
  376. package/src/backend/identity-registry.test.ts +0 -89
  377. package/src/backend/identity-registry.ts +0 -151
  378. package/src/backend/index.ts +0 -221
  379. package/src/backend/lifecycle-interlock.ts +0 -38
  380. package/src/backend/managed-objects.ts +0 -108
  381. package/src/backend/mapping.ts +0 -160
  382. package/src/backend/mm-backend.ts +0 -191
  383. package/src/backend/mm-mutations.ts +0 -228
  384. package/src/backend/modem-actor.test.ts +0 -95
  385. package/src/backend/modem-actor.ts +0 -112
  386. package/src/backend/nm-auto-apn.ts +0 -161
  387. package/src/backend/nm-gsm-fields.ts +0 -122
  388. package/src/backend/nmcli-nm-port.ts +0 -228
  389. package/src/backend/nmcli-runner.ts +0 -52
  390. package/src/backend/observer.ts +0 -297
  391. package/src/backend/power-contract.test.ts +0 -40
  392. package/src/backend/power-contract.ts +0 -83
  393. package/src/backend/recovery-attribution.test.ts +0 -102
  394. package/src/backend/recovery-attribution.ts +0 -86
  395. package/src/backend/recovery-budget.test.ts +0 -64
  396. package/src/backend/recovery-budget.ts +0 -84
  397. package/src/backend/recovery-ladder.test.ts +0 -257
  398. package/src/backend/recovery-ladder.ts +0 -249
  399. package/src/backend/router-ethernet.test.ts +0 -71
  400. package/src/backend/router-ethernet.ts +0 -90
  401. package/src/backend/row-store.ts +0 -105
  402. package/src/backend/signal-setup.ts +0 -112
  403. package/src/backend/sim-unlock.ts +0 -193
  404. package/src/backend/transition-preconditions.ts +0 -149
  405. package/src/backend/usage/accounting.test.ts +0 -147
  406. package/src/backend/usage/accounting.ts +0 -123
  407. package/src/backend/usage/billing-cycle.test.ts +0 -62
  408. package/src/backend/usage/billing-cycle.ts +0 -45
  409. package/src/backend/usage/index.ts +0 -37
  410. package/src/backend/usage/proc-net-dev.test.ts +0 -56
  411. package/src/backend/usage/sampler.test.ts +0 -219
  412. package/src/backend/usage/sampler.ts +0 -228
  413. package/src/backend/usage/store.test.ts +0 -148
  414. package/src/backend/usage/store.ts +0 -177
  415. package/src/backend/usb-enumerator.test.ts +0 -87
  416. package/src/backend/usb-enumerator.ts +0 -181
  417. package/src/backend/usb-mode-transition.test.ts +0 -323
  418. package/src/backend/usb-mode-transition.ts +0 -253
  419. package/src/domain/brand.ts +0 -29
  420. package/src/domain/errors.ts +0 -77
  421. package/src/domain/guards.test.ts +0 -218
  422. package/src/domain/guards.ts +0 -144
  423. package/src/domain/identity.test.ts +0 -83
  424. package/src/domain/identity.ts +0 -165
  425. package/src/domain/index.ts +0 -12
  426. package/src/domain/snapshot.test.ts +0 -266
  427. package/src/domain/snapshot.ts +0 -120
  428. package/src/index.test.ts +0 -6
  429. package/src/index.ts +0 -15
  430. package/src/ports/README.md +0 -61
  431. package/src/ports/forbidden-surface.test.ts +0 -241
  432. package/src/ports/modem-manager.ts +0 -72
  433. package/src/ports/network-manager.ts +0 -87
  434. package/src/ports/ops.ts +0 -60
  435. package/src/ports/ops.type-test.ts +0 -39
  436. package/src/ports/receipts.test.ts +0 -153
  437. package/src/ports/reconcile.test.ts +0 -152
  438. package/src/ports/reconcile.ts +0 -338
  439. package/src/ports/router.ts +0 -29
  440. package/src/redact.test.ts +0 -82
  441. package/src/redact.ts +0 -73
  442. package/src/transport/README.md +0 -65
  443. package/src/transport/calls.ts +0 -113
  444. package/src/transport/characterization.test.ts +0 -260
  445. package/src/transport/codec.test.ts +0 -118
  446. package/src/transport/codec.ts +0 -240
  447. package/src/transport/conformance-python.test.ts +0 -152
  448. package/src/transport/conformance-same-lib.test.ts +0 -115
  449. package/src/transport/dbus-native-lib.d.ts +0 -19
  450. package/src/transport/dbus-native.ts +0 -85
  451. package/src/transport/index.ts +0 -30
  452. package/src/transport/no-library-leak.test.ts +0 -61
  453. package/src/transport/reliability.test.ts +0 -173
  454. package/src/transport/signals.ts +0 -150
  455. package/src/transport/signature.ts +0 -110
  456. package/src/transport/test-support/fake-service.ts +0 -168
  457. package/src/transport/test-support/independent-producer.py +0 -110
  458. package/src/transport/test-support/private-bus.ts +0 -66
  459. package/src/transport/transport.ts +0 -250
  460. package/src/transport/types.ts +0 -118
  461. package/src/usb-mode/catalog-schema.test.ts +0 -181
  462. package/src/usb-mode/catalog-schema.ts +0 -113
  463. package/src/usb-mode/certified-catalog.json +0 -67
  464. package/src/usb-mode/index.ts +0 -27
@@ -1,65 +0,0 @@
1
- # D-Bus transport seam
2
-
3
- A minimal internal transport interface over [`@httptoolkit/dbus-native`](https://www.npmjs.com/package/@httptoolkit/dbus-native).
4
- Everything the rest of `@ceralive/modem-control` needs to talk to ModemManager over
5
- D-Bus goes through the `DbusTransport` interface exported by [`index.ts`](./index.ts) —
6
- method calls, signal subscriptions, and reconnect. The A3.x D-Bus backend builds
7
- directly on this shape.
8
-
9
- ## Why this library
10
-
11
- `@httptoolkit/dbus-native` is a pure-JavaScript D-Bus client (no libdbus / native
12
- addon), which is the deciding factor: it imports and runs under **Bun 1.3.14** with
13
- **EXTERNAL** auth on a session bus — session-verified during A2.4, and pinned exactly at
14
- `0.1.5`. A native-addon client (anything binding libdbus) is a portability and
15
- cross-compile liability for the arm64 + amd64 device image; a pure-JS client is not.
16
-
17
- ## The fallback
18
-
19
- If `@httptoolkit/dbus-native` proves inadequate — an un-fixable marshalling bug, an
20
- unmaintained upstream, or a Bun incompatibility introduced by a future runtime bump —
21
- the documented fallback is [`@particle/dbus-next`](https://www.npmjs.com/package/@particle/dbus-next),
22
- which is also pure-JS and was verified importable under Bun during planning (draft
23
- ledger §dbus-native). It is **not** implemented here; this note records the escape hatch.
24
- Because the entire library surface is quarantined behind this seam (see below), swapping
25
- to it would touch only [`dbus-native.ts`](./dbus-native.ts), [`transport.ts`](./transport.ts),
26
- and [`codec.ts`](./codec.ts) — never a caller.
27
-
28
- ## The seam contract
29
-
30
- * **No library types leak.** `index.ts` re-exports only the transport's own types
31
- (`DbusValue`, `DbusVariant`, `MethodCall`, `SignalEvent`, …). The raw library types
32
- live in [`dbus-native.ts`](./dbus-native.ts) and go no further. A guard test asserts
33
- the package entry (`../index.ts`) never re-exports the library.
34
- * **Lossless 64-bit.** D-Bus `x` (INT64) and `t` (UINT64) are `bigint` end-to-end, never
35
- a JS `number`. On decode the library runs with `ReturnLongjs: true` and we convert its
36
- Long.js objects to `bigint` via their exact decimal string; on encode we require a
37
- `bigint` and hand the library a decimal string (its only lossless 64-bit input).
38
- Passing a `number` for a 64-bit field throws `BigIntRequiredError`.
39
- * **`h` is unsupported.** UNIX_FD / file-descriptor passing is rejected up front with a
40
- typed `UnsupportedSignatureError` — in an outgoing signature, a reply/signal signature,
41
- or nested in a variant — never silently dropped or coerced.
42
- * **Variants round-trip.** A decoded variant keeps its inner signature
43
- (`DbusVariant { signature, value }`), so encode/decode is symmetric.
44
-
45
- ## Conformance
46
-
47
- Tests run under `dbus-run-session -- bun test control/src/transport` and prove the seam
48
- two independent ways:
49
-
50
- 1. **Same library** ([`conformance-same-lib.test.ts`](./conformance-same-lib.test.ts)) —
51
- round-trips representative signatures against a minimal fake service built on the same
52
- `@httptoolkit/dbus-native`.
53
- 2. **Independent producer** ([`conformance-python.test.ts`](./conformance-python.test.ts)) —
54
- round-trips against a `python3-dbus` (`dbus-python`) service in a subprocess,
55
- exercising `a{oa{sa{sv}}}`, `x`/`t` above 2^53, variants, and `PropertiesChanged`
56
- invalidations. A different implementation on the wire is the real proof our codec is
57
- correct, not merely self-consistent.
58
-
59
- Plus [`reliability.test.ts`](./reliability.test.ts): reconnect after a bus restart
60
- (against a dedicated private `dbus-daemon`), a ≥5000-event signal stream, late replies,
61
- and a 100-cycle subscribe/unsubscribe listener-leak check.
62
-
63
- The `test-support/` fakes here are intentionally minimal — just enough to round-trip the
64
- signatures under test. The MM-faithful fake service (root ObjectManager, `Modem` /
65
- `Modem3gpp` interfaces, SIM objects, bearer tripwires) is a separate, later task (A2.3).
@@ -1,113 +0,0 @@
1
- // Method-call dispatch and reply correlation for the D-Bus transport seam.
2
- //
3
- // A call marshals its body through the codec, registers a pending record so a bus drop can
4
- // reject it, and installs a per-call reply callback guarded by a `done` flag — so a reply
5
- // that arrives after the call already timed out or the connection dropped is silently
6
- // ignored rather than mis-correlated onto a stale promise. `rejectAll` mass-rejects every
7
- // in-flight call when the connection drops.
8
-
9
- import { decodeBody, encodeBody } from './codec';
10
- import { messageType, type RawBus, type RawMessage, type ReplyContext } from './dbus-native';
11
- import { DisconnectedError, TransportError } from './errors';
12
- import type { DbusValue, MethodCall, MethodReply } from './types';
13
-
14
- export const DEFAULT_CALL_TIMEOUT_MS = 30_000;
15
-
16
- interface PendingCall {
17
- settle(): void;
18
- reject(error: unknown): void;
19
- }
20
-
21
- export class CallDispatcher {
22
- readonly #pending = new Set<PendingCall>();
23
- readonly #callTimeoutMs: number;
24
-
25
- constructor(callTimeoutMs: number) {
26
- this.#callTimeoutMs = callTimeoutMs;
27
- }
28
-
29
- async call(bus: RawBus | null, connected: boolean, call: MethodCall): Promise<MethodReply> {
30
- if (!connected || bus === null) {
31
- throw new DisconnectedError('cannot call method: transport not connected');
32
- }
33
-
34
- const signature = call.signature ?? '';
35
- const args = call.args ?? [];
36
- const message: RawMessage = {
37
- type: messageType.methodCall,
38
- destination: call.destination,
39
- path: call.path,
40
- interface: call.interface,
41
- member: call.member,
42
- };
43
- if (signature.length > 0) {
44
- // Throws UnsupportedSignatureError / BigIntRequiredError before anything hits
45
- // the wire.
46
- message.signature = signature;
47
- message.body = encodeBody(signature, args);
48
- }
49
-
50
- const timeoutMs = call.timeoutMs ?? this.#callTimeoutMs;
51
- const pendingSet = this.#pending;
52
- return new Promise<MethodReply>((resolve, reject) => {
53
- let done = false;
54
- const pending: PendingCall = {
55
- settle: finish,
56
- reject: (error) => {
57
- finish();
58
- reject(error);
59
- },
60
- };
61
-
62
- function finish(): void {
63
- if (done) {
64
- return;
65
- }
66
- done = true;
67
- clearTimeout(timer);
68
- pendingSet.delete(pending);
69
- }
70
-
71
- const timer = setTimeout(() => {
72
- finish();
73
- reject(
74
- new TransportError(
75
- `Method call ${call.interface}.${call.member} timed out after ${timeoutMs}ms`,
76
- ),
77
- );
78
- }, timeoutMs);
79
-
80
- pendingSet.add(pending);
81
-
82
- bus.invoke(
83
- message,
84
- function reply(this: ReplyContext, error: unknown, ...body: unknown[]): void {
85
- if (done) {
86
- // Reply arrived after timeout/disconnect already settled the promise — ignore.
87
- return;
88
- }
89
- finish();
90
- if (error) {
91
- reject(error instanceof Error ? error : new TransportError(String(error)));
92
- return;
93
- }
94
- try {
95
- const replySignature = this.signature ?? '';
96
- const decoded: DbusValue[] =
97
- replySignature.length > 0 ? decodeBody(replySignature, body) : [];
98
- resolve({ signature: replySignature, body: decoded });
99
- } catch (decodeError) {
100
- reject(decodeError);
101
- }
102
- },
103
- );
104
- });
105
- }
106
-
107
- rejectAll(cause: unknown): void {
108
- for (const pending of this.#pending) {
109
- pending.reject(cause);
110
- }
111
- this.#pending.clear();
112
- }
113
- }
@@ -1,260 +0,0 @@
1
- // Characterization tests for the transport seam's reconnect / call-correlation / ordering
2
- // edges — the behaviour that a later refactor (splitting transport.ts into lifecycle,
3
- // call-dispatch, and signal modules) MUST preserve byte-for-byte at the observable level.
4
- //
5
- // These pin CURRENT behaviour, not aspirational behaviour: each assertion records what the
6
- // unsplit transport.ts actually does today. If the split changes any of these observable
7
- // facts, one of these tests goes red — which is the whole point.
8
- //
9
- // Like reliability.test.ts, these run against dedicated private `dbus-daemon` instances
10
- // (each test owns one) so a destructive kill/restart is safe. That also makes the file
11
- // self-contained — it needs no outer `dbus-run-session`.
12
-
13
- import { describe, expect, test } from 'bun:test';
14
- import { createDbusTransport } from './index';
15
- import { FAKE_IFACE, FAKE_PATH, startFakeService, TICK_MEMBER } from './test-support/fake-service';
16
- import { PrivateBus } from './test-support/private-bus';
17
-
18
- const HAS_DBUS_DAEMON = Bun.which('dbus-daemon') !== null;
19
-
20
- const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));
21
-
22
- async function waitFor(predicate: () => boolean, timeoutMs: number, label: string): Promise<void> {
23
- const deadline = Date.now() + timeoutMs;
24
- while (Date.now() < deadline) {
25
- if (predicate()) {
26
- return;
27
- }
28
- await sleep(10);
29
- }
30
- throw new Error(`timed out after ${timeoutMs}ms waiting for ${label}`);
31
- }
32
-
33
- const tickSpec = { interface: FAKE_IFACE, member: TICK_MEMBER, path: FAKE_PATH };
34
-
35
- describe.skipIf(!HAS_DBUS_DAEMON)('transport characterization', () => {
36
- // (i) A call that times out, then the real reply lands AFTER the timeout already
37
- // settled the promise. The late reply must be silently ignored (each `bus.invoke`
38
- // owns its own reply closure, guarded by a `done` flag) — no crash, and no
39
- // mis-correlation onto a later, unrelated call.
40
- test('a reply arriving after the call already timed out is silently ignored', async () => {
41
- const bus = new PrivateBus();
42
- await bus.start();
43
- const fake = await startFakeService({ socket: bus.socket });
44
- const transport = createDbusTransport({ socket: bus.socket, reconnect: { enabled: false } });
45
- let errorEvents = 0;
46
- transport.on('error', () => {
47
- errorEvents += 1;
48
- });
49
- await transport.connect();
50
-
51
- // SlowPing replies after 400ms; the call's own timeout is 100ms, so it times out
52
- // first and the reply becomes a "late" one 300ms later.
53
- await expect(
54
- transport.callMethod({
55
- destination: fake.busName,
56
- path: FAKE_PATH,
57
- interface: FAKE_IFACE,
58
- member: 'SlowPing',
59
- signature: 'u',
60
- args: [400],
61
- timeoutMs: 100,
62
- }),
63
- ).rejects.toThrow('timed out after 100ms');
64
-
65
- // Wait well past the 400ms reply so the ignored late reply has actually been
66
- // delivered to (and dropped by) the settled callback.
67
- await sleep(500);
68
-
69
- // No crash, no error event, still connected — the late reply disturbed nothing.
70
- expect(errorEvents).toBe(0);
71
- expect(transport.isConnected()).toBe(true);
72
-
73
- // And the pending machinery is intact: a fresh call correlates to its OWN reply,
74
- // proving the late reply was not mis-delivered to a later promise.
75
- const reply = await transport.callMethod({
76
- destination: fake.busName,
77
- path: FAKE_PATH,
78
- interface: FAKE_IFACE,
79
- member: 'Ping',
80
- });
81
- expect(reply.body[0]).toBe('pong');
82
-
83
- await transport.disconnect();
84
- await fake.stop();
85
- await bus.stop();
86
- });
87
-
88
- // (ii) A bus drop while a call is in flight. The in-flight call must reject, and the
89
- // observed ordering is pinned: the `disconnected` event is delivered BEFORE the call
90
- // rejection is observed. (In `#handleDrop`, pending calls are rejected and then
91
- // `disconnected` is emitted synchronously — but a promise rejection is observed on a
92
- // microtask, so the synchronous event listener runs first.)
93
- test('a mid-call bus drop rejects the in-flight call after emitting disconnected', async () => {
94
- const bus = new PrivateBus();
95
- await bus.start();
96
- const fake = await startFakeService({ socket: bus.socket });
97
- const transport = createDbusTransport({ socket: bus.socket, reconnect: { enabled: false } });
98
-
99
- const order: string[] = [];
100
- let rejection: unknown = null;
101
- transport.on('disconnected', () => order.push('disconnected'));
102
- await transport.connect();
103
-
104
- // A call that will never get a reply — the bus dies under it.
105
- const call = transport
106
- .callMethod({
107
- destination: fake.busName,
108
- path: FAKE_PATH,
109
- interface: FAKE_IFACE,
110
- member: 'SlowPing',
111
- signature: 'u',
112
- args: [5000],
113
- })
114
- .catch((error: unknown) => {
115
- order.push('call-rejected');
116
- rejection = error;
117
- });
118
-
119
- // Give the call time to reach the wire, then drop the bus under it.
120
- await sleep(30);
121
- bus.kill();
122
-
123
- await waitFor(
124
- () => order.includes('disconnected') && order.includes('call-rejected'),
125
- 5000,
126
- 'disconnected + call rejection',
127
- );
128
- await call;
129
-
130
- // Pinned ordering: the event precedes the observed rejection.
131
- expect(order).toEqual(['disconnected', 'call-rejected']);
132
- // Pinned rejection type: a DisconnectedError (the connection-end drop cause).
133
- expect(rejection).toBeInstanceOf(Error);
134
- expect((rejection as Error).name).toBe('DisconnectedError');
135
-
136
- await transport.disconnect();
137
- // The fake died with its bus; stopping it would write to a closed stream. Leave it.
138
- await bus.stop();
139
- });
140
-
141
- // (iii) A drop that arrives while a reconnect is already running. The reconnect loop is
142
- // idempotent: `#handleDrop` early-returns whenever the state is already `disconnected`
143
- // or `reconnecting`, so repeated low-level drop signals never spawn a second reconnect
144
- // loop. The transport converges to a single connected state — exactly one `disconnected`
145
- // and one `reconnected`, no error, and it is not wedged.
146
- test('a drop during an in-flight reconnect does not double-schedule or wedge', async () => {
147
- const bus = new PrivateBus();
148
- await bus.start();
149
- let fake = await startFakeService({ socket: bus.socket });
150
- const transport = createDbusTransport({
151
- socket: bus.socket,
152
- reconnect: { initialDelayMs: 25, maxDelayMs: 100 },
153
- });
154
-
155
- const events: string[] = [];
156
- let errorEvents = 0;
157
- transport.on('disconnected', () => events.push('disconnected'));
158
- transport.on('reconnected', () => events.push('reconnected'));
159
- transport.on('error', () => {
160
- errorEvents += 1;
161
- });
162
- await transport.connect();
163
-
164
- const ticks: bigint[] = [];
165
- const subscription = await transport.subscribeSignal(tickSpec, (event) => {
166
- ticks.push(event.body[0] as bigint);
167
- });
168
-
169
- fake.emitTick(11n);
170
- await waitFor(() => ticks.includes(11n), 3000, 'pre-drop tick');
171
-
172
- // Drop the bus and leave it down long enough for the reconnect loop to spin through
173
- // several failed establish attempts before the bus returns.
174
- bus.kill();
175
- await waitFor(() => events.includes('disconnected'), 5000, 'disconnected');
176
- await sleep(150);
177
- await bus.start();
178
- await waitFor(() => events.includes('reconnected'), 15000, 'reconnected');
179
-
180
- // A settle window to catch any spurious extra event from a double-scheduled loop.
181
- await sleep(300);
182
-
183
- expect(events.filter((event) => event === 'disconnected')).toHaveLength(1);
184
- expect(events.filter((event) => event === 'reconnected')).toHaveLength(1);
185
- expect(errorEvents).toBe(0);
186
-
187
- // Not wedged: a fresh producer's signal flows through the auto-resubscribed rule.
188
- fake = await startFakeService({ socket: bus.socket });
189
- fake.emitTick(22n);
190
- await waitFor(() => ticks.includes(22n), 8000, 'post-reconnect tick');
191
- expect(transport.subscriptionCount()).toBe(1);
192
-
193
- await subscription.unsubscribe();
194
- await transport.disconnect();
195
- await fake.stop();
196
- await bus.stop();
197
- }, 30000);
198
-
199
- // (iv) A subscription added AND one removed while a reconnect is in progress. Because
200
- // mutating a subscription while disconnected only touches the in-memory match-rule
201
- // refcount (the bus call is skipped when not connected), and `#establish()` re-issues
202
- // every live rule on reconnect, the refcounting must end up correct: the added
203
- // subscription is registered (receives signals) and the removed one is not.
204
- test('subscriptions mutated during reconnect end up correctly (un)registered', async () => {
205
- const bus = new PrivateBus();
206
- await bus.start();
207
- const transport = createDbusTransport({
208
- socket: bus.socket,
209
- reconnect: { initialDelayMs: 25, maxDelayMs: 100 },
210
- });
211
-
212
- const events: string[] = [];
213
- transport.on('disconnected', () => events.push('disconnected'));
214
- transport.on('reconnected', () => events.push('reconnected'));
215
- await transport.connect();
216
-
217
- // `removed` is a path-filtered rule; `added` is a distinct (no-path) rule that still
218
- // matches the same emitted Tick — so their match-rule strings differ and are tracked
219
- // independently.
220
- const removedTicks: bigint[] = [];
221
- const addedTicks: bigint[] = [];
222
- const removed = await transport.subscribeSignal(tickSpec, (event) => {
223
- removedTicks.push(event.body[0] as bigint);
224
- });
225
- expect(transport.subscriptionCount()).toBe(1);
226
-
227
- // Drop the bus; while the reconnect loop is running, mutate the subscription set.
228
- bus.kill();
229
- await waitFor(() => events.includes('disconnected'), 5000, 'disconnected');
230
-
231
- await removed.unsubscribe();
232
- const added = await transport.subscribeSignal(
233
- { interface: FAKE_IFACE, member: TICK_MEMBER },
234
- (event) => {
235
- addedTicks.push(event.body[0] as bigint);
236
- },
237
- );
238
- expect(transport.subscriptionCount()).toBe(1);
239
-
240
- // Bring the bus back; `#establish()` re-issues exactly the rules still in the
241
- // refcount map — the `added` one, not the `removed` one.
242
- await bus.start();
243
- await waitFor(() => events.includes('reconnected'), 15000, 'reconnected');
244
-
245
- const fake = await startFakeService({ socket: bus.socket });
246
- fake.emitTick(33n);
247
- await waitFor(() => addedTicks.includes(33n), 8000, 'added-subscription tick');
248
-
249
- // Grace to prove the removed subscription genuinely receives nothing.
250
- await sleep(200);
251
- expect(addedTicks).toEqual([33n]);
252
- expect(removedTicks).toEqual([]);
253
- expect(transport.subscriptionCount()).toBe(1);
254
-
255
- await added.unsubscribe();
256
- await transport.disconnect();
257
- await fake.stop();
258
- await bus.stop();
259
- }, 30000);
260
- });
@@ -1,118 +0,0 @@
1
- // Pure, in-process encode/decode round-trip: no bus, fully deterministic. Marshals with
2
- // the library's own marshaller and reads it back with its DBusBuffer under
3
- // `ReturnLongjs: true` — exactly the wire path a real call takes — so a green run here is
4
- // exact proof the codec is lossless, independent of any daemon timing.
5
-
6
- import { expect, test } from 'bun:test';
7
- import DBusBuffer from '@httptoolkit/dbus-native/lib/dbus-buffer';
8
- import marshall from '@httptoolkit/dbus-native/lib/marshall';
9
- import { decodeBody, encodeBody } from './codec';
10
- import { BigIntRequiredError, SixtyFourBitRangeError, UnsupportedSignatureError } from './errors';
11
- import { type DbusValue, variant } from './types';
12
-
13
- const INT64_MAX = 2n ** 63n - 1n;
14
- const INT64_MIN = -(2n ** 63n);
15
- const UINT64_MAX = 2n ** 64n - 1n;
16
-
17
- function roundTrip(signature: string, values: readonly DbusValue[]): DbusValue[] {
18
- const encoded = encodeBody(signature, values);
19
- const buffer = marshall(signature, encoded);
20
- const reader = new DBusBuffer(buffer, 0, { ayBuffer: true, ReturnLongjs: true });
21
- const raw = reader.read(signature) as unknown[];
22
- return decodeBody(signature, raw);
23
- }
24
-
25
- test('2^63-1 round-trips through an INT64 exactly (bigint equality)', () => {
26
- const [value] = roundTrip('x', [INT64_MAX]);
27
- expect(value).toBe(INT64_MAX);
28
- expect(typeof value).toBe('bigint');
29
- });
30
-
31
- test('the full UINT64 range (2^64-1) round-trips exactly', () => {
32
- const [value] = roundTrip('t', [UINT64_MAX]);
33
- expect(value).toBe(UINT64_MAX);
34
- });
35
-
36
- test('INT64 minimum round-trips exactly', () => {
37
- const [value] = roundTrip('x', [INT64_MIN]);
38
- expect(value).toBe(INT64_MIN);
39
- });
40
-
41
- test('a value just above 2^53 survives (no silent Number coercion)', () => {
42
- const beyondSafe = 2n ** 53n + 1n;
43
- const [asInt, asUint] = roundTrip('xt', [beyondSafe, beyondSafe]);
44
- expect(asInt).toBe(beyondSafe);
45
- expect(asUint).toBe(beyondSafe);
46
- // The precision-losing path would have produced 9007199254740992n (== 2^53).
47
- expect(asInt).not.toBe(2n ** 53n);
48
- });
49
-
50
- test('the MM GetManagedObjects shape a{oa{sa{sv}}} round-trips with a 64-bit variant', () => {
51
- const managed: DbusValue = [
52
- [
53
- '/org/freedesktop/ModemManager1/Modem/0',
54
- [
55
- [
56
- 'org.freedesktop.ModemManager1.Modem',
57
- [
58
- ['SupportedCapabilities', variant('t', UINT64_MAX)],
59
- ['SignalQuality', variant('u', 87)],
60
- ['DeviceIdentifier', variant('s', 'dev-0')],
61
- ],
62
- ],
63
- ],
64
- ],
65
- ];
66
- const [decoded] = roundTrip('a{oa{sa{sv}}}', [managed]);
67
- expect(decoded).toEqual(managed);
68
- });
69
-
70
- test('a variant preserves its inner signature and 64-bit value across a round-trip', () => {
71
- const [decoded] = roundTrip('v', [variant('t', UINT64_MAX)]);
72
- expect(decoded).toEqual({ signature: 't', value: UINT64_MAX });
73
- });
74
-
75
- test('a byte array (ay) round-trips as a Uint8Array', () => {
76
- const bytes = new Uint8Array([0, 1, 2, 254, 255]);
77
- const [decoded] = roundTrip('ay', [bytes]);
78
- expect(decoded).toBeInstanceOf(Uint8Array);
79
- expect(Array.from(decoded as Uint8Array)).toEqual([0, 1, 2, 254, 255]);
80
- });
81
-
82
- test('a struct with mixed 64-bit fields round-trips', () => {
83
- const [decoded] = roundTrip('(xtu)', [[INT64_MIN, UINT64_MAX, 7]]);
84
- expect(decoded).toEqual([INT64_MIN, UINT64_MAX, 7]);
85
- });
86
-
87
- test('signature h (UNIX_FD) is rejected on encode with a typed error', () => {
88
- expect(() => encodeBody('h', [0])).toThrow(UnsupportedSignatureError);
89
- });
90
-
91
- test('signature h nested inside a container is rejected on encode', () => {
92
- expect(() => encodeBody('a{sh}', [[]])).toThrow(UnsupportedSignatureError);
93
- });
94
-
95
- test('signature h is rejected on decode with a typed error', () => {
96
- expect(() => decodeBody('h', [0])).toThrow(UnsupportedSignatureError);
97
- });
98
-
99
- test('the UnsupportedSignatureError carries the offending type', () => {
100
- try {
101
- encodeBody('h', [0]);
102
- throw new Error('expected throw');
103
- } catch (error) {
104
- expect(error).toBeInstanceOf(UnsupportedSignatureError);
105
- expect((error as UnsupportedSignatureError).unsupportedType).toBe('h');
106
- }
107
- });
108
-
109
- test('passing a JS number for a 64-bit field throws BigIntRequiredError', () => {
110
- expect(() => encodeBody('t', [123])).toThrow(BigIntRequiredError);
111
- expect(() => encodeBody('x', [123])).toThrow(BigIntRequiredError);
112
- });
113
-
114
- test('an out-of-range 64-bit bigint throws SixtyFourBitRangeError', () => {
115
- expect(() => encodeBody('t', [-1n])).toThrow(SixtyFourBitRangeError);
116
- expect(() => encodeBody('x', [2n ** 63n])).toThrow(SixtyFourBitRangeError);
117
- expect(() => encodeBody('t', [2n ** 64n])).toThrow(SixtyFourBitRangeError);
118
- });