@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,40 @@
1
+ /** The current on-disk schema version. Bump when the persisted shape changes. */
2
+ export declare const FCC_UNLOCK_SCHEMA_VERSION = 1;
3
+ /** The pinned location of the policy of record. `/data` survives a slot swap. */
4
+ export declare const FCC_UNLOCK_POLICY_PATH = "/data/ceralive/fcc-unlock-policy.json";
5
+ /**
6
+ * The persisted document.
7
+ *
8
+ * `unlock` is a TOTAL map from `<vid>:<pid>` to the operator's answer. An absent key
9
+ * and an explicit `false` are the same fact (not opted in) and both are legal on
10
+ * disk: a `false` is what an opt-OUT leaves behind, and keeping it is what lets the
11
+ * shell reconciler prove it parsed a real answer rather than an empty document.
12
+ */
13
+ export interface PersistedFccUnlockPolicy {
14
+ readonly schemaVersion: typeof FCC_UNLOCK_SCHEMA_VERSION;
15
+ readonly savedAtMs: number;
16
+ readonly unlock: Readonly<Record<string, boolean>>;
17
+ }
18
+ /** A metadata-only log event. Corruption NEVER carries the raw file content. */
19
+ export type FccUnlockLogEvent = {
20
+ readonly kind: 'corrupt-policy';
21
+ readonly bytes: number;
22
+ readonly reason: string;
23
+ };
24
+ export type FccUnlockLogger = (event: FccUnlockLogEvent) => void;
25
+ /** The persistence seam `setFccUnlockPolicy` drives. */
26
+ export interface FccUnlockPolicyStore {
27
+ /** Load persisted policy; an absent or unreadable file loads as EMPTY. */
28
+ load(nowMs: number): Promise<PersistedFccUnlockPolicy>;
29
+ /** Atomically write policy with mode 0600 (temp → chmod → rename). */
30
+ save(state: PersistedFccUnlockPolicy): Promise<void>;
31
+ }
32
+ export interface FccUnlockPolicyFileStoreOptions {
33
+ readonly path?: string;
34
+ readonly logger?: FccUnlockLogger;
35
+ }
36
+ /** The `<vid>:<pid>` models the policy positively enables. Sorted, for stability. */
37
+ export declare function enabledFccUnlockKeys(state: PersistedFccUnlockPolicy): string[];
38
+ /** One model's answer. An unmentioned model is NOT enabled — absence is not consent. */
39
+ export declare function isFccUnlockEnabled(state: PersistedFccUnlockPolicy, key: string): boolean;
40
+ export declare function createFccUnlockPolicyFileStore(options?: FccUnlockPolicyFileStoreOptions): FccUnlockPolicyStore;
@@ -0,0 +1,146 @@
1
+ // Durable persistence for the operator's FCC-auto-unlock POLICY.
2
+ //
3
+ // WHY THE FILE IS THE RECORD AND THE SYMLINK IS NOT. ModemManager's opt-in
4
+ // mechanism is a symlink in `/etc/ModemManager/fcc-unlock.d/<vid>:<pid>`. `/etc` is
5
+ // on the rootfs, and the rootfs is exactly what a RAUC A/B slot swap REPLACES
6
+ // (`image-building-pipeline/docs/partition-contract.md`), so that symlink survives a
7
+ // reboot and does NOT survive an OTA. `/data` is the only update-surviving store, so
8
+ // the durable record lives there and the symlink is a derived artifact re-created
9
+ // from it on every boot by `ceralive-fcc-reconcile`.
10
+ //
11
+ // The two hard guarantees are the SAME ones `backend/usage/policy-store.ts` makes,
12
+ // and deliberately implemented the same way so the pair can be read side by side:
13
+ // - MODE 0600 via temp → chmod → atomic rename, regardless of umask.
14
+ // - FAIL-SAFE ON CORRUPTION: an unparseable/incompatible file logs METADATA ONLY
15
+ // (byte length + a classification reason, never the content) and is treated as
16
+ // EMPTY. Note the divergence from the usage store, and it is load-bearing: the
17
+ // usage store REWRITES a fresh file, while this one leaves the damaged bytes on
18
+ // disk for an operator to look at and simply refuses to act on them. Enabling a
19
+ // regulatory-unlock procedure is not something to infer from a file we could not
20
+ // read, and silently replacing the evidence would make the next person's
21
+ // diagnosis impossible.
22
+ //
23
+ // A policy row carries ONLY a `<vid>:<pid>` MODEL identifier and a boolean. There is
24
+ // no per-unit identity here by construction — no serial, no ICCID, no ID_PATH —
25
+ // because ModemManager's mechanism is model-wide and a per-unit key would be a
26
+ // promise the dispatcher cannot keep.
27
+ import { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
28
+ import { dirname } from 'node:path';
29
+ import { isFccUnlockKey } from './coverage.js';
30
+ /** The current on-disk schema version. Bump when the persisted shape changes. */
31
+ export const FCC_UNLOCK_SCHEMA_VERSION = 1;
32
+ /** The pinned location of the policy of record. `/data` survives a slot swap. */
33
+ export const FCC_UNLOCK_POLICY_PATH = '/data/ceralive/fcc-unlock-policy.json';
34
+ function defaultLogger(event) {
35
+ console.warn(`[fcc-unlock-policy] ${event.kind}: bytes=${event.bytes} reason=${event.reason}`);
36
+ }
37
+ function emptyState(nowMs) {
38
+ return { schemaVersion: FCC_UNLOCK_SCHEMA_VERSION, savedAtMs: nowMs, unlock: {} };
39
+ }
40
+ /** A schema violation naming only the offending FIELD (never file content). */
41
+ class FccPolicySchemaError extends Error {
42
+ constructor(field) {
43
+ super(`schema-mismatch: ${field}`);
44
+ }
45
+ }
46
+ /**
47
+ * Parse + validate the document. Throws `FccPolicySchemaError` (metadata-only).
48
+ *
49
+ * WHOLE-DOCUMENT rejection, never per-key skipping: a half-applied policy is a
50
+ * policy nobody wrote, and the shell reconciler makes the same all-or-nothing
51
+ * judgement, so the two halves agree on what a damaged file means.
52
+ */
53
+ function validate(raw) {
54
+ if (typeof raw !== 'object' || raw === null) {
55
+ throw new FccPolicySchemaError('document');
56
+ }
57
+ const doc = raw;
58
+ if (doc.schemaVersion !== FCC_UNLOCK_SCHEMA_VERSION) {
59
+ throw new FccPolicySchemaError('schemaVersion');
60
+ }
61
+ if (typeof doc.savedAtMs !== 'number' || !Number.isFinite(doc.savedAtMs)) {
62
+ throw new FccPolicySchemaError('savedAtMs');
63
+ }
64
+ if (typeof doc.unlock !== 'object' || doc.unlock === null || Array.isArray(doc.unlock)) {
65
+ throw new FccPolicySchemaError('unlock');
66
+ }
67
+ const unlock = {};
68
+ for (const [key, value] of Object.entries(doc.unlock)) {
69
+ if (!isFccUnlockKey(key)) {
70
+ throw new FccPolicySchemaError('unlock.key');
71
+ }
72
+ if (typeof value !== 'boolean') {
73
+ throw new FccPolicySchemaError('unlock.value');
74
+ }
75
+ unlock[key] = value;
76
+ }
77
+ return {
78
+ schemaVersion: FCC_UNLOCK_SCHEMA_VERSION,
79
+ savedAtMs: doc.savedAtMs,
80
+ unlock,
81
+ };
82
+ }
83
+ /** Classify a load failure into a metadata-only reason string (no raw content). */
84
+ function classifyFailure(error) {
85
+ if (error instanceof FccPolicySchemaError) {
86
+ return error.message;
87
+ }
88
+ if (error instanceof SyntaxError) {
89
+ const offset = /position (\d+)/.exec(error.message)?.[1];
90
+ return offset !== undefined ? `invalid-json at offset ${offset}` : 'invalid-json';
91
+ }
92
+ return 'unreadable';
93
+ }
94
+ /** The `<vid>:<pid>` models the policy positively enables. Sorted, for stability. */
95
+ export function enabledFccUnlockKeys(state) {
96
+ return Object.entries(state.unlock)
97
+ .filter(([, enabled]) => enabled)
98
+ .map(([key]) => key)
99
+ .sort();
100
+ }
101
+ /** One model's answer. An unmentioned model is NOT enabled — absence is not consent. */
102
+ export function isFccUnlockEnabled(state, key) {
103
+ return state.unlock[key] === true;
104
+ }
105
+ export function createFccUnlockPolicyFileStore(options = {}) {
106
+ const logger = options.logger ?? defaultLogger;
107
+ const path = options.path ?? FCC_UNLOCK_POLICY_PATH;
108
+ async function writeAtomic(state) {
109
+ await mkdir(dirname(path), { recursive: true });
110
+ const tmp = `${path}.tmp`;
111
+ // The trailing newline is for the shell reconciler's benefit, not decoration:
112
+ // it reads the file with `tr -d`, and a newline-terminated document is what a
113
+ // human `cat`ing it on a board expects to see.
114
+ await writeFile(tmp, `${JSON.stringify(state)}\n`);
115
+ // chmod AFTER the write (not an open flag) so mode is 0600 regardless of umask.
116
+ await chmod(tmp, 0o600);
117
+ await rename(tmp, path);
118
+ }
119
+ return {
120
+ async load(nowMs) {
121
+ let text;
122
+ try {
123
+ text = await readFile(path, 'utf8');
124
+ }
125
+ catch {
126
+ // Absent (or unreadable) → EMPTY, which activates nothing. This is the
127
+ // state on every device that never opted in, and it is the safe default.
128
+ return emptyState(nowMs);
129
+ }
130
+ try {
131
+ return validate(JSON.parse(text));
132
+ }
133
+ catch (error) {
134
+ logger({
135
+ kind: 'corrupt-policy',
136
+ bytes: Buffer.byteLength(text, 'utf8'),
137
+ reason: classifyFailure(error),
138
+ });
139
+ // Deliberately NOT rewritten — see the header. Refuse to act, keep the
140
+ // evidence, and let the next write replace it wholesale.
141
+ return emptyState(nowMs);
142
+ }
143
+ },
144
+ save: writeAtomic,
145
+ };
146
+ }
@@ -0,0 +1,32 @@
1
+ import type { FccUnlockPolicyStore, PersistedFccUnlockPolicy } from './policy-store.js';
2
+ export interface SetFccUnlockPolicyDeps {
3
+ readonly store: FccUnlockPolicyStore;
4
+ /** Injectable clock (defaults to `Date.now`). */
5
+ readonly now?: () => number;
6
+ }
7
+ export interface SetFccUnlockPolicyRequest {
8
+ readonly vid: string;
9
+ readonly pid: string;
10
+ readonly enabled: boolean;
11
+ }
12
+ export type SetFccUnlockPolicyRejection = 'invalid-vid-pid' | 'not-covered';
13
+ export type SetFccUnlockPolicyResult = {
14
+ readonly status: 'applied';
15
+ /** The dispatcher key this write is about, normalized. */
16
+ readonly key: string;
17
+ readonly enabled: boolean;
18
+ /** The whole document now on disk, so a caller need not re-read it. */
19
+ readonly policy: PersistedFccUnlockPolicy;
20
+ /**
21
+ * True when the persisted value CHANGED. A caller uses this to decide
22
+ * whether the modem needs a re-probe: ModemManager runs the dispatcher
23
+ * during initialization only, so a genuine change needs
24
+ * `mmcli -m <id> --disable && --enable` (or a replug) to take effect on an
25
+ * already-enumerated modem — and an unchanged write must not cost one.
26
+ */
27
+ readonly changed: boolean;
28
+ } | {
29
+ readonly status: 'rejected';
30
+ readonly reason: SetFccUnlockPolicyRejection;
31
+ };
32
+ export declare function setFccUnlockPolicy(request: SetFccUnlockPolicyRequest, deps: SetFccUnlockPolicyDeps): Promise<SetFccUnlockPolicyResult>;
@@ -0,0 +1,37 @@
1
+ // `setFccUnlockPolicy` — the WRITE half of the FCC auto-unlock surface.
2
+ //
3
+ // TYPED RESULTS, NEVER A THROW ON BAD INPUT. Following the `PowerHook` and
4
+ // `setUsagePolicy` precedents, a malformed key or an uncovered model is a `rejected`
5
+ // result carrying a named reason rather than an exception — this is called from an
6
+ // RPC boundary, where a throw becomes an opaque 500.
7
+ //
8
+ // THE COVERAGE CHECK IS PART OF THE WRITE, not a UI nicety. Persisting `true` for a
9
+ // model ModemManager ships no procedure for would leave the operator staring at an
10
+ // enabled toggle that provably cannot do anything: the reconciler would find no
11
+ // `<vid>:<pid>` in the available tier and skip it forever, silently. Refusing at the
12
+ // write is the only place that fact can be reported to the person who asked for it.
13
+ //
14
+ // Disabling is deliberately NOT coverage-checked. A `false` must always be
15
+ // persistable — including for a model whose coverage answer has since changed, or
16
+ // which a previous release wrote — because a fail-closed opt-OUT is not a thing.
17
+ import { normalizeVidPid, resolveFccUnlockCoverage } from './coverage.js';
18
+ export async function setFccUnlockPolicy(request, deps) {
19
+ const key = normalizeVidPid(request.vid, request.pid);
20
+ if (key === undefined) {
21
+ return { status: 'rejected', reason: 'invalid-vid-pid' };
22
+ }
23
+ if (request.enabled && resolveFccUnlockCoverage(request.vid, request.pid) !== 'present') {
24
+ return { status: 'rejected', reason: 'not-covered' };
25
+ }
26
+ const now = deps.now ?? Date.now;
27
+ const nowMs = now();
28
+ const current = await deps.store.load(nowMs);
29
+ const changed = (current.unlock[key] === true) !== request.enabled;
30
+ const next = {
31
+ schemaVersion: current.schemaVersion,
32
+ savedAtMs: nowMs,
33
+ unlock: { ...current.unlock, [key]: request.enabled },
34
+ };
35
+ await deps.store.save(next);
36
+ return { status: 'applied', key, enabled: request.enabled, policy: next, changed };
37
+ }
@@ -0,0 +1,39 @@
1
+ export declare function parseHilinkXmlValue(body: string, tag: string): string | undefined;
2
+ export type HilinkSessionDocument = {
3
+ readonly cookie: string;
4
+ readonly token: string;
5
+ };
6
+ export declare function parseHilinkSession(body: string): HilinkSessionDocument | undefined;
7
+ export type HilinkUserState = {
8
+ readonly state: string;
9
+ readonly passwordType: 3 | 4;
10
+ };
11
+ export declare function parseHilinkUserState(body: string): HilinkUserState | undefined;
12
+ export type HilinkProtocolUnknownReason = 'unsupported' | 'not-reported' | 'malformed' | 'auth-expired' | 'unreachable';
13
+ export type HilinkDataCapability = {
14
+ readonly state: 'reported';
15
+ readonly enabled: boolean;
16
+ } | {
17
+ readonly state: 'unavailable';
18
+ readonly reason: HilinkProtocolUnknownReason | 'refused';
19
+ readonly code?: string;
20
+ };
21
+ export declare function parseHilinkDataCapability(body: string): HilinkDataCapability;
22
+ export type HilinkNetModeCapability = {
23
+ readonly state: 'reported';
24
+ readonly modes: readonly {
25
+ readonly id: string;
26
+ readonly name?: string;
27
+ }[];
28
+ readonly current?: string;
29
+ } | {
30
+ readonly state: 'unavailable';
31
+ readonly reason: HilinkProtocolUnknownReason | 'refused';
32
+ readonly code?: string;
33
+ };
34
+ export declare function parseHilinkCapabilities(input: {
35
+ readonly netModeList: string;
36
+ readonly netMode?: string;
37
+ }): {
38
+ readonly net_mode: HilinkNetModeCapability;
39
+ };
@@ -0,0 +1,58 @@
1
+ export function parseHilinkXmlValue(body, tag) {
2
+ const match = body.match(new RegExp(`<${tag}>([^<]*)</${tag}>`, 'i'));
3
+ return match?.[1]?.trim();
4
+ }
5
+ export function parseHilinkSession(body) {
6
+ const cookie = parseHilinkXmlValue(body, 'SesInfo');
7
+ const token = parseHilinkXmlValue(body, 'TokInfo');
8
+ return cookie === undefined || cookie === '' || token === undefined || token === ''
9
+ ? undefined
10
+ : { cookie, token };
11
+ }
12
+ export function parseHilinkUserState(body) {
13
+ const state = parseHilinkXmlValue(body, 'State');
14
+ const rawPasswordType = parseHilinkXmlValue(body, 'password_type');
15
+ if (state === undefined || (rawPasswordType !== '3' && rawPasswordType !== '4'))
16
+ return undefined;
17
+ return { state, passwordType: rawPasswordType === '3' ? 3 : 4 };
18
+ }
19
+ export function parseHilinkDataCapability(body) {
20
+ const code = parseHilinkXmlValue(body, 'code');
21
+ if (code === '125002')
22
+ return { state: 'unavailable', reason: 'auth-expired' };
23
+ if (code !== undefined)
24
+ return { state: 'unavailable', reason: 'refused', code };
25
+ const value = parseHilinkXmlValue(body, 'dataswitch');
26
+ if (value === undefined)
27
+ return { state: 'unavailable', reason: body === '' ? 'unreachable' : 'malformed' };
28
+ if (value !== '0' && value !== '1')
29
+ return { state: 'unavailable', reason: 'malformed' };
30
+ return { state: 'reported', enabled: value === '1' };
31
+ }
32
+ export function parseHilinkCapabilities(input) {
33
+ const code = parseHilinkXmlValue(input.netModeList, 'code');
34
+ if (code === '125002')
35
+ return { net_mode: { state: 'unavailable', reason: 'auth-expired' } };
36
+ if (code !== undefined)
37
+ return { net_mode: { state: 'unavailable', reason: 'refused', code } };
38
+ if (input.netModeList.trim() === '')
39
+ return { net_mode: { state: 'unavailable', reason: 'unreachable' } };
40
+ // `malformed` is a statement about the BODY — something that is not this API
41
+ // answered. A `<response>` carrying no mode list IS this API, saying nothing,
42
+ // which is `not-reported` below.
43
+ if (!/<response>/i.test(input.netModeList))
44
+ return { net_mode: { state: 'unavailable', reason: 'malformed' } };
45
+ const modes = [...input.netModeList.matchAll(/<NetworkMode>([\s\S]*?)<\/NetworkMode>/gi)].flatMap((match) => {
46
+ const id = parseHilinkXmlValue(match[1] ?? '', 'Index');
47
+ if (id === undefined || id === '')
48
+ return [];
49
+ const name = parseHilinkXmlValue(match[1] ?? '', 'Name');
50
+ return name === undefined || name === '' ? [{ id }] : [{ id, name }];
51
+ });
52
+ if (modes.length === 0)
53
+ return { net_mode: { state: 'unavailable', reason: 'not-reported' } };
54
+ const current = parseHilinkXmlValue(input.netMode ?? '', 'NetworkMode');
55
+ return current === undefined || current === ''
56
+ ? { net_mode: { state: 'reported', modes } }
57
+ : { net_mode: { state: 'reported', modes, current } };
58
+ }
@@ -0,0 +1,3 @@
1
+ export * from '../band/index.js';
2
+ export * from '../usb-mode/index.js';
3
+ export * from './router-parsers.js';
@@ -0,0 +1,15 @@
1
+ // `@ceralive/modem-control/hardware` — the per-SKU hardware model.
2
+ //
3
+ // This subpath is the narrow entry for everything keyed on the PHYSICAL unit rather
4
+ // than on a live D-Bus object: which USB composition a SKU may be switched into and
5
+ // which transitions were certified for it (`../usb-mode`), and the MMModemBand
6
+ // vocabulary plus the per-SKU band-lock certification catalog (`../band`).
7
+ //
8
+ // Both halves are evidence-gated catalogs plus their pure lookups — no transport, no
9
+ // mutation verb. The D-Bus verbs that ACT on these facts stay where they live
10
+ // (`../backend/mm-mutations.ts`, declared on `ModemManagerPort`); a consumer that only
11
+ // needs to know what a SKU is capable of should not have to import a bus client to
12
+ // find out. That asymmetry is the reason this entry exists.
13
+ export * from '../band/index.js';
14
+ export * from '../usb-mode/index.js';
15
+ export * from './router-parsers.js';
@@ -0,0 +1,89 @@
1
+ export * from './hilink-protocol.js';
2
+ export type SimPresence = 'present' | 'absent' | 'unknown';
3
+ export type SimPresenceFacts = {
4
+ readonly sim?: string;
5
+ readonly simSlots?: readonly string[];
6
+ readonly failedReason?: string;
7
+ };
8
+ /** The mmcli spelling of `MM_MODEM_STATE_FAILED_REASON_SIM_MISSING` — the ONLY proof of absence. */
9
+ export declare const SIM_MISSING_FAILED_REASON = "sim-missing";
10
+ /** The fields a presence decision may be drawn from, in the order they are inspected. */
11
+ export declare const SIM_PRESENCE_FIELDS: readonly ['sim', 'simSlots', 'failedReason'];
12
+ export type SimPresenceField = (typeof SIM_PRESENCE_FIELDS)[number];
13
+ /**
14
+ * WHICH FACT decided a SIM presence — the whole point of this type.
15
+ *
16
+ * `absent` is reachable through exactly ONE member (`state-failed-reason`), so a
17
+ * consumer can prove that no code path inferred "there is no SIM" from a blank or
18
+ * missing field. A modem that exports `Sim: '/'` and says nothing else is
19
+ * `no-evidence`/`unknown`: an empty object path is ModemManager's answer for "no SIM
20
+ * object is bound right now", which a modem also reports while it is still
21
+ * initializing, while its SIM is locked out, and while a slot switch is in flight.
22
+ *
23
+ * `vendor-code-unclaimed` is the router half. HiLink, goform and HIMI each report
24
+ * their own presence code with vendor semantics no migrated decoder covers, so the
25
+ * code is NAMED here and its value stays verbatim in the diagnostics block, rather
26
+ * than being guessed into a presence.
27
+ */
28
+ export type SimPresenceEvidence = {
29
+ readonly kind: 'sim-object-path';
30
+ readonly field: 'sim';
31
+ readonly value: string;
32
+ } | {
33
+ readonly kind: 'sim-slot-object-path';
34
+ readonly field: 'simSlots';
35
+ readonly value: string;
36
+ } | {
37
+ readonly kind: 'state-failed-reason';
38
+ readonly field: 'failedReason';
39
+ readonly value: typeof SIM_MISSING_FAILED_REASON;
40
+ } | {
41
+ readonly kind: 'no-evidence';
42
+ readonly inspected: readonly SimPresenceField[];
43
+ } | {
44
+ readonly kind: 'vendor-code-unclaimed';
45
+ readonly field: string;
46
+ };
47
+ export type SimPresenceReading = {
48
+ readonly presence: SimPresence;
49
+ readonly evidence: SimPresenceEvidence;
50
+ };
51
+ /** The presence decision together with the fact that produced it. */
52
+ export declare function readSimPresence(facts: SimPresenceFacts): SimPresenceReading;
53
+ export declare function deriveSimPresence(facts: SimPresenceFacts): SimPresence;
54
+ export type RouterSignalUnknownReason = 'unsupported' | 'not-reported' | 'malformed' | 'auth-expired' | 'unreachable';
55
+ export type RouterSignalMetric = {
56
+ readonly state: 'known';
57
+ readonly value: number;
58
+ } | {
59
+ readonly state: 'unknown';
60
+ readonly reason: RouterSignalUnknownReason;
61
+ };
62
+ export type RouterSignalModel = {
63
+ readonly provenance: 'hilink-admin-api' | 'zte-goform' | 'ufi-himiapi';
64
+ readonly freshness: 'live' | 'unknown';
65
+ readonly bars: RouterSignalMetric;
66
+ readonly max_bars: RouterSignalMetric;
67
+ readonly dbm: RouterSignalMetric;
68
+ readonly rsrp: RouterSignalMetric;
69
+ readonly rsrq: RouterSignalMetric;
70
+ readonly snr: RouterSignalMetric;
71
+ readonly sinr: RouterSignalMetric;
72
+ };
73
+ export declare function parseHilinkSignal(input: {
74
+ readonly status: string;
75
+ readonly signal: string;
76
+ }): RouterSignalModel;
77
+ export declare function parseZteSignal(body: string): RouterSignalModel;
78
+ export declare function parseUfiSignal(input: {
79
+ readonly sysinfo: string;
80
+ readonly overview: string;
81
+ readonly status: string;
82
+ }): RouterSignalModel;
83
+ export type RouterDetails = Readonly<Record<string, string>>;
84
+ export declare function parseZteDetails(body: string): RouterDetails | undefined;
85
+ export declare function parseUfiDetails(input: {
86
+ readonly overview?: string;
87
+ readonly sysinfo?: string;
88
+ readonly produceInfo?: string;
89
+ }): RouterDetails | undefined;