@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,23 @@
1
+ import type { AuthenticatedProfileResult, ProviderMatchRequest } from '../contracts.js';
2
+ import { type ZteOptions, type ZteProfile } from './provider.js';
3
+ import type { ZteHttpResponse } from './transport.js';
4
+ type ZteEvidence = {
5
+ readonly record: Readonly<Record<string, string | number>>;
6
+ readonly profile: ZteProfile | undefined;
7
+ };
8
+ export declare function parseZteRecord(body: string): Readonly<Record<string, string | number>> | undefined;
9
+ export declare class ZteSessionRuntime {
10
+ #private;
11
+ protected readonly options: ZteOptions;
12
+ constructor(options: ZteOptions);
13
+ authenticateProfile(request: ProviderMatchRequest, candidates: readonly string[]): Promise<AuthenticatedProfileResult>;
14
+ protected probeEvidence(request: ProviderMatchRequest): Promise<ZteEvidence | undefined>;
15
+ protected sessionCookie(request: ProviderMatchRequest): string | undefined;
16
+ protected get(cmd: string, cookie?: string, multiData?: boolean): Promise<ZteHttpResponse>;
17
+ private login;
18
+ private loginSalted;
19
+ private sessionKey;
20
+ private post;
21
+ private request;
22
+ }
23
+ export {};
@@ -0,0 +1,197 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ import { ZTE_EVIDENCE_CMD, ZTE_PATHS, ZTE_UNKNOWN_PROFILE, zteProfileById, zteProfilesForFirmware, } from './provider.js';
4
+ const flatRecordSchema = z.record(z.string(), z.union([z.string(), z.number()]));
5
+ export function parseZteRecord(body) {
6
+ const result = z
7
+ .string()
8
+ .transform((value, context) => {
9
+ try {
10
+ return JSON.parse(value);
11
+ }
12
+ catch (error) {
13
+ if (!(error instanceof SyntaxError))
14
+ throw error;
15
+ context.addIssue({ code: 'custom', message: 'invalid JSON' });
16
+ return z.NEVER;
17
+ }
18
+ })
19
+ .pipe(flatRecordSchema)
20
+ .safeParse(body);
21
+ return result.success ? result.data : undefined;
22
+ }
23
+ function stokCookie(response) {
24
+ const expected = 'set-cookie';
25
+ const header = Object.entries(response.headers ?? {}).find(([key]) => key.toLowerCase() === expected)?.[1];
26
+ const cookie = header?.split(';', 1)[0]?.trim();
27
+ return cookie?.startsWith('stok=') ? cookie : undefined;
28
+ }
29
+ function sha256(value) {
30
+ return createHash('sha256').update(value).digest('hex').toUpperCase();
31
+ }
32
+ function evidenceNumber(value) {
33
+ if (typeof value === 'string' && value.trim() === '')
34
+ return undefined;
35
+ const parsed = typeof value === 'number' ? value : Number(value);
36
+ return Number.isInteger(parsed) && parsed >= 0 ? parsed : undefined;
37
+ }
38
+ function profileFromEvidence(firmware, record) {
39
+ const versionEvidence = `${record.wa_inner_version ?? ''} ${record.cr_version ?? ''}`.toUpperCase();
40
+ const family = versionEvidence.includes('MF266')
41
+ ? 'MF266'
42
+ : versionEvidence.includes('MF79U')
43
+ ? 'MF79U'
44
+ : firmware;
45
+ const hasLd = typeof record.LD === 'string' && record.LD.length > 0;
46
+ const profileId = family === 'MF266'
47
+ ? hasLd
48
+ ? 'mf266-salted'
49
+ : undefined
50
+ : family === 'MF79U'
51
+ ? hasLd
52
+ ? 'mf79u-ld-salted'
53
+ : 'mf79u-legacy'
54
+ : undefined;
55
+ return zteProfilesForFirmware(family).find((profile) => profile.id === profileId);
56
+ }
57
+ function classifyLogin(response) {
58
+ const result = parseZteRecord(response.body)?.result;
59
+ if (response.status !== 200 || result === '1') {
60
+ return { status: 'refused', detail: 'protocol-mismatch' };
61
+ }
62
+ if (result === '3')
63
+ return { status: 'refused', detail: 'auth-rejection' };
64
+ const cookie = stokCookie(response);
65
+ return result === '0' && cookie !== undefined
66
+ ? { status: 'accepted', cookie }
67
+ : { status: 'refused', detail: 'protocol-mismatch' };
68
+ }
69
+ export class ZteSessionRuntime {
70
+ options;
71
+ #sessions = new Map();
72
+ #evidence = new Map();
73
+ constructor(options) {
74
+ this.options = options;
75
+ }
76
+ async authenticateProfile(request, candidates) {
77
+ const candidate = candidates.length === 1 ? candidates[0] : undefined;
78
+ if (candidate === ZTE_UNKNOWN_PROFILE) {
79
+ return { status: 'matched', profile: ZTE_UNKNOWN_PROFILE, detail: 'read-only-fingerprint' };
80
+ }
81
+ const profile = zteProfileById(candidate ?? '');
82
+ if (profile === undefined) {
83
+ return { status: 'refused', detail: 'profile-mismatch' };
84
+ }
85
+ const evidence = this.#evidence.get(this.sessionKey(request)) ?? (await this.probeEvidence(request));
86
+ if (evidence === undefined)
87
+ return { status: 'refused', detail: 'protocol-mismatch' };
88
+ const remainingAttempts = evidenceNumber(evidence.record.psw_fail_num_str);
89
+ const lockTime = evidenceNumber(evidence.record.login_lock_time);
90
+ if (remainingAttempts === undefined || lockTime === undefined) {
91
+ return { status: 'refused', detail: 'protocol-mismatch' };
92
+ }
93
+ if (lockTime > 0 || remainingAttempts === 0) {
94
+ return { status: 'refused', detail: 'lockout' };
95
+ }
96
+ if (evidence.profile?.id !== profile.id) {
97
+ return { status: 'refused', detail: 'protocol-mismatch' };
98
+ }
99
+ switch (profile.algorithm) {
100
+ case 'legacy-base64':
101
+ return this.login(request, profile, Buffer.from(this.options.credentials.password).toString('base64'));
102
+ case 'login-salted-sha256': {
103
+ const ld = evidence.record.LD;
104
+ if (typeof ld !== 'string')
105
+ return { status: 'refused', detail: 'protocol-mismatch' };
106
+ return this.login(request, profile, sha256(`${sha256(this.options.credentials.password)}${ld}`));
107
+ }
108
+ case 'multi-user-salted-sha256':
109
+ return this.loginSalted(request, profile, evidence.record);
110
+ default: {
111
+ const exhaustive = profile.algorithm;
112
+ return exhaustive;
113
+ }
114
+ }
115
+ }
116
+ async probeEvidence(request) {
117
+ const response = await this.get(ZTE_EVIDENCE_CMD, undefined, true);
118
+ const record = response.status === 200 ? parseZteRecord(response.body) : undefined;
119
+ if (record === undefined)
120
+ return undefined;
121
+ const evidence = { record, profile: profileFromEvidence(request.firmware, record) };
122
+ this.#evidence.set(this.sessionKey(request), evidence);
123
+ return evidence;
124
+ }
125
+ sessionCookie(request) {
126
+ return this.#sessions.get(this.sessionKey(request))?.cookie;
127
+ }
128
+ get(cmd, cookie, multiData = false) {
129
+ const query = new URLSearchParams({ isTest: 'false', cmd });
130
+ if (multiData)
131
+ query.set('multi_data', '1');
132
+ return this.request('GET', `${ZTE_PATHS.get}?${query.toString()}`, undefined, cookie);
133
+ }
134
+ async login(request, profile, password) {
135
+ const response = await this.post(new URLSearchParams({
136
+ goformId: 'LOGIN',
137
+ isTest: 'false',
138
+ password,
139
+ }).toString());
140
+ const result = classifyLogin(response);
141
+ if (result.status === 'refused')
142
+ return result;
143
+ this.#sessions.set(this.sessionKey(request), { cookie: result.cookie });
144
+ return { status: 'matched', profile: profile.id, detail: 'login-ok' };
145
+ }
146
+ async loginSalted(request, profile, evidence) {
147
+ const ld = evidence.LD;
148
+ if (typeof ld !== 'string') {
149
+ return { status: 'refused', detail: 'protocol-mismatch' };
150
+ }
151
+ const login = await this.post(new URLSearchParams({
152
+ goformId: 'LOGIN_MULTI_USER',
153
+ isTest: 'false',
154
+ password: sha256(`${sha256(this.options.credentials.password)}${ld}`),
155
+ IP: 'localhost',
156
+ user: this.options.credentials.username,
157
+ }).toString());
158
+ const result = classifyLogin(login);
159
+ if (result.status === 'refused')
160
+ return result;
161
+ const rd = parseZteRecord((await this.get('RD', result.cookie)).body)?.RD;
162
+ const waVersion = evidence.wa_inner_version;
163
+ const crVersion = evidence.cr_version;
164
+ if (typeof waVersion !== 'string' || typeof crVersion !== 'string' || typeof rd !== 'string') {
165
+ return { status: 'refused', detail: 'protocol-mismatch' };
166
+ }
167
+ this.#sessions.set(this.sessionKey(request), {
168
+ cookie: result.cookie,
169
+ ad: sha256(`${sha256(`${waVersion}${crVersion}`)}${rd}`),
170
+ });
171
+ return { status: 'matched', profile: profile.id, detail: 'login-ok' };
172
+ }
173
+ sessionKey(request) {
174
+ return `${request.physicalModemId}:${request.generation}`;
175
+ }
176
+ post(body) {
177
+ return this.request('POST', ZTE_PATHS.set, body);
178
+ }
179
+ request(method, path, body, cookie) {
180
+ const headers = [
181
+ ...(method === 'POST'
182
+ ? ['Content-Type: application/x-www-form-urlencoded; charset=UTF-8']
183
+ : []),
184
+ ...(cookie === undefined ? [] : [`Cookie: ${cookie}`]),
185
+ `Origin: ${this.options.adminUrl}`,
186
+ `Referer: ${this.options.adminUrl}/index.html`,
187
+ ];
188
+ return this.options.transport.request({
189
+ method,
190
+ url: `${this.options.adminUrl}${path}`,
191
+ ...(body === undefined ? {} : { body }),
192
+ headers,
193
+ interfaceName: this.options.interfaceName,
194
+ redirect: 'error',
195
+ });
196
+ }
197
+ }
@@ -0,0 +1,16 @@
1
+ export type ZteHttpRequest = {
2
+ readonly method: 'GET' | 'POST';
3
+ readonly url: string;
4
+ readonly body?: string;
5
+ readonly headers: readonly string[];
6
+ readonly interfaceName: string;
7
+ readonly redirect: 'error';
8
+ };
9
+ export type ZteHttpResponse = {
10
+ readonly status: number;
11
+ readonly body: string;
12
+ readonly headers?: Readonly<Record<string, string>>;
13
+ };
14
+ export interface ZteTransport {
15
+ request(request: ZteHttpRequest): Promise<ZteHttpResponse>;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import { type BandCertificationEntry, type BandName } from '../band/index.js';
2
+ import { type OperationDescriptor } from '../domain/index.js';
3
+ import type { ModemBands } from '../ports/index.js';
4
+ export declare const BAND_WRITE_OPERATION_ID = "modemmanager.bands";
5
+ /** The refusal reasons a band write may carry. Certification is the first gate. */
6
+ export declare const BAND_WRITE_REFUSAL = "band-certification-required";
7
+ export declare const BAND_READ_REFUSAL = "band-read-unsupported";
8
+ export declare const BAND_NONE_OFFERABLE_REFUSAL = "no-offerable-certified-bands";
9
+ /**
10
+ * The band-lock certification decision for one device, as a descriptor consumer sees it.
11
+ *
12
+ * `required` is `true` unconditionally and is typed as the literal, so no code path can
13
+ * produce a band-write decision that does not require certification. This is the one
14
+ * capability module documented as STRICTER than `support-claim.ts`'s `capable` floor.
15
+ */
16
+ export type BandWriteCertification = {
17
+ readonly required: true;
18
+ readonly satisfied: boolean;
19
+ readonly reason: 'band-certification-proven' | typeof BAND_WRITE_REFUSAL;
20
+ /** What the catalog proves is settable, intersected with what the modem advertises. */
21
+ readonly offerable: readonly BandName[];
22
+ };
23
+ export declare function describeBandWriteCertification(input: {
24
+ readonly entry: BandCertificationEntry | undefined;
25
+ readonly supported: readonly BandName[];
26
+ }): BandWriteCertification;
27
+ export type BandWriteDescriptorInput = {
28
+ readonly provider: string;
29
+ readonly profile: string;
30
+ readonly certification: BandWriteCertification;
31
+ readonly readSupported: boolean;
32
+ };
33
+ /**
34
+ * Whether a band readback confirms the write.
35
+ *
36
+ * A NARROWING lock must match exactly — a superset is a different lock from the one
37
+ * that was asked for. The reset (`['any']`) is the exception ModemManager forces:
38
+ * releasing a lock is `SetCurrentBands([ANY])`, and a modem afterwards reports either
39
+ * `any` or its whole supported set, both of which mean "no lock is in force".
40
+ */
41
+ export declare function bandWriteReadbackMatches(requested: readonly BandName[], observed: ModemBands): boolean;
42
+ /**
43
+ * The live band-write descriptor.
44
+ *
45
+ * `mutationImpact: 'disruptive'` because `SetCurrentBands` re-registers the radio and
46
+ * drops the bearer underneath NetworkManager; `readback` is REQUIRED because an
47
+ * accepted-but-ignored band write is the failure mode the catalog's own `readback`
48
+ * proof exists to catch, and it looks like success from the call site alone.
49
+ */
50
+ export declare function buildBandWriteDescriptor(input: BandWriteDescriptorInput): OperationDescriptor<readonly BandName[], ModemBands>;
@@ -0,0 +1,92 @@
1
+ // The band-write descriptor — the certification gate, expressed as an operation contract.
2
+ //
3
+ // It ADDS NOTHING to `band/certification.ts`. That module already owns the four-proof
4
+ // per-SKU catalog, the fail-closed lookup, and the `offerableBands` narrowing, and it
5
+ // is the only place a SKU may be declared certified. What was missing was the other
6
+ // end of the wire: a band write's OPERATION DESCRIPTOR did not say that it is
7
+ // disruptive-with-a-certification-requirement, so the gate lived only inside the
8
+ // provider's capability flag and a consumer reading the descriptor could not see it.
9
+ //
10
+ // TWO INDEPENDENT FENCES, deliberately. `availability: refused` is what a consumer
11
+ // reads to decide whether to offer the control at all; the provider's own
12
+ // `bandWrite` capability check is what refuses the call if one is made anyway. A gate
13
+ // that exists only in the descriptor is advisory, and a gate that exists only in the
14
+ // provider is invisible — a band lock can take a working uplink off the air, so it
15
+ // gets both.
16
+ import { offerableBands } from '../band/index.js';
17
+ import { defineOperationDescriptor } from '../domain/index.js';
18
+ export const BAND_WRITE_OPERATION_ID = 'modemmanager.bands';
19
+ /** The refusal reasons a band write may carry. Certification is the first gate. */
20
+ export const BAND_WRITE_REFUSAL = 'band-certification-required';
21
+ export const BAND_READ_REFUSAL = 'band-read-unsupported';
22
+ export const BAND_NONE_OFFERABLE_REFUSAL = 'no-offerable-certified-bands';
23
+ export function describeBandWriteCertification(input) {
24
+ const offerable = offerableBands(input.entry, input.supported);
25
+ return input.entry === undefined
26
+ ? { required: true, satisfied: false, reason: BAND_WRITE_REFUSAL, offerable }
27
+ : { required: true, satisfied: true, reason: 'band-certification-proven', offerable };
28
+ }
29
+ function sameBandSet(left, right) {
30
+ if (left.length !== right.length)
31
+ return false;
32
+ const sorted = [...right].sort();
33
+ return [...left].sort().every((band, index) => band === sorted[index]);
34
+ }
35
+ /**
36
+ * Whether a band readback confirms the write.
37
+ *
38
+ * A NARROWING lock must match exactly — a superset is a different lock from the one
39
+ * that was asked for. The reset (`['any']`) is the exception ModemManager forces:
40
+ * releasing a lock is `SetCurrentBands([ANY])`, and a modem afterwards reports either
41
+ * `any` or its whole supported set, both of which mean "no lock is in force".
42
+ */
43
+ export function bandWriteReadbackMatches(requested, observed) {
44
+ if (requested.length === 1 && requested[0] === 'any') {
45
+ return ((observed.current.length === 1 && observed.current[0] === 'any') ||
46
+ sameBandSet(observed.current, observed.supported));
47
+ }
48
+ return sameBandSet(requested, observed.current);
49
+ }
50
+ /**
51
+ * The live band-write descriptor.
52
+ *
53
+ * `mutationImpact: 'disruptive'` because `SetCurrentBands` re-registers the radio and
54
+ * drops the bearer underneath NetworkManager; `readback` is REQUIRED because an
55
+ * accepted-but-ignored band write is the failure mode the catalog's own `readback`
56
+ * proof exists to catch, and it looks like success from the call site alone.
57
+ */
58
+ export function buildBandWriteDescriptor(input) {
59
+ const refusal = !input.certification.satisfied
60
+ ? BAND_WRITE_REFUSAL
61
+ : input.certification.offerable.length === 0
62
+ ? BAND_NONE_OFFERABLE_REFUSAL
63
+ : undefined;
64
+ return defineOperationDescriptor({
65
+ id: BAND_WRITE_OPERATION_ID,
66
+ support: {
67
+ read: input.readSupported
68
+ ? { supported: true }
69
+ : { supported: false, reason: BAND_READ_REFUSAL },
70
+ write: input.certification.satisfied
71
+ ? { supported: true }
72
+ : { supported: false, reason: BAND_WRITE_REFUSAL },
73
+ },
74
+ authority: 'provider',
75
+ provider: input.provider,
76
+ constraints: { kind: 'allowed-values', values: [input.certification.offerable] },
77
+ livePreconditions: ['modem-present', 'runtime-interface-present', 'band-certification-present'],
78
+ availability: refusal === undefined ? { state: 'available' } : { state: 'refused', reason: refusal },
79
+ mutationImpact: 'disruptive',
80
+ retryClass: 'never',
81
+ readback: {
82
+ required: true,
83
+ reason: 'band-write-readback',
84
+ matches: bandWriteReadbackMatches,
85
+ },
86
+ rollback: { required: false },
87
+ journal: { required: true, reason: 'disruptive-radio-write' },
88
+ admission: { required: true, reason: 'provider-mutation' },
89
+ evidence: { profiles: [input.profile], firmware: [] },
90
+ confidence: 'high',
91
+ });
92
+ }
@@ -0,0 +1,3 @@
1
+ export * from './band-truth.js';
2
+ export * from './mode-combinations.js';
3
+ export * from './mode-truth.js';
@@ -0,0 +1,10 @@
1
+ // Radio capability TRUTH: the modem's own mode catalog and band-write gate, verbatim.
2
+ //
3
+ // It sits beside `src/band/` (the band vocabulary and per-SKU certification catalog)
4
+ // rather than inside it, because a mode combination is not a band and the two have
5
+ // different safety models — a mode change is disruptive-but-reversible, a band lock
6
+ // can strand a radio where nothing registers. Reachable through the package ROOT
7
+ // entry, deliberately NOT a new package subpath (the todo 17/18/23 precedent).
8
+ export * from './band-truth.js';
9
+ export * from './mode-combinations.js';
10
+ export * from './mode-truth.js';
@@ -0,0 +1,88 @@
1
+ /** A mode as every operator-facing surface spells it. Opaque; compare by equality. */
2
+ export type ModeName = string;
3
+ /**
4
+ * `MM_MODEM_MODE_NONE` (0) — the modem expresses no preference within its allowed set.
5
+ * A legal, load-bearing value; never a stand-in for "not reported".
6
+ */
7
+ export declare const MODE_NONE = "none";
8
+ /** `MM_MODEM_MODE_ANY` (0xFFFFFFFF) — every mode the modem has. */
9
+ export declare const MODE_ANY = "any";
10
+ /** Decode one `MMModemMode` bit. Total: an unnamed bit round-trips. */
11
+ export declare function modeName(bit: number): ModeName;
12
+ /** Encode one mode name. `undefined` for a name this build cannot place. */
13
+ export declare function modeValue(name: ModeName): number | undefined;
14
+ /** True when this build recognises the name (a `mode-bit-<n>` passthrough does not). */
15
+ export declare function isNamedMode(name: ModeName): boolean;
16
+ /**
17
+ * Split a mask into its set bits, named where this build can and passed through where
18
+ * it cannot. A zero mask is the EMPTY set — the caller decides whether that reads as
19
+ * `none` (a preference) or as an anomaly (an allowed set nothing can be chosen from).
20
+ */
21
+ export declare function modeNames(mask: number): readonly ModeName[];
22
+ /** Encode a set of mode names into one mask. Fails closed on an unplaceable name. */
23
+ export declare function encodeModeNames(names: readonly ModeName[]): {
24
+ readonly ok: true;
25
+ readonly mask: number;
26
+ } | {
27
+ readonly ok: false;
28
+ readonly unknown: ModeName;
29
+ };
30
+ /** Why a combination could not be fully placed. Never a reason to hide it. */
31
+ export declare const MODE_COMBINATION_ANOMALIES: readonly [
32
+ /** The allowed mask carries a bit this build does not name. */
33
+ 'unnamed-allowed-bit',
34
+ /** The preferred mask carries a bit this build does not name. */
35
+ 'unnamed-preferred-bit',
36
+ /** The preferred mode is not a member of the allowed set. */
37
+ 'preferred-not-in-allowed',
38
+ /** The preferred mask names more than one mode; MM's contract is at most one. */
39
+ 'preferred-not-singular',
40
+ /** The allowed mask is zero — nothing can be selected from this combination. */
41
+ 'empty-allowed'];
42
+ export type ModeCombinationAnomaly = (typeof MODE_COMBINATION_ANOMALIES)[number];
43
+ export type ModeCombinationClassification = 'named' | 'unknown-combination';
44
+ /**
45
+ * One `(allowed, preferred)` pair, decoded without loss.
46
+ *
47
+ * The masks are retained ALONGSIDE the names so a consumer can always reproduce the
48
+ * exact bytes the modem reported, whatever this build managed to name.
49
+ */
50
+ export type ModeCombination = {
51
+ readonly allowedMask: number;
52
+ readonly allowed: readonly ModeName[];
53
+ readonly preferredMask: number;
54
+ /** `none` when the modem stated no preference — verbatim, never a substitute. */
55
+ readonly preferred: ModeName;
56
+ readonly classification: ModeCombinationClassification;
57
+ readonly anomalies: readonly ModeCombinationAnomaly[];
58
+ };
59
+ /**
60
+ * A `SupportedModes` catalog: everything decoded, plus everything that could not be.
61
+ *
62
+ * `undecodable` exists so the no-drop property is structural rather than a promise —
63
+ * `combinations.length + undecodable.length` is the member count the provider sent.
64
+ */
65
+ export type ModeCombinationSet = {
66
+ readonly combinations: readonly ModeCombination[];
67
+ /** Members that were not a `(uu)` pair, retained exactly as the provider sent them. */
68
+ readonly undecodable: readonly unknown[];
69
+ };
70
+ /** Build a combination from two raw masks, recording every anomaly it carries. */
71
+ export declare function modeCombination(allowedMask: number, preferredMask: number): ModeCombination;
72
+ /** True when the modem stated no preference within this combination's allowed set. */
73
+ export declare function statesNoPreference(combination: ModeCombination): boolean;
74
+ /** Decode one `CurrentModes` `(uu)`. `undefined` only when the value is not a pair. */
75
+ export declare function decodeModeCombination(value: unknown): ModeCombination | undefined;
76
+ /**
77
+ * Decode a `SupportedModes` `a(uu)`.
78
+ *
79
+ * Nothing is dropped: a member that is not a pair lands in `undecodable`, and a pair
80
+ * this build cannot fully name lands in `combinations` classified
81
+ * `unknown-combination`. A non-array value is an empty catalog, not an error — a modem
82
+ * that advertises no mode control is a real reading.
83
+ */
84
+ export declare function decodeSupportedModeCombinations(value: unknown): ModeCombinationSet;
85
+ /** True when any advertised combination carries an anomaly this build could not place. */
86
+ export declare function hasUnknownCombination(set: ModeCombinationSet): boolean;
87
+ /** Whether a mask names a mode this build recognises across every set bit. */
88
+ export declare function isFullyNamedMask(mask: number): boolean;