@ceralive/modem-control 1.0.0 → 1.2.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 (480) hide show
  1. package/README.md +341 -0
  2. package/dist/backend/at-lease.d.ts +59 -0
  3. package/dist/backend/at-lease.js +118 -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 +101 -0
  61. package/dist/backend/transition-preconditions.js +132 -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 +216 -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 +20 -0
  146. package/dist/index.js +27 -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 +61 -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/operation-ids.d.ts +2 -0
  196. package/dist/operation-ids.js +26 -0
  197. package/dist/operations/contracts.d.ts +72 -0
  198. package/dist/operations/contracts.js +1 -0
  199. package/dist/operations/index.d.ts +1 -0
  200. package/dist/operations/index.js +1 -0
  201. package/dist/operations/operation-engine.d.ts +16 -0
  202. package/dist/operations/operation-engine.js +194 -0
  203. package/dist/ports/index.d.ts +12 -0
  204. package/{src/ports/index.ts → dist/ports/index.js} +12 -8
  205. package/dist/ports/location.d.ts +87 -0
  206. package/dist/ports/location.js +36 -0
  207. package/dist/ports/modem-manager.d.ts +89 -0
  208. package/dist/ports/modem-manager.js +9 -0
  209. package/dist/ports/mutation-admission.d.ts +27 -0
  210. package/dist/ports/mutation-admission.js +9 -0
  211. package/dist/ports/network-manager.d.ts +68 -0
  212. package/dist/ports/network-manager.js +13 -0
  213. package/{src/ports/observation.ts → dist/ports/observation.d.ts} +16 -27
  214. package/dist/ports/observation.js +7 -0
  215. package/dist/ports/ops.d.ts +44 -0
  216. package/dist/ports/ops.js +16 -0
  217. package/{src/ports/receipts.ts → dist/ports/receipts.d.ts} +5 -27
  218. package/dist/ports/receipts.js +9 -0
  219. package/dist/ports/reconcile.d.ts +33 -0
  220. package/dist/ports/reconcile.js +200 -0
  221. package/dist/ports/resource-ownership.d.ts +29 -0
  222. package/dist/ports/resource-ownership.js +1 -0
  223. package/dist/ports/router.d.ts +19 -0
  224. package/dist/ports/router.js +7 -0
  225. package/dist/ports/sms.d.ts +64 -0
  226. package/dist/ports/sms.js +24 -0
  227. package/dist/ports/uhubctl.d.ts +6 -0
  228. package/dist/ports/uhubctl.js +1 -0
  229. package/dist/providers/contracts.d.ts +124 -0
  230. package/dist/providers/contracts.js +10 -0
  231. package/dist/providers/huawei-hilink/index.d.ts +2 -0
  232. package/dist/providers/huawei-hilink/index.js +2 -0
  233. package/dist/providers/huawei-hilink/operations.d.ts +20 -0
  234. package/dist/providers/huawei-hilink/operations.js +56 -0
  235. package/dist/providers/huawei-hilink/provider.d.ts +52 -0
  236. package/dist/providers/huawei-hilink/provider.js +76 -0
  237. package/dist/providers/huawei-hilink/runtime.d.ts +22 -0
  238. package/dist/providers/huawei-hilink/runtime.js +171 -0
  239. package/dist/providers/huawei-hilink/session.d.ts +28 -0
  240. package/dist/providers/huawei-hilink/session.js +120 -0
  241. package/dist/providers/huawei-hilink/transport.d.ts +19 -0
  242. package/dist/providers/huawei-hilink/transport.js +1 -0
  243. package/dist/providers/index.d.ts +8 -0
  244. package/dist/providers/index.js +8 -0
  245. package/dist/providers/matcher.d.ts +3 -0
  246. package/dist/providers/matcher.js +205 -0
  247. package/dist/providers/modem-manager/errors.d.ts +7 -0
  248. package/dist/providers/modem-manager/errors.js +37 -0
  249. package/dist/providers/modem-manager/generic-operations.d.ts +10 -0
  250. package/dist/providers/modem-manager/generic-operations.js +209 -0
  251. package/dist/providers/modem-manager/index.d.ts +4 -0
  252. package/dist/providers/modem-manager/index.js +4 -0
  253. package/dist/providers/modem-manager/module-operations.d.ts +21 -0
  254. package/dist/providers/modem-manager/module-operations.js +118 -0
  255. package/dist/providers/modem-manager/provider.d.ts +41 -0
  256. package/dist/providers/modem-manager/provider.js +155 -0
  257. package/dist/providers/modem-manager/runtime-composition-operation.d.ts +32 -0
  258. package/dist/providers/modem-manager/runtime-composition-operation.js +151 -0
  259. package/dist/providers/modem-manager/snapshot.d.ts +5 -0
  260. package/dist/providers/modem-manager/snapshot.js +204 -0
  261. package/dist/providers/modem-manager/types.d.ts +137 -0
  262. package/dist/providers/modem-manager/types.js +1 -0
  263. package/dist/providers/network-manager/adapter.d.ts +71 -0
  264. package/dist/providers/network-manager/adapter.js +348 -0
  265. package/dist/providers/network-manager/index.d.ts +2 -0
  266. package/dist/providers/network-manager/index.js +2 -0
  267. package/dist/providers/network-manager/types.d.ts +171 -0
  268. package/dist/providers/network-manager/types.js +77 -0
  269. package/dist/providers/registry.d.ts +13 -0
  270. package/dist/providers/registry.js +33 -0
  271. package/dist/providers/ufi-himi/index.d.ts +6 -0
  272. package/dist/providers/ufi-himi/index.js +6 -0
  273. package/dist/providers/ufi-himi/operations.d.ts +41 -0
  274. package/dist/providers/ufi-himi/operations.js +66 -0
  275. package/dist/providers/ufi-himi/prohibitions.d.ts +62 -0
  276. package/dist/providers/ufi-himi/prohibitions.js +88 -0
  277. package/dist/providers/ufi-himi/provider.d.ts +41 -0
  278. package/dist/providers/ufi-himi/provider.js +204 -0
  279. package/dist/providers/ufi-himi/qualcomm-evidence.d.ts +32 -0
  280. package/dist/providers/ufi-himi/qualcomm-evidence.js +51 -0
  281. package/dist/providers/ufi-himi/session.d.ts +46 -0
  282. package/dist/providers/ufi-himi/session.js +92 -0
  283. package/dist/providers/ufi-himi/transport.d.ts +29 -0
  284. package/dist/providers/ufi-himi/transport.js +25 -0
  285. package/dist/providers/zte-goform/index.d.ts +2 -0
  286. package/dist/providers/zte-goform/index.js +2 -0
  287. package/dist/providers/zte-goform/provider.d.ts +56 -0
  288. package/dist/providers/zte-goform/provider.js +101 -0
  289. package/dist/providers/zte-goform/session.d.ts +23 -0
  290. package/dist/providers/zte-goform/session.js +197 -0
  291. package/dist/providers/zte-goform/transport.d.ts +16 -0
  292. package/dist/providers/zte-goform/transport.js +1 -0
  293. package/dist/radio/band-truth.d.ts +50 -0
  294. package/dist/radio/band-truth.js +92 -0
  295. package/dist/radio/index.d.ts +3 -0
  296. package/dist/radio/index.js +10 -0
  297. package/dist/radio/mode-combinations.d.ts +88 -0
  298. package/dist/radio/mode-combinations.js +198 -0
  299. package/dist/radio/mode-truth.d.ts +67 -0
  300. package/dist/radio/mode-truth.js +112 -0
  301. package/dist/redact.d.ts +15 -0
  302. package/dist/redact.js +189 -0
  303. package/dist/safety/composition-root.d.ts +28 -0
  304. package/dist/safety/composition-root.js +65 -0
  305. package/dist/safety/flock-resource-ownership.d.ts +11 -0
  306. package/dist/safety/flock-resource-ownership.js +138 -0
  307. package/dist/safety/index.d.ts +2 -0
  308. package/dist/safety/index.js +2 -0
  309. package/dist/sms/dbus-messaging.d.ts +17 -0
  310. package/dist/sms/dbus-messaging.js +185 -0
  311. package/dist/sms/inbox-store.d.ts +10 -0
  312. package/dist/sms/inbox-store.js +82 -0
  313. package/dist/sms/index.d.ts +4 -0
  314. package/dist/sms/index.js +10 -0
  315. package/dist/sms/mmcli-parse.d.ts +54 -0
  316. package/dist/sms/mmcli-parse.js +224 -0
  317. package/dist/sms/normalize.d.ts +42 -0
  318. package/dist/sms/normalize.js +95 -0
  319. package/dist/testing/domain-fakes.d.ts +58 -0
  320. package/dist/testing/domain-fakes.js +98 -0
  321. package/dist/testing/index.d.ts +2 -0
  322. package/dist/testing/index.js +17 -0
  323. package/dist/testing/provider-fakes.d.ts +45 -0
  324. package/dist/testing/provider-fakes.js +64 -0
  325. package/dist/transport/calls.d.ts +9 -0
  326. package/dist/transport/calls.js +88 -0
  327. package/dist/transport/codec.d.ts +3 -0
  328. package/dist/transport/codec.js +207 -0
  329. package/dist/transport/dbus-native.d.ts +57 -0
  330. package/dist/transport/dbus-native.js +17 -0
  331. package/dist/transport/errors.d.ts +21 -0
  332. package/{src/transport/errors.ts → dist/transport/errors.js} +34 -46
  333. package/dist/transport/index.d.ts +4 -0
  334. package/dist/transport/index.js +9 -0
  335. package/dist/transport/signals.d.ts +15 -0
  336. package/dist/transport/signals.js +123 -0
  337. package/dist/transport/signature.d.ts +7 -0
  338. package/dist/transport/signature.js +94 -0
  339. package/dist/transport/transport.d.ts +2 -0
  340. package/dist/transport/transport.js +202 -0
  341. package/dist/transport/types.d.ts +61 -0
  342. package/dist/transport/types.js +19 -0
  343. package/dist/usb-mode/catalog-schema.d.ts +139 -0
  344. package/dist/usb-mode/catalog-schema.js +97 -0
  345. package/dist/usb-mode/catalog.d.ts +21 -0
  346. package/{src/usb-mode/catalog.ts → dist/usb-mode/catalog.js} +10 -32
  347. package/dist/usb-mode/certified-catalog.json +67 -0
  348. package/dist/usb-mode/index.d.ts +6 -0
  349. package/dist/usb-mode/index.js +16 -0
  350. package/dist/usb-mode/ingestion.d.ts +111 -0
  351. package/dist/usb-mode/ingestion.js +187 -0
  352. package/dist/usb-mode/promotion-review.d.ts +21 -0
  353. package/dist/usb-mode/promotion-review.js +87 -0
  354. package/dist/usb-mode/runtime-capability.d.ts +59 -0
  355. package/dist/usb-mode/runtime-capability.js +157 -0
  356. package/dist/usb-mode/usb-devices-parse.d.ts +36 -0
  357. package/dist/usb-mode/usb-devices-parse.js +157 -0
  358. package/dist/ussd/calls.d.ts +32 -0
  359. package/dist/ussd/calls.js +96 -0
  360. package/dist/ussd/index.d.ts +5 -0
  361. package/dist/ussd/index.js +12 -0
  362. package/dist/ussd/mm-ussd.d.ts +37 -0
  363. package/dist/ussd/mm-ussd.js +205 -0
  364. package/dist/ussd/refusal.d.ts +53 -0
  365. package/dist/ussd/refusal.js +154 -0
  366. package/dist/ussd/registration.d.ts +20 -0
  367. package/dist/ussd/registration.js +101 -0
  368. package/dist/ussd/session.d.ts +106 -0
  369. package/dist/ussd/session.js +163 -0
  370. package/package.json +38 -4
  371. package/src/backend/at-lease.test.ts +0 -106
  372. package/src/backend/at-lease.ts +0 -158
  373. package/src/backend/cell-info.test.ts +0 -154
  374. package/src/backend/cell-info.ts +0 -160
  375. package/src/backend/device-classifier.test.ts +0 -168
  376. package/src/backend/device-classifier.ts +0 -248
  377. package/src/backend/enrichment.ts +0 -96
  378. package/src/backend/features.test.ts +0 -162
  379. package/src/backend/features.ts +0 -179
  380. package/src/backend/identity-ladder.test.ts +0 -117
  381. package/src/backend/identity-ladder.ts +0 -221
  382. package/src/backend/identity-registry.test.ts +0 -89
  383. package/src/backend/identity-registry.ts +0 -151
  384. package/src/backend/index.ts +0 -236
  385. package/src/backend/lifecycle-interlock.ts +0 -38
  386. package/src/backend/managed-objects.ts +0 -108
  387. package/src/backend/mapping.ts +0 -160
  388. package/src/backend/mm-backend.ts +0 -191
  389. package/src/backend/mm-mutations.ts +0 -228
  390. package/src/backend/modem-actor.test.ts +0 -95
  391. package/src/backend/modem-actor.ts +0 -112
  392. package/src/backend/nm-auto-apn.ts +0 -161
  393. package/src/backend/nm-gsm-fields.ts +0 -122
  394. package/src/backend/nmcli-nm-port.ts +0 -228
  395. package/src/backend/nmcli-runner.ts +0 -52
  396. package/src/backend/observer.ts +0 -297
  397. package/src/backend/power-contract.test.ts +0 -40
  398. package/src/backend/power-contract.ts +0 -83
  399. package/src/backend/recovery-attribution.test.ts +0 -102
  400. package/src/backend/recovery-attribution.ts +0 -86
  401. package/src/backend/recovery-budget.test.ts +0 -64
  402. package/src/backend/recovery-budget.ts +0 -84
  403. package/src/backend/recovery-ladder.test.ts +0 -257
  404. package/src/backend/recovery-ladder.ts +0 -249
  405. package/src/backend/router-ethernet.test.ts +0 -71
  406. package/src/backend/router-ethernet.ts +0 -90
  407. package/src/backend/row-store.ts +0 -105
  408. package/src/backend/signal-setup.ts +0 -112
  409. package/src/backend/sim-unlock.ts +0 -193
  410. package/src/backend/transition-preconditions.ts +0 -149
  411. package/src/backend/uhubctl-power-hook.test.ts +0 -274
  412. package/src/backend/uhubctl-power-hook.ts +0 -377
  413. package/src/backend/usage/accounting.test.ts +0 -147
  414. package/src/backend/usage/accounting.ts +0 -123
  415. package/src/backend/usage/billing-cycle.test.ts +0 -62
  416. package/src/backend/usage/billing-cycle.ts +0 -45
  417. package/src/backend/usage/index.ts +0 -60
  418. package/src/backend/usage/policy-store.test.ts +0 -164
  419. package/src/backend/usage/policy-store.ts +0 -216
  420. package/src/backend/usage/policy-write.test.ts +0 -198
  421. package/src/backend/usage/policy-write.ts +0 -207
  422. package/src/backend/usage/proc-net-dev.test.ts +0 -56
  423. package/src/backend/usage/sampler.test.ts +0 -327
  424. package/src/backend/usage/sampler.ts +0 -282
  425. package/src/backend/usage/store.test.ts +0 -148
  426. package/src/backend/usage/store.ts +0 -177
  427. package/src/backend/usb-enumerator.test.ts +0 -87
  428. package/src/backend/usb-enumerator.ts +0 -181
  429. package/src/backend/usb-mode-transition.test.ts +0 -323
  430. package/src/backend/usb-mode-transition.ts +0 -253
  431. package/src/domain/brand.ts +0 -29
  432. package/src/domain/errors.ts +0 -77
  433. package/src/domain/guards.test.ts +0 -218
  434. package/src/domain/guards.ts +0 -144
  435. package/src/domain/identity.test.ts +0 -83
  436. package/src/domain/identity.ts +0 -165
  437. package/src/domain/index.ts +0 -12
  438. package/src/domain/snapshot.test.ts +0 -266
  439. package/src/domain/snapshot.ts +0 -120
  440. package/src/index.test.ts +0 -6
  441. package/src/index.ts +0 -15
  442. package/src/ports/README.md +0 -61
  443. package/src/ports/forbidden-surface.test.ts +0 -241
  444. package/src/ports/modem-manager.ts +0 -72
  445. package/src/ports/network-manager.ts +0 -87
  446. package/src/ports/ops.ts +0 -60
  447. package/src/ports/ops.type-test.ts +0 -39
  448. package/src/ports/receipts.test.ts +0 -153
  449. package/src/ports/reconcile.test.ts +0 -152
  450. package/src/ports/reconcile.ts +0 -338
  451. package/src/ports/router.ts +0 -29
  452. package/src/redact.test.ts +0 -82
  453. package/src/redact.ts +0 -73
  454. package/src/transport/README.md +0 -65
  455. package/src/transport/calls.ts +0 -113
  456. package/src/transport/characterization.test.ts +0 -260
  457. package/src/transport/codec.test.ts +0 -118
  458. package/src/transport/codec.ts +0 -240
  459. package/src/transport/conformance-python.test.ts +0 -152
  460. package/src/transport/conformance-same-lib.test.ts +0 -115
  461. package/src/transport/dbus-native-lib.d.ts +0 -19
  462. package/src/transport/dbus-native.ts +0 -85
  463. package/src/transport/index.ts +0 -30
  464. package/src/transport/no-library-leak.test.ts +0 -61
  465. package/src/transport/reliability.test.ts +0 -173
  466. package/src/transport/signals.ts +0 -150
  467. package/src/transport/signature.ts +0 -110
  468. package/src/transport/test-support/fake-service.ts +0 -168
  469. package/src/transport/test-support/independent-producer.py +0 -110
  470. package/src/transport/test-support/private-bus.ts +0 -66
  471. package/src/transport/transport.ts +0 -250
  472. package/src/transport/types.ts +0 -118
  473. package/src/usb-mode/catalog-schema.test.ts +0 -181
  474. package/src/usb-mode/catalog-schema.ts +0 -113
  475. package/src/usb-mode/certified-catalog.json +0 -67
  476. package/src/usb-mode/index.ts +0 -58
  477. package/src/usb-mode/ingestion.test.ts +0 -268
  478. package/src/usb-mode/ingestion.ts +0 -297
  479. package/src/usb-mode/promotion-review.ts +0 -117
  480. package/src/usb-mode/usb-devices-parse.ts +0 -196
