@ceralive/modem-control 0.2.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (464) hide show
  1. package/README.md +317 -0
  2. package/dist/backend/at-lease.d.ts +57 -0
  3. package/dist/backend/at-lease.js +109 -0
  4. package/dist/backend/cell-info.d.ts +46 -0
  5. package/dist/backend/cell-info.js +124 -0
  6. package/dist/backend/constants.d.ts +24 -0
  7. package/{src/backend/constants.ts → dist/backend/constants.js} +4 -9
  8. package/dist/backend/device-classifier.d.ts +46 -0
  9. package/dist/backend/device-classifier.js +258 -0
  10. package/dist/backend/enrichment.d.ts +28 -0
  11. package/dist/backend/enrichment.js +59 -0
  12. package/dist/backend/features.d.ts +61 -0
  13. package/dist/backend/features.js +109 -0
  14. package/dist/backend/identity-ladder.d.ts +57 -0
  15. package/dist/backend/identity-ladder.js +158 -0
  16. package/dist/backend/identity-registry.d.ts +51 -0
  17. package/dist/backend/identity-registry.js +101 -0
  18. package/dist/backend/index.d.ts +30 -0
  19. package/dist/backend/index.js +35 -0
  20. package/dist/backend/lifecycle-interlock.d.ts +25 -0
  21. package/dist/backend/lifecycle-interlock.js +18 -0
  22. package/dist/backend/managed-objects.d.ts +39 -0
  23. package/dist/backend/managed-objects.js +82 -0
  24. package/dist/backend/mapping.d.ts +11 -0
  25. package/dist/backend/mapping.js +148 -0
  26. package/dist/backend/mm-backend.d.ts +44 -0
  27. package/dist/backend/mm-backend.js +154 -0
  28. package/dist/backend/mm-location.d.ts +21 -0
  29. package/dist/backend/mm-location.js +237 -0
  30. package/dist/backend/mm-mutations.d.ts +42 -0
  31. package/dist/backend/mm-mutations.js +259 -0
  32. package/dist/backend/modem-actor.d.ts +41 -0
  33. package/dist/backend/modem-actor.js +78 -0
  34. package/dist/backend/nm-auto-apn.d.ts +54 -0
  35. package/dist/backend/nm-auto-apn.js +124 -0
  36. package/dist/backend/nm-gsm-fields.d.ts +23 -0
  37. package/dist/backend/nm-gsm-fields.js +107 -0
  38. package/dist/backend/nmcli-nm-port.d.ts +28 -0
  39. package/dist/backend/nmcli-nm-port.js +173 -0
  40. package/dist/backend/nmcli-runner.d.ts +24 -0
  41. package/dist/backend/nmcli-runner.js +35 -0
  42. package/dist/backend/observer.d.ts +37 -0
  43. package/dist/backend/observer.js +219 -0
  44. package/dist/backend/power-contract.d.ts +49 -0
  45. package/dist/backend/power-contract.js +34 -0
  46. package/dist/backend/recovery-attribution.d.ts +32 -0
  47. package/dist/backend/recovery-attribution.js +57 -0
  48. package/dist/backend/recovery-budget.d.ts +45 -0
  49. package/dist/backend/recovery-budget.js +44 -0
  50. package/dist/backend/recovery-ladder.d.ts +94 -0
  51. package/dist/backend/recovery-ladder.js +116 -0
  52. package/dist/backend/router-ethernet.d.ts +19 -0
  53. package/dist/backend/router-ethernet.js +66 -0
  54. package/dist/backend/row-store.d.ts +13 -0
  55. package/dist/backend/row-store.js +82 -0
  56. package/dist/backend/signal-setup.d.ts +30 -0
  57. package/dist/backend/signal-setup.js +92 -0
  58. package/dist/backend/sim-unlock.d.ts +13 -0
  59. package/dist/backend/sim-unlock.js +153 -0
  60. package/dist/backend/transition-preconditions.d.ts +76 -0
  61. package/dist/backend/transition-preconditions.js +64 -0
  62. package/dist/backend/usage/accounting.d.ts +39 -0
  63. package/dist/backend/usage/accounting.js +73 -0
  64. package/dist/backend/usage/billing-cycle.d.ts +11 -0
  65. package/dist/backend/usage/billing-cycle.js +39 -0
  66. package/dist/backend/usage/boot-id.d.ts +6 -0
  67. package/{src/backend/usage/boot-id.ts → dist/backend/usage/boot-id.js} +7 -7
  68. package/dist/backend/usage/index.d.ts +8 -0
  69. package/dist/backend/usage/index.js +11 -0
  70. package/dist/backend/usage/policy-store.d.ts +50 -0
  71. package/dist/backend/usage/policy-store.js +161 -0
  72. package/dist/backend/usage/policy-write.d.ts +65 -0
  73. package/dist/backend/usage/policy-write.js +112 -0
  74. package/dist/backend/usage/proc-net-dev.d.ts +18 -0
  75. package/{src/backend/usage/proc-net-dev.ts → dist/backend/usage/proc-net-dev.js} +39 -47
  76. package/dist/backend/usage/sampler.d.ts +75 -0
  77. package/dist/backend/usage/sampler.js +211 -0
  78. package/dist/backend/usage/store.d.ts +38 -0
  79. package/dist/backend/usage/store.js +126 -0
  80. package/dist/backend/usb-device-snapshot.d.ts +31 -0
  81. package/dist/backend/usb-device-snapshot.js +1 -0
  82. package/dist/backend/usb-enumerator.d.ts +21 -0
  83. package/dist/backend/usb-enumerator.js +153 -0
  84. package/dist/backend/usb-mode-transition.d.ts +29 -0
  85. package/dist/backend/usb-mode-transition.js +196 -0
  86. package/dist/band/band-names.d.ts +42 -0
  87. package/dist/band/band-names.js +150 -0
  88. package/dist/band/certification.d.ts +84 -0
  89. package/dist/band/certification.js +127 -0
  90. package/dist/band/certified-bands.json +4 -0
  91. package/dist/band/index.d.ts +2 -0
  92. package/dist/band/index.js +8 -0
  93. package/dist/capability/detect.d.ts +52 -0
  94. package/dist/capability/detect.js +86 -0
  95. package/dist/capability/five-g-preference.d.ts +104 -0
  96. package/dist/capability/five-g-preference.js +171 -0
  97. package/dist/capability/index.d.ts +3 -0
  98. package/dist/capability/index.js +10 -0
  99. package/dist/capability/support-claim.d.ts +39 -0
  100. package/dist/capability/support-claim.js +81 -0
  101. package/dist/domain/brand.d.ts +10 -0
  102. package/dist/domain/brand.js +21 -0
  103. package/dist/domain/errors.d.ts +32 -0
  104. package/dist/domain/errors.js +48 -0
  105. package/dist/domain/generation.d.ts +8 -0
  106. package/dist/domain/generation.js +12 -0
  107. package/dist/domain/guards.d.ts +6 -0
  108. package/dist/domain/guards.js +127 -0
  109. package/dist/domain/identity.d.ts +109 -0
  110. package/dist/domain/identity.js +86 -0
  111. package/dist/domain/index.d.ts +14 -0
  112. package/dist/domain/index.js +18 -0
  113. package/dist/domain/mm-enums.d.ts +12 -0
  114. package/dist/domain/mm-enums.js +139 -0
  115. package/dist/domain/modem-presentation.d.ts +10 -0
  116. package/dist/domain/modem-presentation.js +39 -0
  117. package/dist/domain/observation.d.ts +39 -0
  118. package/dist/domain/observation.js +4 -0
  119. package/dist/domain/operation.d.ts +118 -0
  120. package/dist/domain/operation.js +85 -0
  121. package/dist/domain/physical-identity.d.ts +43 -0
  122. package/dist/domain/physical-identity.js +113 -0
  123. package/{src/domain/policy.ts → dist/domain/policy.d.ts} +34 -69
  124. package/dist/domain/policy.js +38 -0
  125. package/dist/domain/shadow-divergence.d.ts +27 -0
  126. package/dist/domain/shadow-divergence.js +70 -0
  127. package/dist/domain/snapshot.d.ts +53 -0
  128. package/dist/domain/snapshot.js +75 -0
  129. package/{src/domain/state.ts → dist/domain/state.d.ts} +23 -122
  130. package/dist/domain/state.js +38 -0
  131. package/dist/fcc/coverage.d.ts +63 -0
  132. package/dist/fcc/coverage.js +102 -0
  133. package/dist/fcc/index.d.ts +3 -0
  134. package/dist/fcc/index.js +12 -0
  135. package/dist/fcc/policy-store.d.ts +40 -0
  136. package/dist/fcc/policy-store.js +146 -0
  137. package/dist/fcc/policy-write.d.ts +32 -0
  138. package/dist/fcc/policy-write.js +37 -0
  139. package/dist/hardware/hilink-protocol.d.ts +39 -0
  140. package/dist/hardware/hilink-protocol.js +58 -0
  141. package/dist/hardware/index.d.ts +3 -0
  142. package/dist/hardware/index.js +15 -0
  143. package/dist/hardware/router-parsers.d.ts +89 -0
  144. package/dist/hardware/router-parsers.js +234 -0
  145. package/dist/index.d.ts +19 -0
  146. package/dist/index.js +26 -0
  147. package/dist/journal/codec.d.ts +44 -0
  148. package/dist/journal/codec.js +198 -0
  149. package/dist/journal/engine.d.ts +28 -0
  150. package/dist/journal/engine.js +68 -0
  151. package/dist/journal/entry.d.ts +74 -0
  152. package/dist/journal/entry.js +56 -0
  153. package/dist/journal/index.d.ts +6 -0
  154. package/dist/journal/index.js +6 -0
  155. package/dist/journal/legacy-ceraui.d.ts +73 -0
  156. package/dist/journal/legacy-ceraui.js +227 -0
  157. package/dist/journal/recovery.d.ts +58 -0
  158. package/dist/journal/recovery.js +117 -0
  159. package/dist/journal/store.d.ts +55 -0
  160. package/dist/journal/store.js +150 -0
  161. package/dist/location/fix-state.d.ts +53 -0
  162. package/dist/location/fix-state.js +75 -0
  163. package/dist/location/index.d.ts +2 -0
  164. package/dist/location/index.js +8 -0
  165. package/dist/location/nmea.d.ts +10 -0
  166. package/dist/location/nmea.js +89 -0
  167. package/dist/observations/envelope.d.ts +63 -0
  168. package/dist/observations/envelope.js +77 -0
  169. package/dist/observations/freshness.d.ts +28 -0
  170. package/dist/observations/freshness.js +76 -0
  171. package/dist/observations/index.d.ts +13 -0
  172. package/dist/observations/index.js +24 -0
  173. package/dist/observations/metric.d.ts +47 -0
  174. package/dist/observations/metric.js +73 -0
  175. package/dist/observations/model.d.ts +80 -0
  176. package/dist/observations/model.js +11 -0
  177. package/dist/observations/provenance.d.ts +94 -0
  178. package/dist/observations/provenance.js +67 -0
  179. package/dist/observations/raw.d.ts +42 -0
  180. package/dist/observations/raw.js +146 -0
  181. package/dist/observations/reading.d.ts +51 -0
  182. package/dist/observations/reading.js +65 -0
  183. package/dist/observations/sources/hilink.d.ts +10 -0
  184. package/dist/observations/sources/hilink.js +84 -0
  185. package/dist/observations/sources/modemmanager.d.ts +18 -0
  186. package/dist/observations/sources/modemmanager.js +239 -0
  187. package/dist/observations/sources/router-shared.d.ts +29 -0
  188. package/dist/observations/sources/router-shared.js +68 -0
  189. package/dist/observations/sources/ufi.d.ts +10 -0
  190. package/dist/observations/sources/ufi.js +111 -0
  191. package/dist/observations/sources/zte.d.ts +7 -0
  192. package/dist/observations/sources/zte.js +71 -0
  193. package/dist/observations/state-separation.d.ts +64 -0
  194. package/dist/observations/state-separation.js +52 -0
  195. package/dist/operations/contracts.d.ts +72 -0
  196. package/dist/operations/contracts.js +1 -0
  197. package/dist/operations/index.d.ts +1 -0
  198. package/dist/operations/index.js +1 -0
  199. package/dist/operations/operation-engine.d.ts +16 -0
  200. package/dist/operations/operation-engine.js +194 -0
  201. package/dist/ports/index.d.ts +12 -0
  202. package/{src/ports/index.ts → dist/ports/index.js} +12 -8
  203. package/dist/ports/location.d.ts +87 -0
  204. package/dist/ports/location.js +36 -0
  205. package/dist/ports/modem-manager.d.ts +89 -0
  206. package/dist/ports/modem-manager.js +9 -0
  207. package/dist/ports/mutation-admission.d.ts +27 -0
  208. package/dist/ports/mutation-admission.js +9 -0
  209. package/dist/ports/network-manager.d.ts +68 -0
  210. package/dist/ports/network-manager.js +13 -0
  211. package/{src/ports/observation.ts → dist/ports/observation.d.ts} +16 -27
  212. package/dist/ports/observation.js +7 -0
  213. package/dist/ports/ops.d.ts +44 -0
  214. package/dist/ports/ops.js +16 -0
  215. package/{src/ports/receipts.ts → dist/ports/receipts.d.ts} +5 -27
  216. package/dist/ports/receipts.js +9 -0
  217. package/dist/ports/reconcile.d.ts +33 -0
  218. package/dist/ports/reconcile.js +200 -0
  219. package/dist/ports/resource-ownership.d.ts +29 -0
  220. package/dist/ports/resource-ownership.js +1 -0
  221. package/dist/ports/router.d.ts +19 -0
  222. package/dist/ports/router.js +7 -0
  223. package/dist/ports/sms.d.ts +64 -0
  224. package/dist/ports/sms.js +24 -0
  225. package/dist/ports/uhubctl.d.ts +6 -0
  226. package/dist/ports/uhubctl.js +1 -0
  227. package/dist/providers/contracts.d.ts +124 -0
  228. package/dist/providers/contracts.js +10 -0
  229. package/dist/providers/huawei-hilink/index.d.ts +2 -0
  230. package/dist/providers/huawei-hilink/index.js +2 -0
  231. package/dist/providers/huawei-hilink/operations.d.ts +20 -0
  232. package/dist/providers/huawei-hilink/operations.js +56 -0
  233. package/dist/providers/huawei-hilink/provider.d.ts +52 -0
  234. package/dist/providers/huawei-hilink/provider.js +76 -0
  235. package/dist/providers/huawei-hilink/runtime.d.ts +22 -0
  236. package/dist/providers/huawei-hilink/runtime.js +171 -0
  237. package/dist/providers/huawei-hilink/session.d.ts +28 -0
  238. package/dist/providers/huawei-hilink/session.js +120 -0
  239. package/dist/providers/huawei-hilink/transport.d.ts +19 -0
  240. package/dist/providers/huawei-hilink/transport.js +1 -0
  241. package/dist/providers/index.d.ts +8 -0
  242. package/dist/providers/index.js +8 -0
  243. package/dist/providers/matcher.d.ts +3 -0
  244. package/dist/providers/matcher.js +205 -0
  245. package/dist/providers/modem-manager/errors.d.ts +7 -0
  246. package/dist/providers/modem-manager/errors.js +37 -0
  247. package/dist/providers/modem-manager/generic-operations.d.ts +8 -0
  248. package/dist/providers/modem-manager/generic-operations.js +207 -0
  249. package/dist/providers/modem-manager/index.d.ts +3 -0
  250. package/dist/providers/modem-manager/index.js +3 -0
  251. package/dist/providers/modem-manager/module-operations.d.ts +21 -0
  252. package/dist/providers/modem-manager/module-operations.js +118 -0
  253. package/dist/providers/modem-manager/provider.d.ts +39 -0
  254. package/dist/providers/modem-manager/provider.js +152 -0
  255. package/dist/providers/modem-manager/snapshot.d.ts +5 -0
  256. package/dist/providers/modem-manager/snapshot.js +204 -0
  257. package/dist/providers/modem-manager/types.d.ts +135 -0
  258. package/dist/providers/modem-manager/types.js +1 -0
  259. package/dist/providers/network-manager/adapter.d.ts +71 -0
  260. package/dist/providers/network-manager/adapter.js +348 -0
  261. package/dist/providers/network-manager/index.d.ts +2 -0
  262. package/dist/providers/network-manager/index.js +2 -0
  263. package/dist/providers/network-manager/types.d.ts +163 -0
  264. package/dist/providers/network-manager/types.js +77 -0
  265. package/dist/providers/registry.d.ts +13 -0
  266. package/dist/providers/registry.js +33 -0
  267. package/dist/providers/ufi-himi/index.d.ts +6 -0
  268. package/dist/providers/ufi-himi/index.js +6 -0
  269. package/dist/providers/ufi-himi/operations.d.ts +41 -0
  270. package/dist/providers/ufi-himi/operations.js +66 -0
  271. package/dist/providers/ufi-himi/prohibitions.d.ts +62 -0
  272. package/dist/providers/ufi-himi/prohibitions.js +88 -0
  273. package/dist/providers/ufi-himi/provider.d.ts +41 -0
  274. package/dist/providers/ufi-himi/provider.js +204 -0
  275. package/dist/providers/ufi-himi/qualcomm-evidence.d.ts +32 -0
  276. package/dist/providers/ufi-himi/qualcomm-evidence.js +51 -0
  277. package/dist/providers/ufi-himi/session.d.ts +46 -0
  278. package/dist/providers/ufi-himi/session.js +92 -0
  279. package/dist/providers/ufi-himi/transport.d.ts +29 -0
  280. package/dist/providers/ufi-himi/transport.js +25 -0
  281. package/dist/providers/zte-goform/index.d.ts +2 -0
  282. package/dist/providers/zte-goform/index.js +2 -0
  283. package/dist/providers/zte-goform/provider.d.ts +51 -0
  284. package/dist/providers/zte-goform/provider.js +101 -0
  285. package/dist/providers/zte-goform/session.d.ts +17 -0
  286. package/dist/providers/zte-goform/session.js +133 -0
  287. package/dist/providers/zte-goform/transport.d.ts +16 -0
  288. package/dist/providers/zte-goform/transport.js +1 -0
  289. package/dist/radio/band-truth.d.ts +50 -0
  290. package/dist/radio/band-truth.js +92 -0
  291. package/dist/radio/index.d.ts +3 -0
  292. package/dist/radio/index.js +10 -0
  293. package/dist/radio/mode-combinations.d.ts +78 -0
  294. package/dist/radio/mode-combinations.js +198 -0
  295. package/dist/radio/mode-truth.d.ts +67 -0
  296. package/dist/radio/mode-truth.js +112 -0
  297. package/dist/redact.d.ts +15 -0
  298. package/dist/redact.js +189 -0
  299. package/dist/safety/composition-root.d.ts +28 -0
  300. package/dist/safety/composition-root.js +65 -0
  301. package/dist/safety/flock-resource-ownership.d.ts +11 -0
  302. package/dist/safety/flock-resource-ownership.js +151 -0
  303. package/dist/safety/index.d.ts +2 -0
  304. package/dist/safety/index.js +2 -0
  305. package/dist/sms/dbus-messaging.d.ts +17 -0
  306. package/dist/sms/dbus-messaging.js +185 -0
  307. package/dist/sms/inbox-store.d.ts +10 -0
  308. package/dist/sms/inbox-store.js +82 -0
  309. package/dist/sms/index.d.ts +4 -0
  310. package/dist/sms/index.js +10 -0
  311. package/dist/sms/mmcli-parse.d.ts +54 -0
  312. package/dist/sms/mmcli-parse.js +224 -0
  313. package/dist/sms/normalize.d.ts +42 -0
  314. package/dist/sms/normalize.js +95 -0
  315. package/dist/testing/domain-fakes.d.ts +58 -0
  316. package/dist/testing/domain-fakes.js +98 -0
  317. package/dist/testing/index.d.ts +2 -0
  318. package/dist/testing/index.js +17 -0
  319. package/dist/testing/provider-fakes.d.ts +45 -0
  320. package/dist/testing/provider-fakes.js +64 -0
  321. package/dist/transport/calls.d.ts +9 -0
  322. package/dist/transport/calls.js +88 -0
  323. package/dist/transport/codec.d.ts +3 -0
  324. package/dist/transport/codec.js +207 -0
  325. package/dist/transport/dbus-native.d.ts +57 -0
  326. package/dist/transport/dbus-native.js +17 -0
  327. package/dist/transport/errors.d.ts +21 -0
  328. package/{src/transport/errors.ts → dist/transport/errors.js} +34 -46
  329. package/dist/transport/index.d.ts +4 -0
  330. package/dist/transport/index.js +9 -0
  331. package/dist/transport/signals.d.ts +15 -0
  332. package/dist/transport/signals.js +123 -0
  333. package/dist/transport/signature.d.ts +7 -0
  334. package/dist/transport/signature.js +94 -0
  335. package/dist/transport/transport.d.ts +2 -0
  336. package/dist/transport/transport.js +202 -0
  337. package/dist/transport/types.d.ts +61 -0
  338. package/dist/transport/types.js +19 -0
  339. package/dist/usb-mode/catalog-schema.d.ts +139 -0
  340. package/dist/usb-mode/catalog-schema.js +97 -0
  341. package/dist/usb-mode/catalog.d.ts +21 -0
  342. package/{src/usb-mode/catalog.ts → dist/usb-mode/catalog.js} +10 -32
  343. package/dist/usb-mode/certified-catalog.json +67 -0
  344. package/dist/usb-mode/index.d.ts +5 -0
  345. package/dist/usb-mode/index.js +15 -0
  346. package/dist/usb-mode/ingestion.d.ts +111 -0
  347. package/dist/usb-mode/ingestion.js +187 -0
  348. package/dist/usb-mode/promotion-review.d.ts +21 -0
  349. package/dist/usb-mode/promotion-review.js +87 -0
  350. package/dist/usb-mode/usb-devices-parse.d.ts +36 -0
  351. package/dist/usb-mode/usb-devices-parse.js +157 -0
  352. package/dist/ussd/calls.d.ts +32 -0
  353. package/dist/ussd/calls.js +96 -0
  354. package/dist/ussd/index.d.ts +5 -0
  355. package/dist/ussd/index.js +12 -0
  356. package/dist/ussd/mm-ussd.d.ts +37 -0
  357. package/dist/ussd/mm-ussd.js +205 -0
  358. package/dist/ussd/refusal.d.ts +53 -0
  359. package/dist/ussd/refusal.js +154 -0
  360. package/dist/ussd/registration.d.ts +20 -0
  361. package/dist/ussd/registration.js +101 -0
  362. package/dist/ussd/session.d.ts +84 -0
  363. package/dist/ussd/session.js +163 -0
  364. package/package.json +38 -4
  365. package/src/backend/at-lease.test.ts +0 -106
  366. package/src/backend/at-lease.ts +0 -158
  367. package/src/backend/cell-info.test.ts +0 -154
  368. package/src/backend/cell-info.ts +0 -160
  369. package/src/backend/device-classifier.test.ts +0 -168
  370. package/src/backend/device-classifier.ts +0 -248
  371. package/src/backend/enrichment.ts +0 -96
  372. package/src/backend/features.test.ts +0 -162
  373. package/src/backend/features.ts +0 -179
  374. package/src/backend/identity-ladder.test.ts +0 -117
  375. package/src/backend/identity-ladder.ts +0 -221
  376. package/src/backend/identity-registry.test.ts +0 -89
  377. package/src/backend/identity-registry.ts +0 -151
  378. package/src/backend/index.ts +0 -221
  379. package/src/backend/lifecycle-interlock.ts +0 -38
  380. package/src/backend/managed-objects.ts +0 -108
  381. package/src/backend/mapping.ts +0 -160
  382. package/src/backend/mm-backend.ts +0 -191
  383. package/src/backend/mm-mutations.ts +0 -228
  384. package/src/backend/modem-actor.test.ts +0 -95
  385. package/src/backend/modem-actor.ts +0 -112
  386. package/src/backend/nm-auto-apn.ts +0 -161
  387. package/src/backend/nm-gsm-fields.ts +0 -122
  388. package/src/backend/nmcli-nm-port.ts +0 -228
  389. package/src/backend/nmcli-runner.ts +0 -52
  390. package/src/backend/observer.ts +0 -297
  391. package/src/backend/power-contract.test.ts +0 -40
  392. package/src/backend/power-contract.ts +0 -83
  393. package/src/backend/recovery-attribution.test.ts +0 -102
  394. package/src/backend/recovery-attribution.ts +0 -86
  395. package/src/backend/recovery-budget.test.ts +0 -64
  396. package/src/backend/recovery-budget.ts +0 -84
  397. package/src/backend/recovery-ladder.test.ts +0 -257
  398. package/src/backend/recovery-ladder.ts +0 -249
  399. package/src/backend/router-ethernet.test.ts +0 -71
  400. package/src/backend/router-ethernet.ts +0 -90
  401. package/src/backend/row-store.ts +0 -105
  402. package/src/backend/signal-setup.ts +0 -112
  403. package/src/backend/sim-unlock.ts +0 -193
  404. package/src/backend/transition-preconditions.ts +0 -149
  405. package/src/backend/usage/accounting.test.ts +0 -147
  406. package/src/backend/usage/accounting.ts +0 -123
  407. package/src/backend/usage/billing-cycle.test.ts +0 -62
  408. package/src/backend/usage/billing-cycle.ts +0 -45
  409. package/src/backend/usage/index.ts +0 -37
  410. package/src/backend/usage/proc-net-dev.test.ts +0 -56
  411. package/src/backend/usage/sampler.test.ts +0 -219
  412. package/src/backend/usage/sampler.ts +0 -228
  413. package/src/backend/usage/store.test.ts +0 -148
  414. package/src/backend/usage/store.ts +0 -177
  415. package/src/backend/usb-enumerator.test.ts +0 -87
  416. package/src/backend/usb-enumerator.ts +0 -181
  417. package/src/backend/usb-mode-transition.test.ts +0 -323
  418. package/src/backend/usb-mode-transition.ts +0 -253
  419. package/src/domain/brand.ts +0 -29
  420. package/src/domain/errors.ts +0 -77
  421. package/src/domain/guards.test.ts +0 -218
  422. package/src/domain/guards.ts +0 -144
  423. package/src/domain/identity.test.ts +0 -83
  424. package/src/domain/identity.ts +0 -165
  425. package/src/domain/index.ts +0 -12
  426. package/src/domain/snapshot.test.ts +0 -266
  427. package/src/domain/snapshot.ts +0 -120
  428. package/src/index.test.ts +0 -6
  429. package/src/index.ts +0 -15
  430. package/src/ports/README.md +0 -61
  431. package/src/ports/forbidden-surface.test.ts +0 -241
  432. package/src/ports/modem-manager.ts +0 -72
  433. package/src/ports/network-manager.ts +0 -87
  434. package/src/ports/ops.ts +0 -60
  435. package/src/ports/ops.type-test.ts +0 -39
  436. package/src/ports/receipts.test.ts +0 -153
  437. package/src/ports/reconcile.test.ts +0 -152
  438. package/src/ports/reconcile.ts +0 -338
  439. package/src/ports/router.ts +0 -29
  440. package/src/redact.test.ts +0 -82
  441. package/src/redact.ts +0 -73
  442. package/src/transport/README.md +0 -65
  443. package/src/transport/calls.ts +0 -113
  444. package/src/transport/characterization.test.ts +0 -260
  445. package/src/transport/codec.test.ts +0 -118
  446. package/src/transport/codec.ts +0 -240
  447. package/src/transport/conformance-python.test.ts +0 -152
  448. package/src/transport/conformance-same-lib.test.ts +0 -115
  449. package/src/transport/dbus-native-lib.d.ts +0 -19
  450. package/src/transport/dbus-native.ts +0 -85
  451. package/src/transport/index.ts +0 -30
  452. package/src/transport/no-library-leak.test.ts +0 -61
  453. package/src/transport/reliability.test.ts +0 -173
  454. package/src/transport/signals.ts +0 -150
  455. package/src/transport/signature.ts +0 -110
  456. package/src/transport/test-support/fake-service.ts +0 -168
  457. package/src/transport/test-support/independent-producer.py +0 -110
  458. package/src/transport/test-support/private-bus.ts +0 -66
  459. package/src/transport/transport.ts +0 -250
  460. package/src/transport/types.ts +0 -118
  461. package/src/usb-mode/catalog-schema.test.ts +0 -181
  462. package/src/usb-mode/catalog-schema.ts +0 -113
  463. package/src/usb-mode/certified-catalog.json +0 -67
  464. package/src/usb-mode/index.ts +0 -27