@@ -0,0 +1,11 @@
1
+ import type { ResourceOwnershipPort } from '../ports/index.js';
2
+ export type FlockResourceOwnershipOptions = {
3
+ readonly lockPath: string;
4
+ readonly flockBinary?: string;
5
+ };
6
+ export declare class FlockResourceOwnershipError extends Error {
7
+ readonly detail: string;
8
+ readonly name = "FlockResourceOwnershipError";
9
+ constructor(detail: string);
10
+ }
11
+ export declare function createFlockResourceOwnershipPort(options: FlockResourceOwnershipOptions): ResourceOwnershipPort;
@@ -0,0 +1,138 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { readFile, writeFile } from 'node:fs/promises';
3
+ export class FlockResourceOwnershipError extends Error {
4
+ detail;
5
+ name = 'FlockResourceOwnershipError';
6
+ constructor(detail) {
7
+ super(`flock ownership failed: ${detail}`);
8
+ this.detail = detail;
9
+ }
10
+ }
11
+ export function createFlockResourceOwnershipPort(options) {
12
+ return {
13
+ async acquire() {
14
+ const child = spawn(options.flockBinary ?? 'flock', ['--exclusive', '--nonblock', '--no-fork', options.lockPath, '/bin/cat'], { stdio: ['pipe', 'pipe', 'pipe'] });
15
+ if (child.pid === undefined) {
16
+ throw new FlockResourceOwnershipError('helper started without a process id');
17
+ }
18
+ const holder = { pid: child.pid, startedAtEpochMs: Date.now() };
19
+ const closed = childClosed(child);
20
+ const started = await childStarted(child, options.lockPath, holder);
21
+ if (started.status === 'closed') {
22
+ if (started.code === 1) {
23
+ const holder = await readHolder(options.lockPath);
24
+ return {
25
+ status: 'refused',
26
+ reason: 'already-owned',
27
+ ...(holder !== undefined && pidIsAlive(holder.pid) ? { holder } : {}),
28
+ };
29
+ }
30
+ throw new FlockResourceOwnershipError(`helper exited ${started.code ?? 'by signal'}${started.stderr ? `: ${started.stderr}` : ''}`);
31
+ }
32
+ return {
33
+ status: 'acquired',
34
+ lease: createLease(child, closed, started.holder),
35
+ };
36
+ },
37
+ };
38
+ }
39
+ function createLease(child, closed, holder) {
40
+ let released = false;
41
+ return {
42
+ holder,
43
+ lost: closed.then(() => ({ reason: 'holder-exited' })),
44
+ async release() {
45
+ if (released)
46
+ return;
47
+ released = true;
48
+ if (child.exitCode === null && child.signalCode === null) {
49
+ child.stdin.end();
50
+ }
51
+ await closed;
52
+ },
53
+ };
54
+ }
55
+ function childClosed(child) {
56
+ return new Promise((resolve) => child.once('close', () => resolve()));
57
+ }
58
+ function childStarted(child, lockPath, holder) {
59
+ return new Promise((resolve, reject) => {
60
+ let stdout = '';
61
+ let stderr = '';
62
+ let settled = false;
63
+ const finish = (result) => {
64
+ if (settled)
65
+ return;
66
+ settled = true;
67
+ resolve(result);
68
+ };
69
+ child.stderr.on('data', (chunk) => {
70
+ stderr += chunk.toString('utf8');
71
+ });
72
+ child.stdout.on('data', (chunk) => {
73
+ stdout += chunk.toString('utf8');
74
+ const newline = stdout.indexOf('\n');
75
+ if (newline < 0)
76
+ return;
77
+ const acquired = parseAcquiredLine(stdout.slice(0, newline));
78
+ if (acquired === undefined || settled)
79
+ return;
80
+ settled = true;
81
+ void writeFile(lockPath, `${JSON.stringify(holder)}\n`, { mode: 0o600 }).then(() => resolve({ status: 'acquired', holder }), (error) => {
82
+ child.stdin.end();
83
+ reject(error);
84
+ });
85
+ });
86
+ child.once('close', (code) => finish({ status: 'closed', code, stderr: stderr.trim() }));
87
+ child.stdin.write(`${JSON.stringify({ type: 'acquired', holder })}\n`);
88
+ });
89
+ }
90
+ function parseAcquiredLine(line) {
91
+ try {
92
+ const parsed = JSON.parse(line);
93
+ if (typeof parsed !== 'object' || parsed === null || !('holder' in parsed))
94
+ return undefined;
95
+ return parseHolder(parsed.holder);
96
+ }
97
+ catch (error) {
98
+ if (error instanceof SyntaxError)
99
+ return undefined;
100
+ throw error;
101
+ }
102
+ }
103
+ async function readHolder(lockPath) {
104
+ try {
105
+ return parseHolder(JSON.parse(await readFile(lockPath, 'utf8')));
106
+ }
107
+ catch (error) {
108
+ if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
109
+ return undefined;
110
+ if (error instanceof SyntaxError)
111
+ return undefined;
112
+ throw error;
113
+ }
114
+ }
115
+ function parseHolder(value) {
116
+ if (typeof value !== 'object' || value === null)
117
+ return undefined;
118
+ if (!('pid' in value) || !('startedAtEpochMs' in value))
119
+ return undefined;
120
+ if (typeof value.pid !== 'number' || !Number.isSafeInteger(value.pid) || value.pid <= 0) {
121
+ return undefined;
122
+ }
123
+ if (typeof value.startedAtEpochMs !== 'number' || !Number.isFinite(value.startedAtEpochMs)) {
124
+ return undefined;
125
+ }
126
+ return { pid: value.pid, startedAtEpochMs: value.startedAtEpochMs };
127
+ }
128
+ function pidIsAlive(pid) {
129
+ try {
130
+ process.kill(pid, 0);
131
+ return true;
132
+ }
133
+ catch (error) {
134
+ if (error instanceof Error && 'code' in error && error.code === 'ESRCH')
135
+ return false;
136
+ return true;
137
+ }
138
+ }
@@ -0,0 +1,2 @@
1
+ export * from './composition-root.js';
2
+ export * from './flock-resource-ownership.js';
@@ -0,0 +1,2 @@
1
+ export * from './composition-root.js';
2
+ export * from './flock-resource-ownership.js';
@@ -0,0 +1,17 @@
1
+ import { type DecodedProps } from '../backend/managed-objects.js';
2
+ import type { SmsMessage, SmsObservationPort } from '../ports/sms.js';
3
+ import type { DbusTransport } from '../transport/index.js';
4
+ /** `org.freedesktop.ModemManager1.Sms` — one message object. */
5
+ export declare const SMS_IFACE = "org.freedesktop.ModemManager1.Sms";
6
+ /** Build one message from an SMS object's decoded `Sms` properties. */
7
+ export declare function smsFromProps(path: string, props: DecodedProps | undefined): SmsMessage;
8
+ export interface DbusSmsPortOptions {
9
+ readonly transport: DbusTransport;
10
+ /** The modem's ModemManager object path. */
11
+ readonly modemPath: string;
12
+ readonly destination?: string;
13
+ readonly cap?: number;
14
+ /** Called when a fold-time error must be surfaced without failing a read. */
15
+ readonly onError?: (error: unknown) => void;
16
+ }
17
+ export declare function createDbusSmsPort(options: DbusSmsPortOptions): SmsObservationPort;
@@ -0,0 +1,185 @@
1
+ // The ModemManager Messaging adapter — LIST ONCE, then follow Added / Deleted.
2
+ //
3
+ // Three verbs, all reads: `Messaging.List` for the object paths,
4
+ // `Properties.GetAll` per message, and a subscription to `Added` / `Deleted`.
5
+ // There is no `Create`, no `Send`, no `Delete`, and none may be added — see
6
+ // `../ports/sms.ts` for why that is permanent rather than staged, and
7
+ // `readonly-gate.test.ts` for the lock.
8
+ //
9
+ // NEVER RE-LIST ON A TICK. MM tells us about every change, so a poll would cost
10
+ // one method call per stored message per tick and still could not report an
11
+ // arrival sooner than the tick it happened to land on. The ONLY re-list is on a
12
+ // source RECONNECT, where the events that occurred while the bus was down were
13
+ // never delivered and folding is therefore impossible; that re-list is published
14
+ // as `resynced` so the consumer replaces its rows instead of merging (see
15
+ // `inbox-store.ts`).
16
+ //
17
+ // A MESSAGE THAT VANISHES BETWEEN THE LIST AND ITS READ IS ORDINARY. The modem's
18
+ // own storage rotates, so a failed per-message read SKIPS that message rather
19
+ // than failing the whole inbox. A failed LIST is different — nothing was read at
20
+ // all — and answers a typed refusal.
21
+ import { MM_BUS_NAME, PROPERTIES_IFACE } from '../backend/constants.js';
22
+ import { numberProp, stringProp } from '../backend/managed-objects.js';
23
+ // The one definition of MM's Messaging interface name lives with the capability
24
+ // probe that also keys on it; duplicating it here is how the two drift apart.
25
+ import { MESSAGING_IFACE } from '../capability/detect.js';
26
+ import { classifySmsFailure } from './mmcli-parse.js';
27
+ import { normalizeSmsState, SMS_INBOX_CAP, selectReadablePaths, sortAndCapSms } from './normalize.js';
28
+ /** `org.freedesktop.ModemManager1.Sms` — one message object. */
29
+ export const SMS_IFACE = 'org.freedesktop.ModemManager1.Sms';
30
+ /**
31
+ * `MMSmsState` (ModemManager `mm-enums.h`) as the port's own vocabulary. The
32
+ * index IS the enum value; an out-of-range value folds to `unknown` through
33
+ * {@link normalizeSmsState}, so a future MM state can never surface as a raw
34
+ * number an operator cannot act on.
35
+ */
36
+ const SMS_STATE_BY_ORDINAL = [
37
+ 'unknown',
38
+ 'stored',
39
+ 'receiving',
40
+ 'received',
41
+ 'sending',
42
+ 'sent',
43
+ ];
44
+ function stateFromOrdinal(ordinal) {
45
+ if (ordinal === undefined) {
46
+ return 'unknown';
47
+ }
48
+ return normalizeSmsState(SMS_STATE_BY_ORDINAL[ordinal]);
49
+ }
50
+ /** Build one message from an SMS object's decoded `Sms` properties. */
51
+ export function smsFromProps(path, props) {
52
+ const from = stringProp(props, 'Number');
53
+ const timestamp = stringProp(props, 'Timestamp');
54
+ const index = path.slice(path.lastIndexOf('/') + 1);
55
+ return {
56
+ id: index,
57
+ ...(from !== undefined && from !== '' ? { from } : {}),
58
+ ...(timestamp !== undefined && timestamp !== '' ? { timestamp } : {}),
59
+ // A data-only (WAP/PDU) message carries no text at all; `''` says so.
60
+ text: stringProp(props, 'Text') ?? '',
61
+ state: stateFromOrdinal(numberProp(props, 'State')),
62
+ };
63
+ }
64
+ function describe(error) {
65
+ return error instanceof Error ? error.message : String(error);
66
+ }
67
+ export function createDbusSmsPort(options) {
68
+ const { transport, modemPath } = options;
69
+ const destination = options.destination ?? MM_BUS_NAME;
70
+ const cap = options.cap ?? SMS_INBOX_CAP;
71
+ const listeners = new Set();
72
+ const subscriptions = [];
73
+ let wiring;
74
+ let stopped = false;
75
+ const emit = (event) => {
76
+ for (const listener of listeners) {
77
+ try {
78
+ listener(event);
79
+ }
80
+ catch (error) {
81
+ options.onError?.(error);
82
+ }
83
+ }
84
+ };
85
+ const readMessage = async (path) => {
86
+ try {
87
+ const reply = await transport.callMethod({
88
+ destination,
89
+ path,
90
+ interface: PROPERTIES_IFACE,
91
+ member: 'GetAll',
92
+ signature: 's',
93
+ args: [SMS_IFACE],
94
+ });
95
+ return smsFromProps(path, reply.body[0]);
96
+ }
97
+ catch {
98
+ // Vanished between the list and this read — ordinary storage rotation.
99
+ // Nothing is logged: the error text is the only place a body could hide.
100
+ return undefined;
101
+ }
102
+ };
103
+ const listInbox = async () => {
104
+ let paths;
105
+ try {
106
+ const reply = await transport.callMethod({
107
+ destination,
108
+ path: modemPath,
109
+ interface: MESSAGING_IFACE,
110
+ member: 'List',
111
+ });
112
+ paths = Array.isArray(reply.body[0]) ? reply.body[0] : [];
113
+ }
114
+ catch (error) {
115
+ return { ok: false, reason: classifySmsFailure(describe(error)) };
116
+ }
117
+ const candidates = selectReadablePaths(paths.filter((value) => typeof value === 'string'), cap);
118
+ const messages = [];
119
+ for (const path of candidates) {
120
+ const message = await readMessage(path);
121
+ if (message !== undefined) {
122
+ messages.push(message);
123
+ }
124
+ }
125
+ return { ok: true, messages: sortAndCapSms(messages, cap) };
126
+ };
127
+ const resync = async () => {
128
+ const result = await listInbox();
129
+ if (result.ok) {
130
+ emit({ kind: 'resynced', messages: result.messages });
131
+ }
132
+ };
133
+ const onAdded = async (body) => {
134
+ const path = body[0];
135
+ if (typeof path !== 'string') {
136
+ return;
137
+ }
138
+ const message = await readMessage(path);
139
+ if (message !== undefined) {
140
+ emit({ kind: 'added', message });
141
+ }
142
+ };
143
+ const wire = async () => {
144
+ const added = await transport.subscribeSignal({ interface: MESSAGING_IFACE, member: 'Added', path: modemPath }, (event) => {
145
+ void onAdded(event.body).catch((error) => options.onError?.(error));
146
+ });
147
+ const deleted = await transport.subscribeSignal({ interface: MESSAGING_IFACE, member: 'Deleted', path: modemPath }, (event) => {
148
+ const path = event.body[0];
149
+ if (typeof path === 'string') {
150
+ emit({ kind: 'deleted', id: path.slice(path.lastIndexOf('/') + 1) });
151
+ }
152
+ });
153
+ subscriptions.push(added, deleted);
154
+ transport.on('reconnected', reconnected);
155
+ // A subscription established AFTER the caller's own `list()` can have
156
+ // missed an arrival in between, so the wiring ends with one resync.
157
+ await resync();
158
+ };
159
+ const reconnected = () => {
160
+ void resync().catch((error) => options.onError?.(error));
161
+ };
162
+ return {
163
+ list: listInbox,
164
+ observe(listener) {
165
+ listeners.add(listener);
166
+ if (wiring === undefined && !stopped) {
167
+ wiring = wire().catch((error) => {
168
+ options.onError?.(error);
169
+ });
170
+ }
171
+ return () => {
172
+ listeners.delete(listener);
173
+ };
174
+ },
175
+ async stop() {
176
+ stopped = true;
177
+ listeners.clear();
178
+ transport.off('reconnected', reconnected);
179
+ await wiring?.catch(() => undefined);
180
+ wiring = undefined;
181
+ const held = subscriptions.splice(0, subscriptions.length);
182
+ await Promise.all(held.map((subscription) => subscription.unsubscribe()));
183
+ },
184
+ };
185
+ }
@@ -0,0 +1,10 @@
1
+ import type { SmsInboxEvent, SmsMessage } from '../ports/sms.js';
2
+ export interface SmsInboxStore {
3
+ /** Apply one event. Answers whether the visible inbox actually changed. */
4
+ apply(event: SmsInboxEvent): boolean;
5
+ /** The current inbox, newest-first and capped. */
6
+ snapshot(): SmsMessage[];
7
+ /** Number of retained rows, before the cap is applied. */
8
+ size(): number;
9
+ }
10
+ export declare function createSmsInboxStore(cap?: number): SmsInboxStore;
@@ -0,0 +1,82 @@
1
+ // The inbox row store — folds `Added` / `Deleted` / resync events into one
2
+ // newest-first, capped list.
3
+ //
4
+ // TWO PROPERTIES ARE THE WHOLE POINT OF THIS FILE, and both are failures a
5
+ // signal-driven inbox produces on its own unless something stops them.
6
+ //
7
+ // DUPLICATE SUPPRESSION. ModemManager emits `Added` for a message it is
8
+ // receiving AND again once it is stored, a re-subscribe after a bus hiccup can
9
+ // replay one, and a consumer that also re-listed would hold the same message
10
+ // twice. Rows are therefore keyed by object index and an `Added` carrying
11
+ // nothing new is a NO-OP — `apply` answers `false` and no consumer is woken.
12
+ //
13
+ // RESTART RECOVERY. A source restart cannot be folded, because the events that
14
+ // happened while it was down were never delivered. `resynced` therefore REPLACES
15
+ // the whole row set rather than merging into it: merging would keep a message
16
+ // deleted during the outage forever, and re-adding each row of a fresh list one
17
+ // `added` at a time is exactly how a restart comes to duplicate the inbox it
18
+ // already had.
19
+ import { SMS_INBOX_CAP, sortAndCapSms } from './normalize.js';
20
+ /** Two rows are the same message when every rendered field matches. */
21
+ function sameMessage(a, b) {
22
+ return (a.id === b.id &&
23
+ a.text === b.text &&
24
+ a.state === b.state &&
25
+ a.from === b.from &&
26
+ a.timestamp === b.timestamp);
27
+ }
28
+ export function createSmsInboxStore(cap = SMS_INBOX_CAP) {
29
+ const rows = new Map();
30
+ const applyAdded = (message) => {
31
+ const held = rows.get(message.id);
32
+ // A repeated Added for a row we already hold VERBATIM is the duplicate
33
+ // this store exists to swallow. An Added that genuinely differs is a
34
+ // state transition (receiving -> received) and does update the row.
35
+ if (held !== undefined && sameMessage(held, message)) {
36
+ return false;
37
+ }
38
+ rows.set(message.id, message);
39
+ return true;
40
+ };
41
+ const applyResynced = (messages) => {
42
+ const next = new Map();
43
+ for (const message of messages) {
44
+ next.set(message.id, message);
45
+ }
46
+ // Report "unchanged" when the authoritative list matches what is already
47
+ // held, so a reconnect that found nothing new broadcasts nothing.
48
+ let changed = next.size !== rows.size;
49
+ if (!changed) {
50
+ for (const [id, message] of next) {
51
+ const held = rows.get(id);
52
+ if (held === undefined || !sameMessage(held, message)) {
53
+ changed = true;
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ rows.clear();
59
+ for (const [id, message] of next) {
60
+ rows.set(id, message);
61
+ }
62
+ return changed;
63
+ };
64
+ return {
65
+ apply(event) {
66
+ switch (event.kind) {
67
+ case 'added':
68
+ return applyAdded(event.message);
69
+ case 'deleted':
70
+ return rows.delete(event.id);
71
+ case 'resynced':
72
+ return applyResynced(event.messages);
73
+ }
74
+ },
75
+ snapshot() {
76
+ return sortAndCapSms([...rows.values()], cap);
77
+ },
78
+ size() {
79
+ return rows.size;
80
+ },
81
+ };
82
+ }
@@ -0,0 +1,4 @@
1
+ export * from './dbus-messaging.js';
2
+ export * from './inbox-store.js';
3
+ export * from './mmcli-parse.js';
4
+ export * from './normalize.js';
@@ -0,0 +1,10 @@
1
+ // The read-only SMS surface: normalization, the `mmcli -K` grammar, the
2
+ // Added/Deleted fold, and the ModemManager Messaging adapter.
3
+ //
4
+ // LIST / READ and observation ONLY. Nothing exported here composes, stores,
5
+ // sends, or deletes a message; `readonly-gate.test.ts` fails the build if that
6
+ // ever stops being true.
7
+ export * from './dbus-messaging.js';
8
+ export * from './inbox-store.js';
9
+ export * from './mmcli-parse.js';
10
+ export * from './normalize.js';
@@ -0,0 +1,54 @@
1
+ import type { SmsMessage, SmsReadRefusal } from '../ports/sms.js';
2
+ /** A parse outcome. `detail` NEVER carries message content — key names only. */
3
+ export type SmsParseResult<T> = {
4
+ readonly ok: true;
5
+ readonly value: T;
6
+ } | {
7
+ readonly ok: false;
8
+ readonly reason: string;
9
+ readonly detail: string;
10
+ };
11
+ /**
12
+ * Undo `g_strescape()` on one `-K` value.
13
+ *
14
+ * mmcli does not print non-ASCII text — it prints the LITERAL ASCII characters
15
+ * of the octal escape. A Spanish message arrives on stdout as the eight
16
+ * characters `\`,`3`,`0`,`2`,`\`,`2`,`4`,`1` where the wire carried the two
17
+ * UTF-8 bytes `0xC2 0xA1` (confirmed on the bench board with `od -c`). The
18
+ * escapes are therefore per-BYTE, not per-character, and the only correct
19
+ * decode is to rebuild the byte sequence and read it back as UTF-8 — decoding
20
+ * each escape with `String.fromCharCode` instead turns `¡` into `¡`.
21
+ *
22
+ * Total and silent: it never throws and never logs, because the value it holds
23
+ * is message content. An escape outside the grammar is copied VERBATIM rather
24
+ * than dropped — mmcli cannot emit one, so meeting one means the value was
25
+ * never escaped and copying it is the only lossless answer.
26
+ */
27
+ export declare function unescapeMmcliValue(value: string): string;
28
+ /**
29
+ * Extract SMS object paths from `mmcli -K -m <id> --messaging-list-sms`.
30
+ *
31
+ * An inbox with no messages prints as `modem.messaging.sms: --`, whose `--`
32
+ * carries no entry — so an ABSENT key is a legitimate EMPTY INBOX, exactly as it
33
+ * is for `--3gpp-scan`, not drift. What IS drift, and what fails loud here, is
34
+ * output that never mentions the key at all (a renamed field, an error body
35
+ * reaching this parser): answering "no messages" to a read that never ran would
36
+ * be the worst possible lie about an inbox.
37
+ */
38
+ export declare function parseSmsListOutput(raw: string): SmsParseResult<string[]>;
39
+ /**
40
+ * Parse one `mmcli -K -s <path>` record.
41
+ *
42
+ * A malformed record reports the KEY NAMES it found and nothing else — see the
43
+ * content-free note at the top of this file.
44
+ */
45
+ export declare function parseSmsRecordOutput(raw: string): SmsParseResult<SmsMessage>;
46
+ /**
47
+ * Classify a source failure into a refusal the operator can act on.
48
+ *
49
+ * The three recognised strings are ModemManager 1.24's own, confirmed on the
50
+ * bench board: a modem with no Messaging interface, a radio that has not come up
51
+ * yet, and a selector nothing answers to. Anything else stays `read_failed`
52
+ * rather than being guessed at.
53
+ */
54
+ export declare function classifySmsFailure(description: string): SmsReadRefusal;