@@ -0,0 +1,24 @@
1
+ // The SMS port — LIST / READ and Added/Deleted observation. NOTHING ELSE.
2
+ //
3
+ // READ-ONLY IS PERMANENT, NOT A PHASE LIMITATION. There is no verb here that
4
+ // composes, stores, sends, or deletes a message, and none may ever be added.
5
+ // Sending or deleting an SMS is billable and irreversible, and it turns a
6
+ // diagnostic read into real modem-control capability over the subscriber's
7
+ // account. CeraUI carries the same contract on its own side, enforced by a grep
8
+ // gate (`tests/modem-sms-readonly-gate.test.ts`); `sms/readonly-gate.test.ts`
9
+ // is this package's half. Neither may be weakened to land a write path — that
10
+ // is a new spec change with its own confirmation/interlock design.
11
+ //
12
+ // THE OBSERVATION MODEL IS "LIST ONCE, THEN FOLLOW THE SIGNALS". ModemManager's
13
+ // Messaging interface emits `Added` and `Deleted` for every inbox change, so a
14
+ // consumer lists once at start and folds events from then on. Re-listing on a
15
+ // poll tick is the anti-pattern this port exists to remove: it costs one method
16
+ // call per message per tick and still cannot report an arrival any sooner than
17
+ // the tick it lands on.
18
+ //
19
+ // CONTENT NEVER RIDES A DIAGNOSTIC. A message body routinely carries a one-time
20
+ // code and its originator identifies the subscriber, so nothing on this port
21
+ // puts either into a reason string, a receipt, or a log line — see
22
+ // `../redact.ts` for the key class and `../sms/mmcli-parse.ts` for the
23
+ // content-free parse errors.
24
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { PowerCapability, PowerCycleContext, PowerCycleResult } from '../backend/power-contract.js';
2
+ /** Consumer-supplied USB-hub actuator. This package intentionally ships no implementation. */
3
+ export interface UhubctlPort {
4
+ readonly capability: PowerCapability;
5
+ cycle(context: PowerCycleContext): Promise<PowerCycleResult>;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,124 @@
1
+ import type { DeviceGeneration, ObservationEnvelope, OperationDescriptor, OperationResult, PhysicalModemId } from '../domain/index.js';
2
+ export declare const PROVIDER_TRANSPORTS: readonly ["usb", "pci", "network", "modemmanager"];
3
+ export type ProviderTransport = (typeof PROVIDER_TRANSPORTS)[number];
4
+ export declare const PASSIVE_FACT_KINDS: readonly ["usb", "pci", "interface", "driver", "gateway", "model", "firmware"];
5
+ export type PassiveFactKind = (typeof PASSIVE_FACT_KINDS)[number];
6
+ export type EvidenceStrength = 'none' | 'weak' | 'moderate' | 'strong';
7
+ export type MatcherScore = 'unsupported' | 'maybe' | 'likely' | 'supported';
8
+ export type PassiveFact = {
9
+ readonly kind: PassiveFactKind;
10
+ readonly value: string;
11
+ };
12
+ export type ProviderMatchRequest = {
13
+ readonly physicalModemId: PhysicalModemId;
14
+ readonly generation: DeviceGeneration;
15
+ readonly transport: ProviderTransport;
16
+ readonly passiveFacts: readonly PassiveFact[];
17
+ readonly composition: string;
18
+ readonly firmware?: string;
19
+ };
20
+ export type ProviderExecutionContext = ProviderMatchRequest & {
21
+ readonly profile: string;
22
+ };
23
+ export type PassiveMatcher = {
24
+ readonly id: string;
25
+ readonly fact: PassiveFactKind;
26
+ readonly expected: readonly string[];
27
+ readonly profiles: readonly string[];
28
+ readonly strength: Exclude<EvidenceStrength, 'none'>;
29
+ readonly required: boolean;
30
+ };
31
+ export type FingerprintResult = {
32
+ readonly signal: 'match' | 'mismatch' | 'unknown';
33
+ readonly strength: Exclude<EvidenceStrength, 'none'>;
34
+ readonly profiles: readonly string[];
35
+ readonly detail: string;
36
+ };
37
+ export type UnauthenticatedProbe = {
38
+ readonly id: string;
39
+ readonly run: (context: ProviderMatchRequest) => Promise<FingerprintResult>;
40
+ };
41
+ export type CapabilityReader = {
42
+ readonly id: string;
43
+ readonly read: (context: ProviderExecutionContext) => Promise<Omit<FingerprintResult, 'profiles'>>;
44
+ };
45
+ export type AuthenticatedProfileResult = {
46
+ readonly status: 'matched';
47
+ readonly profile: string;
48
+ readonly detail: string;
49
+ } | {
50
+ readonly status: 'refused';
51
+ readonly detail: string;
52
+ } | {
53
+ readonly status: 'unavailable';
54
+ readonly detail: string;
55
+ };
56
+ /** One algorithm and one call per generation-scoped evaluation; cycling is unrepresentable. */
57
+ export type AuthenticatedProfile = {
58
+ readonly algorithm: string;
59
+ readonly attemptLimit: 1;
60
+ readonly authenticate: (context: ProviderMatchRequest, profileCandidates: readonly string[]) => Promise<AuthenticatedProfileResult>;
61
+ };
62
+ export type ProviderOperationsSurface = {
63
+ readonly access: 'read-only' | 'read-write';
64
+ };
65
+ export interface ProviderReadOperations<O> {
66
+ readonly descriptor: OperationDescriptor<never, O>;
67
+ readonly read: (context: ProviderExecutionContext) => Promise<OperationResult<O>>;
68
+ }
69
+ export interface ProviderWriteOperations<I, O> {
70
+ readonly descriptor: OperationDescriptor<I, O>;
71
+ readonly read: (context: ProviderExecutionContext) => Promise<OperationResult<O>>;
72
+ readonly write: (context: ProviderExecutionContext, input: I) => Promise<OperationResult<O>>;
73
+ }
74
+ export type ProviderContractFixture = {
75
+ readonly profile: string;
76
+ readonly request: Readonly<Record<string, unknown>>;
77
+ readonly response: Readonly<Record<string, unknown>>;
78
+ };
79
+ export interface ProviderDefinition<TObservation = unknown, TOperations extends ProviderOperationsSurface = ProviderOperationsSurface> {
80
+ readonly id: string;
81
+ readonly profileVersion: string;
82
+ readonly eligibleTransports: readonly ProviderTransport[];
83
+ readonly passiveMatchers: readonly PassiveMatcher[];
84
+ readonly unauthenticatedProbes: readonly UnauthenticatedProbe[];
85
+ readonly authenticatedProfile?: AuthenticatedProfile;
86
+ readonly capabilityReaders: readonly CapabilityReader[];
87
+ readonly observe: (context: ProviderExecutionContext) => Promise<readonly ObservationEnvelope<TObservation>[]>;
88
+ readonly operations: (profile: string) => TOperations;
89
+ readonly contractFixtures: readonly ProviderContractFixture[];
90
+ }
91
+ export type MatcherEvidence = {
92
+ readonly provider: string;
93
+ readonly profile: string | null;
94
+ readonly stage: 'transport-eligibility' | 'passive-facts' | 'unauthenticated-fingerprint' | 'authenticated-profile' | 'capability-read';
95
+ readonly source: string;
96
+ readonly signal: 'match' | 'mismatch' | 'unknown';
97
+ readonly strength: EvidenceStrength;
98
+ readonly detail: string;
99
+ };
100
+ type MatchResultBase = {
101
+ readonly score: MatcherScore;
102
+ readonly confidence: number;
103
+ readonly evidence: readonly MatcherEvidence[];
104
+ readonly conflicts: readonly MatcherEvidence[];
105
+ readonly generation: DeviceGeneration;
106
+ readonly physicalModemId: PhysicalModemId;
107
+ };
108
+ export type ProviderMatchResult = (MatchResultBase & {
109
+ readonly status: 'unsupported' | 'ambiguous';
110
+ readonly provider: null;
111
+ readonly profile: null;
112
+ readonly operations: null;
113
+ readonly writable: false;
114
+ }) | (MatchResultBase & {
115
+ readonly status: 'selected';
116
+ readonly provider: string;
117
+ readonly profile: string;
118
+ readonly operations: ProviderOperationsSurface;
119
+ readonly writable: boolean;
120
+ });
121
+ export interface ProviderMatcher {
122
+ match(request: ProviderMatchRequest): Promise<ProviderMatchResult>;
123
+ }
124
+ export {};
@@ -0,0 +1,10 @@
1
+ export const PROVIDER_TRANSPORTS = ['usb', 'pci', 'network', 'modemmanager'];
2
+ export const PASSIVE_FACT_KINDS = [
3
+ 'usb',
4
+ 'pci',
5
+ 'interface',
6
+ 'driver',
7
+ 'gateway',
8
+ 'model',
9
+ 'firmware',
10
+ ];
@@ -0,0 +1,2 @@
1
+ export * from './provider.js';
2
+ export * from './transport.js';
@@ -0,0 +1,2 @@
1
+ export * from './provider.js';
2
+ export * from './transport.js';
@@ -0,0 +1,20 @@
1
+ import type { DeviceGeneration, OperationDescriptor, OperationResult } from '../../domain/index.js';
2
+ import type { ProviderExecutionContext } from '../contracts.js';
3
+ import { type HilinkProfile } from './provider.js';
4
+ export type ReadValue = Readonly<Record<string, unknown>>;
5
+ export type ReadOperation = {
6
+ readonly descriptor: OperationDescriptor<never, ReadValue>;
7
+ readonly read: (context: ProviderExecutionContext) => Promise<OperationResult<ReadValue>>;
8
+ };
9
+ export type WriteOperation = {
10
+ readonly descriptor: OperationDescriptor<string | boolean, ReadValue>;
11
+ readonly read: ReadOperation['read'];
12
+ readonly write: (context: ProviderExecutionContext, value: string | boolean) => Promise<OperationResult<ReadValue>>;
13
+ };
14
+ export declare function applied(generation: DeviceGeneration, value: ReadValue): OperationResult<ReadValue>;
15
+ export declare function refused(generation: DeviceGeneration, reason: string): OperationResult<ReadValue>;
16
+ export declare function operationDescriptor<I>(id: string, write: boolean, profile: HilinkProfile): OperationDescriptor<I, ReadValue>;
17
+ export declare function requestSucceeded(status: number, body: string): boolean;
18
+ export declare function capabilityPath(kind: 'status' | 'signal' | 'mode' | 'data'): string;
19
+ export declare function writeDocument(kind: 'mode' | 'data', value: string | boolean): string;
20
+ export declare function readbackMatches(kind: 'mode' | 'data', body: string, value: string | boolean): boolean;
@@ -0,0 +1,56 @@
1
+ import { defineOperationDescriptor } from '../../domain/index.js';
2
+ import { parseHilinkDataCapability, parseHilinkXmlValue } from '../../hardware/router-parsers.js';
3
+ import { HILINK_PATHS } from './provider.js';
4
+ export function applied(generation, value) {
5
+ return { status: 'applied', value, generation, requiresReconciliation: false };
6
+ }
7
+ export function refused(generation, reason) {
8
+ return { status: 'refused', reason, generation, requiresReconciliation: false };
9
+ }
10
+ export function operationDescriptor(id, write, profile) {
11
+ return defineOperationDescriptor({
12
+ id,
13
+ support: {
14
+ read: { supported: true },
15
+ write: write ? { supported: true } : { supported: false, reason: 'read-only' },
16
+ },
17
+ authority: 'provider',
18
+ provider: 'huawei-hilink',
19
+ constraints: { kind: 'unconstrained' },
20
+ livePreconditions: ['fresh-session', 'capability-evidence'],
21
+ availability: { state: 'available' },
22
+ mutationImpact: write ? 'write' : 'read',
23
+ retryClass: 'never',
24
+ readback: write
25
+ ? { required: true, reason: 'fresh-readback', matches: () => true }
26
+ : { required: false },
27
+ rollback: { required: false },
28
+ journal: { required: false },
29
+ admission: { required: true, reason: 'router-session' },
30
+ evidence: { profiles: [profile.id], firmware: [profile.firmware] },
31
+ confidence: 'high',
32
+ });
33
+ }
34
+ export function requestSucceeded(status, body) {
35
+ return status >= 200 && status < 300 && /<response>\s*OK\s*<\/response>/i.test(body);
36
+ }
37
+ export function capabilityPath(kind) {
38
+ return kind === 'status'
39
+ ? HILINK_PATHS.status
40
+ : kind === 'signal'
41
+ ? HILINK_PATHS.signal
42
+ : kind === 'mode'
43
+ ? HILINK_PATHS.modeList
44
+ : HILINK_PATHS.data;
45
+ }
46
+ export function writeDocument(kind, value) {
47
+ return kind === 'mode'
48
+ ? `<?xml version="1.0" encoding="UTF-8"?><request><NetworkMode>${String(value)}</NetworkMode></request>`
49
+ : `<?xml version="1.0" encoding="UTF-8"?><request><dataswitch>${value ? 1 : 0}</dataswitch></request>`;
50
+ }
51
+ export function readbackMatches(kind, body, value) {
52
+ if (kind === 'mode')
53
+ return parseHilinkXmlValue(body, 'NetworkMode') === String(value);
54
+ const parsed = parseHilinkDataCapability(body);
55
+ return parsed.state === 'reported' && parsed.enabled === Boolean(value);
56
+ }
@@ -0,0 +1,52 @@
1
+ import type { NormalizedModemObservation } from '../../observations/index.js';
2
+ import type { ResourceOwnershipPort } from '../../ports/resource-ownership.js';
3
+ import type { ProviderDefinition, ProviderOperationsSurface } from '../contracts.js';
4
+ import { HuaweiProvider, type ReadOperation, type WriteOperation } from './runtime.js';
5
+ import type { HilinkTransport } from './transport.js';
6
+ export declare const HILINK_PATHS: {
7
+ readonly session: "/api/webserver/SesTokInfo";
8
+ readonly loginState: "/api/user/state-login";
9
+ readonly login: "/api/user/login";
10
+ readonly status: "/api/monitoring/status";
11
+ readonly signal: "/api/device/signal";
12
+ readonly modeList: "/api/net/net-mode-list";
13
+ readonly mode: "/api/net/net-mode";
14
+ readonly data: "/api/dialup/mobile-dataswitch";
15
+ };
16
+ export type HilinkProfile = {
17
+ readonly id: string;
18
+ readonly firmware: string;
19
+ readonly passwordType: 3 | 4;
20
+ };
21
+ export declare const HILINK_PROFILES: readonly [{
22
+ readonly id: "e3372h-22.200-password-type-3";
23
+ readonly firmware: "22.200.05.00.1080";
24
+ readonly passwordType: 3;
25
+ }, {
26
+ readonly id: "e3372h-22.333-password-type-4";
27
+ readonly firmware: "22.333.01.00.00";
28
+ readonly passwordType: 4;
29
+ }];
30
+ export type HilinkCredentials = {
31
+ readonly username: string;
32
+ readonly password: string;
33
+ };
34
+ export type HilinkOptions = {
35
+ readonly interfaceName: string;
36
+ readonly adminUrl: string;
37
+ readonly transport: HilinkTransport;
38
+ readonly ownership: ResourceOwnershipPort;
39
+ readonly credentials: HilinkCredentials;
40
+ readonly now?: () => number;
41
+ };
42
+ export type HilinkObservation = NormalizedModemObservation;
43
+ export type HuaweiOperations = ProviderOperationsSurface & {
44
+ readonly status: ReadOperation;
45
+ readonly signal: ReadOperation;
46
+ readonly mode: WriteOperation;
47
+ readonly data: WriteOperation;
48
+ };
49
+ export declare function hilinkProfile(profileId: string): HilinkProfile | undefined;
50
+ export declare function createHuaweiHiLinkProvider(options: HilinkOptions): HuaweiProvider;
51
+ export declare function createHuaweiHiLinkDefinition(options: HilinkOptions): ProviderDefinition<HilinkObservation, HuaweiOperations>;
52
+ export { HuaweiProvider as HuaweiHiLinkProvider };
@@ -0,0 +1,76 @@
1
+ import { HuaweiProvider } from './runtime.js';
2
+ export const HILINK_PATHS = {
3
+ session: '/api/webserver/SesTokInfo',
4
+ loginState: '/api/user/state-login',
5
+ login: '/api/user/login',
6
+ status: '/api/monitoring/status',
7
+ signal: '/api/device/signal',
8
+ modeList: '/api/net/net-mode-list',
9
+ mode: '/api/net/net-mode',
10
+ data: '/api/dialup/mobile-dataswitch',
11
+ };
12
+ export const HILINK_PROFILES = [
13
+ {
14
+ id: 'e3372h-22.200-password-type-3',
15
+ firmware: '22.200.05.00.1080',
16
+ passwordType: 3,
17
+ },
18
+ {
19
+ id: 'e3372h-22.333-password-type-4',
20
+ firmware: '22.333.01.00.00',
21
+ passwordType: 4,
22
+ },
23
+ ];
24
+ export function hilinkProfile(profileId) {
25
+ return HILINK_PROFILES.find((profile) => profile.id === profileId);
26
+ }
27
+ export function createHuaweiHiLinkProvider(options) {
28
+ return new HuaweiProvider(options);
29
+ }
30
+ export function createHuaweiHiLinkDefinition(options) {
31
+ const runtime = createHuaweiHiLinkProvider(options);
32
+ return {
33
+ id: 'huawei-hilink',
34
+ profileVersion: '1',
35
+ eligibleTransports: ['network'],
36
+ passiveMatchers: HILINK_PROFILES.map((profile) => ({
37
+ id: `firmware-${profile.firmware}`,
38
+ fact: 'firmware',
39
+ expected: [profile.firmware],
40
+ profiles: [profile.id],
41
+ strength: 'strong',
42
+ required: true,
43
+ })),
44
+ unauthenticatedProbes: [
45
+ {
46
+ id: 'hilink-session-shape',
47
+ run: (request) => runtime.sessionProbe(request),
48
+ },
49
+ ],
50
+ authenticatedProfile: {
51
+ algorithm: 'firmware-selected-hilink-password',
52
+ attemptLimit: 1,
53
+ authenticate: (request, candidates) => runtime.authenticateProfile(request, candidates),
54
+ },
55
+ capabilityReaders: [
56
+ runtime.capability('status'),
57
+ runtime.capability('signal'),
58
+ runtime.capability('mode'),
59
+ runtime.capability('data'),
60
+ ],
61
+ observe: (context) => runtime.observe(context),
62
+ operations: (profile) => runtime.operations(profile),
63
+ contractFixtures: HILINK_PROFILES.map((profile) => ({
64
+ profile: profile.id,
65
+ request: {
66
+ method: 'POST',
67
+ path: HILINK_PATHS.login,
68
+ passwordType: profile.passwordType,
69
+ interfaceBound: true,
70
+ redirects: 'disabled',
71
+ },
72
+ response: { status: 'matched', sessionMaterial: '[redacted]' },
73
+ })),
74
+ };
75
+ }
76
+ export { HuaweiProvider as HuaweiHiLinkProvider };
@@ -0,0 +1,22 @@
1
+ import type { ObservationEnvelope } from '../../domain/index.js';
2
+ import type { AuthenticatedProfileResult, CapabilityReader, ProviderExecutionContext, ProviderMatchRequest } from '../contracts.js';
3
+ import { type HilinkObservation, type HuaweiOperations } from './provider.js';
4
+ import { HilinkSessionRuntime } from './session.js';
5
+ export type { ReadOperation, WriteOperation } from './operations.js';
6
+ export declare class HuaweiProvider extends HilinkSessionRuntime {
7
+ sessionProbe(request: ProviderMatchRequest): Promise<{
8
+ signal: "unknown" | "match";
9
+ strength: "strong";
10
+ profiles: ("e3372h-22.200-password-type-3" | "e3372h-22.333-password-type-4")[];
11
+ detail: string;
12
+ }>;
13
+ authenticateProfile(request: ProviderMatchRequest, candidates: readonly string[]): Promise<AuthenticatedProfileResult>;
14
+ observe(context: ProviderExecutionContext): Promise<readonly ObservationEnvelope<HilinkObservation>[]>;
15
+ capability(kind: 'status' | 'signal' | 'mode' | 'data'): CapabilityReader;
16
+ operations(profileId: string): HuaweiOperations;
17
+ private sessionFor;
18
+ private capabilitySupported;
19
+ private readOperation;
20
+ private writeOperation;
21
+ private write;
22
+ }
@@ -0,0 +1,171 @@
1
+ import { parseHilinkCapabilities, parseHilinkDataCapability, parseHilinkSession, parseHilinkXmlValue, } from '../../hardware/router-parsers.js';
2
+ import { normalizeHilinkObservation } from '../../observations/sources/hilink.js';
3
+ import { applied, capabilityPath, operationDescriptor, readbackMatches, refused, requestSucceeded, writeDocument, } from './operations.js';
4
+ import { HILINK_PATHS, HILINK_PROFILES, hilinkProfile, } from './provider.js';
5
+ import { HilinkSessionRuntime } from './session.js';
6
+ export class HuaweiProvider extends HilinkSessionRuntime {
7
+ async sessionProbe(request) {
8
+ const profile = HILINK_PROFILES.find((candidate) => candidate.firmware === request.firmware);
9
+ const response = await this.request('GET', HILINK_PATHS.session);
10
+ const matches = response.status === 200 && parseHilinkSession(response.body) !== undefined;
11
+ return {
12
+ signal: matches && profile !== undefined ? 'match' : 'unknown',
13
+ strength: 'strong',
14
+ profiles: profile === undefined ? [] : [profile.id],
15
+ detail: matches ? 'session-token-evidence' : 'session-token-not-proven',
16
+ };
17
+ }
18
+ async authenticateProfile(request, candidates) {
19
+ const candidate = candidates.length === 1 ? hilinkProfile(candidates[0] ?? '') : undefined;
20
+ if (candidate === undefined)
21
+ return { status: 'refused', detail: 'profile-mismatch' };
22
+ const result = await this.authenticate(request, candidate, true);
23
+ if (result.status === 'ready')
24
+ return { status: 'matched', profile: candidate.id, detail: 'login-ok' };
25
+ return {
26
+ status: result.reason === 'unreachable' ? 'unavailable' : 'refused',
27
+ detail: result.reason,
28
+ };
29
+ }
30
+ async observe(context) {
31
+ const ready = await this.sessionFor(context);
32
+ if (ready === undefined)
33
+ return [];
34
+ const [status, signal, modeList, mode] = await Promise.all([
35
+ this.getResponse(HILINK_PATHS.status, ready),
36
+ this.getResponse(HILINK_PATHS.signal, ready),
37
+ this.getResponse(HILINK_PATHS.modeList, ready),
38
+ this.getResponse(HILINK_PATHS.mode, ready),
39
+ ]);
40
+ const input = {
41
+ status: status.body,
42
+ signal: signal.body,
43
+ netModeList: modeList.body,
44
+ netMode: mode.body,
45
+ };
46
+ return [
47
+ normalizeHilinkObservation(input, {
48
+ stableKey: `modem:${this.options.interfaceName}`,
49
+ generation: context.generation,
50
+ sourceEpoch: 1,
51
+ observedAt: (this.options.now?.() ?? Date.now()),
52
+ }),
53
+ ];
54
+ }
55
+ capability(kind) {
56
+ return {
57
+ id: `hilink-${kind}`,
58
+ read: async (context) => {
59
+ const session = await this.sessionFor(context);
60
+ if (session === undefined)
61
+ return { signal: 'unknown', strength: 'strong', detail: 'session-unavailable' };
62
+ const path = capabilityPath(kind);
63
+ const response = await this.getResponse(path, session);
64
+ const supported = this.capabilitySupported(kind, response.body) && !this.authExpired(response);
65
+ return {
66
+ signal: supported ? 'match' : 'mismatch',
67
+ strength: 'strong',
68
+ detail: supported ? 'capability-reported' : 'capability-refused',
69
+ };
70
+ },
71
+ };
72
+ }
73
+ operations(profileId) {
74
+ const profile = hilinkProfile(profileId);
75
+ if (profile === undefined)
76
+ return unsupportedOperations(profileId);
77
+ return {
78
+ access: 'read-write',
79
+ status: this.readOperation('status', HILINK_PATHS.status, profile),
80
+ signal: this.readOperation('signal', HILINK_PATHS.signal, profile),
81
+ mode: this.writeOperation('mode', HILINK_PATHS.mode, profile),
82
+ data: this.writeOperation('data', HILINK_PATHS.data, profile),
83
+ };
84
+ }
85
+ async sessionFor(context) {
86
+ const cached = this.cachedSession(context);
87
+ if (cached !== undefined)
88
+ return cached;
89
+ const profile = hilinkProfile(context.profile);
90
+ if (profile === undefined)
91
+ return undefined;
92
+ const result = await this.authenticate(context, profile, true);
93
+ return result.status === 'ready' ? result.session : undefined;
94
+ }
95
+ capabilitySupported(kind, body) {
96
+ if (kind === 'mode')
97
+ return parseHilinkCapabilities({ netModeList: body }).net_mode.state === 'reported';
98
+ if (kind === 'data')
99
+ return parseHilinkDataCapability(body).state === 'reported';
100
+ return parseHilinkXmlValue(body, 'code') === undefined && /<response>/i.test(body);
101
+ }
102
+ readOperation(id, path, profile) {
103
+ return {
104
+ descriptor: operationDescriptor(id, false, profile),
105
+ read: async (context) => {
106
+ const result = await this.authenticate(context, profile, false);
107
+ if (result.status === 'refused')
108
+ return refused(context.generation, result.reason);
109
+ const response = await this.getResponse(path, result.session);
110
+ if (this.authExpired(response))
111
+ return refused(context.generation, 'auth-expired');
112
+ if (response.status < 200 || response.status >= 300)
113
+ return refused(context.generation, 'http-failure');
114
+ return applied(context.generation, { body: response.body });
115
+ },
116
+ };
117
+ }
118
+ writeOperation(id, path, profile) {
119
+ return {
120
+ descriptor: operationDescriptor(id, true, profile),
121
+ read: this.readOperation(`${id}-read`, path, profile).read,
122
+ write: (context, value) => this.write(context, profile, id, path, value),
123
+ };
124
+ }
125
+ async write(context, profile, kind, path, value) {
126
+ return this.withDevice(context, async () => {
127
+ const ownership = await this.options.ownership.acquire({ resource: 'router-session' });
128
+ if (ownership.status === 'refused')
129
+ return refused(context.generation, 'busy');
130
+ try {
131
+ const ready = await this.authenticate(context, profile, false);
132
+ if (ready.status === 'refused')
133
+ return refused(context.generation, ready.reason);
134
+ const capabilityPath = kind === 'mode' ? HILINK_PATHS.modeList : HILINK_PATHS.data;
135
+ const capability = await this.getResponse(capabilityPath, ready.session);
136
+ if (this.authExpired(capability))
137
+ return refused(context.generation, 'auth-expired');
138
+ if (!this.capabilitySupported(kind, capability.body))
139
+ return refused(context.generation, 'capability-unavailable');
140
+ if (kind === 'mode') {
141
+ const offered = parseHilinkCapabilities({ netModeList: capability.body }).net_mode;
142
+ if (offered.state !== 'reported' ||
143
+ !offered.modes.some((mode) => mode.id === String(value)))
144
+ return refused(context.generation, 'capability-unavailable');
145
+ }
146
+ const body = writeDocument(kind, value);
147
+ const posted = await this.postResponse(path, body, ready.session);
148
+ if (this.authExpired(posted))
149
+ return refused(context.generation, 'auth-expired');
150
+ if (!requestSucceeded(posted.status, posted.body))
151
+ return refused(context.generation, 'http-failure');
152
+ const fresh = await this.authenticate(context, profile, false);
153
+ if (fresh.status === 'refused')
154
+ return refused(context.generation, fresh.reason);
155
+ const readback = await this.getResponse(path, fresh.session);
156
+ if (this.authExpired(readback))
157
+ return refused(context.generation, 'auth-expired');
158
+ const matches = readbackMatches(kind, readback.body, value);
159
+ return matches
160
+ ? applied(context.generation, { body: readback.body })
161
+ : refused(context.generation, 'not-applied');
162
+ }
163
+ finally {
164
+ await ownership.lease.release();
165
+ }
166
+ });
167
+ }
168
+ }
169
+ function unsupportedOperations(_profileId) {
170
+ throw new Error('unsupported-hilink-profile');
171
+ }
@@ -0,0 +1,28 @@
1
+ import type { ProviderExecutionContext, ProviderMatchRequest } from '../contracts.js';
2
+ import { type HilinkOptions, type HilinkProfile } from './provider.js';
3
+ import type { HilinkHttpResponse } from './transport.js';
4
+ export type HilinkSession = {
5
+ readonly cookie: string;
6
+ readonly token: string;
7
+ };
8
+ export type HilinkSessionFailure = 'auth-expired' | 'http-failure' | 'malformed' | 'profile-mismatch' | 'unreachable';
9
+ export type HilinkSessionResult = {
10
+ readonly status: 'ready';
11
+ readonly session: HilinkSession;
12
+ } | {
13
+ readonly status: 'refused';
14
+ readonly reason: HilinkSessionFailure;
15
+ };
16
+ export declare class HilinkSessionRuntime {
17
+ #private;
18
+ protected readonly options: HilinkOptions;
19
+ constructor(options: HilinkOptions);
20
+ protected withDevice<T>(context: ProviderExecutionContext, run: () => Promise<T>): Promise<T>;
21
+ protected sessionKey(context: ProviderMatchRequest): string;
22
+ protected cachedSession(context: ProviderMatchRequest): HilinkSession | undefined;
23
+ protected authenticate(context: ProviderMatchRequest, profile: HilinkProfile, cache: boolean): Promise<HilinkSessionResult>;
24
+ protected authExpired(response: HilinkHttpResponse): boolean;
25
+ protected getResponse(path: string, session: HilinkSession): Promise<HilinkHttpResponse>;
26
+ protected postResponse(path: string, body: string, session: HilinkSession): Promise<HilinkHttpResponse>;
27
+ protected request(method: 'GET' | 'POST', path: string, body?: string, headers?: readonly string[]): Promise<HilinkHttpResponse>;
28
+ }