@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.
- package/README.md +317 -0
- package/dist/backend/at-lease.d.ts +57 -0
- package/dist/backend/at-lease.js +109 -0
- package/dist/backend/cell-info.d.ts +46 -0
- package/dist/backend/cell-info.js +124 -0
- package/dist/backend/constants.d.ts +24 -0
- package/{src/backend/constants.ts → dist/backend/constants.js} +4 -9
- package/dist/backend/device-classifier.d.ts +46 -0
- package/dist/backend/device-classifier.js +258 -0
- package/dist/backend/enrichment.d.ts +28 -0
- package/dist/backend/enrichment.js +59 -0
- package/dist/backend/features.d.ts +61 -0
- package/dist/backend/features.js +109 -0
- package/dist/backend/identity-ladder.d.ts +57 -0
- package/dist/backend/identity-ladder.js +158 -0
- package/dist/backend/identity-registry.d.ts +51 -0
- package/dist/backend/identity-registry.js +101 -0
- package/dist/backend/index.d.ts +30 -0
- package/dist/backend/index.js +35 -0
- package/dist/backend/lifecycle-interlock.d.ts +25 -0
- package/dist/backend/lifecycle-interlock.js +18 -0
- package/dist/backend/managed-objects.d.ts +39 -0
- package/dist/backend/managed-objects.js +82 -0
- package/dist/backend/mapping.d.ts +11 -0
- package/dist/backend/mapping.js +148 -0
- package/dist/backend/mm-backend.d.ts +44 -0
- package/dist/backend/mm-backend.js +154 -0
- package/dist/backend/mm-location.d.ts +21 -0
- package/dist/backend/mm-location.js +237 -0
- package/dist/backend/mm-mutations.d.ts +42 -0
- package/dist/backend/mm-mutations.js +259 -0
- package/dist/backend/modem-actor.d.ts +41 -0
- package/dist/backend/modem-actor.js +78 -0
- package/dist/backend/nm-auto-apn.d.ts +54 -0
- package/dist/backend/nm-auto-apn.js +124 -0
- package/dist/backend/nm-gsm-fields.d.ts +23 -0
- package/dist/backend/nm-gsm-fields.js +107 -0
- package/dist/backend/nmcli-nm-port.d.ts +28 -0
- package/dist/backend/nmcli-nm-port.js +173 -0
- package/dist/backend/nmcli-runner.d.ts +24 -0
- package/dist/backend/nmcli-runner.js +35 -0
- package/dist/backend/observer.d.ts +37 -0
- package/dist/backend/observer.js +219 -0
- package/dist/backend/power-contract.d.ts +49 -0
- package/dist/backend/power-contract.js +34 -0
- package/dist/backend/recovery-attribution.d.ts +32 -0
- package/dist/backend/recovery-attribution.js +57 -0
- package/dist/backend/recovery-budget.d.ts +45 -0
- package/dist/backend/recovery-budget.js +44 -0
- package/dist/backend/recovery-ladder.d.ts +94 -0
- package/dist/backend/recovery-ladder.js +116 -0
- package/dist/backend/router-ethernet.d.ts +19 -0
- package/dist/backend/router-ethernet.js +66 -0
- package/dist/backend/row-store.d.ts +13 -0
- package/dist/backend/row-store.js +82 -0
- package/dist/backend/signal-setup.d.ts +30 -0
- package/dist/backend/signal-setup.js +92 -0
- package/dist/backend/sim-unlock.d.ts +13 -0
- package/dist/backend/sim-unlock.js +153 -0
- package/dist/backend/transition-preconditions.d.ts +76 -0
- package/dist/backend/transition-preconditions.js +64 -0
- package/dist/backend/usage/accounting.d.ts +39 -0
- package/dist/backend/usage/accounting.js +73 -0
- package/dist/backend/usage/billing-cycle.d.ts +11 -0
- package/dist/backend/usage/billing-cycle.js +39 -0
- package/dist/backend/usage/boot-id.d.ts +6 -0
- package/{src/backend/usage/boot-id.ts → dist/backend/usage/boot-id.js} +7 -7
- package/dist/backend/usage/index.d.ts +8 -0
- package/dist/backend/usage/index.js +11 -0
- package/dist/backend/usage/policy-store.d.ts +50 -0
- package/dist/backend/usage/policy-store.js +161 -0
- package/dist/backend/usage/policy-write.d.ts +65 -0
- package/dist/backend/usage/policy-write.js +112 -0
- package/dist/backend/usage/proc-net-dev.d.ts +18 -0
- package/{src/backend/usage/proc-net-dev.ts → dist/backend/usage/proc-net-dev.js} +39 -47
- package/dist/backend/usage/sampler.d.ts +75 -0
- package/dist/backend/usage/sampler.js +211 -0
- package/dist/backend/usage/store.d.ts +38 -0
- package/dist/backend/usage/store.js +126 -0
- package/dist/backend/usb-device-snapshot.d.ts +31 -0
- package/dist/backend/usb-device-snapshot.js +1 -0
- package/dist/backend/usb-enumerator.d.ts +21 -0
- package/dist/backend/usb-enumerator.js +153 -0
- package/dist/backend/usb-mode-transition.d.ts +29 -0
- package/dist/backend/usb-mode-transition.js +196 -0
- package/dist/band/band-names.d.ts +42 -0
- package/dist/band/band-names.js +150 -0
- package/dist/band/certification.d.ts +84 -0
- package/dist/band/certification.js +127 -0
- package/dist/band/certified-bands.json +4 -0
- package/dist/band/index.d.ts +2 -0
- package/dist/band/index.js +8 -0
- package/dist/capability/detect.d.ts +52 -0
- package/dist/capability/detect.js +86 -0
- package/dist/capability/five-g-preference.d.ts +104 -0
- package/dist/capability/five-g-preference.js +171 -0
- package/dist/capability/index.d.ts +3 -0
- package/dist/capability/index.js +10 -0
- package/dist/capability/support-claim.d.ts +39 -0
- package/dist/capability/support-claim.js +81 -0
- package/dist/domain/brand.d.ts +10 -0
- package/dist/domain/brand.js +21 -0
- package/dist/domain/errors.d.ts +32 -0
- package/dist/domain/errors.js +48 -0
- package/dist/domain/generation.d.ts +8 -0
- package/dist/domain/generation.js +12 -0
- package/dist/domain/guards.d.ts +6 -0
- package/dist/domain/guards.js +127 -0
- package/dist/domain/identity.d.ts +109 -0
- package/dist/domain/identity.js +86 -0
- package/dist/domain/index.d.ts +14 -0
- package/dist/domain/index.js +18 -0
- package/dist/domain/mm-enums.d.ts +12 -0
- package/dist/domain/mm-enums.js +139 -0
- package/dist/domain/modem-presentation.d.ts +10 -0
- package/dist/domain/modem-presentation.js +39 -0
- package/dist/domain/observation.d.ts +39 -0
- package/dist/domain/observation.js +4 -0
- package/dist/domain/operation.d.ts +118 -0
- package/dist/domain/operation.js +85 -0
- package/dist/domain/physical-identity.d.ts +43 -0
- package/dist/domain/physical-identity.js +113 -0
- package/{src/domain/policy.ts → dist/domain/policy.d.ts} +34 -69
- package/dist/domain/policy.js +38 -0
- package/dist/domain/shadow-divergence.d.ts +27 -0
- package/dist/domain/shadow-divergence.js +70 -0
- package/dist/domain/snapshot.d.ts +53 -0
- package/dist/domain/snapshot.js +75 -0
- package/{src/domain/state.ts → dist/domain/state.d.ts} +23 -122
- package/dist/domain/state.js +38 -0
- package/dist/fcc/coverage.d.ts +63 -0
- package/dist/fcc/coverage.js +102 -0
- package/dist/fcc/index.d.ts +3 -0
- package/dist/fcc/index.js +12 -0
- package/dist/fcc/policy-store.d.ts +40 -0
- package/dist/fcc/policy-store.js +146 -0
- package/dist/fcc/policy-write.d.ts +32 -0
- package/dist/fcc/policy-write.js +37 -0
- package/dist/hardware/hilink-protocol.d.ts +39 -0
- package/dist/hardware/hilink-protocol.js +58 -0
- package/dist/hardware/index.d.ts +3 -0
- package/dist/hardware/index.js +15 -0
- package/dist/hardware/router-parsers.d.ts +89 -0
- package/dist/hardware/router-parsers.js +234 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +26 -0
- package/dist/journal/codec.d.ts +44 -0
- package/dist/journal/codec.js +198 -0
- package/dist/journal/engine.d.ts +28 -0
- package/dist/journal/engine.js +68 -0
- package/dist/journal/entry.d.ts +74 -0
- package/dist/journal/entry.js +56 -0
- package/dist/journal/index.d.ts +6 -0
- package/dist/journal/index.js +6 -0
- package/dist/journal/legacy-ceraui.d.ts +73 -0
- package/dist/journal/legacy-ceraui.js +227 -0
- package/dist/journal/recovery.d.ts +58 -0
- package/dist/journal/recovery.js +117 -0
- package/dist/journal/store.d.ts +55 -0
- package/dist/journal/store.js +150 -0
- package/dist/location/fix-state.d.ts +53 -0
- package/dist/location/fix-state.js +75 -0
- package/dist/location/index.d.ts +2 -0
- package/dist/location/index.js +8 -0
- package/dist/location/nmea.d.ts +10 -0
- package/dist/location/nmea.js +89 -0
- package/dist/observations/envelope.d.ts +63 -0
- package/dist/observations/envelope.js +77 -0
- package/dist/observations/freshness.d.ts +28 -0
- package/dist/observations/freshness.js +76 -0
- package/dist/observations/index.d.ts +13 -0
- package/dist/observations/index.js +24 -0
- package/dist/observations/metric.d.ts +47 -0
- package/dist/observations/metric.js +73 -0
- package/dist/observations/model.d.ts +80 -0
- package/dist/observations/model.js +11 -0
- package/dist/observations/provenance.d.ts +94 -0
- package/dist/observations/provenance.js +67 -0
- package/dist/observations/raw.d.ts +42 -0
- package/dist/observations/raw.js +146 -0
- package/dist/observations/reading.d.ts +51 -0
- package/dist/observations/reading.js +65 -0
- package/dist/observations/sources/hilink.d.ts +10 -0
- package/dist/observations/sources/hilink.js +84 -0
- package/dist/observations/sources/modemmanager.d.ts +18 -0
- package/dist/observations/sources/modemmanager.js +239 -0
- package/dist/observations/sources/router-shared.d.ts +29 -0
- package/dist/observations/sources/router-shared.js +68 -0
- package/dist/observations/sources/ufi.d.ts +10 -0
- package/dist/observations/sources/ufi.js +111 -0
- package/dist/observations/sources/zte.d.ts +7 -0
- package/dist/observations/sources/zte.js +71 -0
- package/dist/observations/state-separation.d.ts +64 -0
- package/dist/observations/state-separation.js +52 -0
- package/dist/operations/contracts.d.ts +72 -0
- package/dist/operations/contracts.js +1 -0
- package/dist/operations/index.d.ts +1 -0
- package/dist/operations/index.js +1 -0
- package/dist/operations/operation-engine.d.ts +16 -0
- package/dist/operations/operation-engine.js +194 -0
- package/dist/ports/index.d.ts +12 -0
- package/{src/ports/index.ts → dist/ports/index.js} +12 -8
- package/dist/ports/location.d.ts +87 -0
- package/dist/ports/location.js +36 -0
- package/dist/ports/modem-manager.d.ts +89 -0
- package/dist/ports/modem-manager.js +9 -0
- package/dist/ports/mutation-admission.d.ts +27 -0
- package/dist/ports/mutation-admission.js +9 -0
- package/dist/ports/network-manager.d.ts +68 -0
- package/dist/ports/network-manager.js +13 -0
- package/{src/ports/observation.ts → dist/ports/observation.d.ts} +16 -27
- package/dist/ports/observation.js +7 -0
- package/dist/ports/ops.d.ts +44 -0
- package/dist/ports/ops.js +16 -0
- package/{src/ports/receipts.ts → dist/ports/receipts.d.ts} +5 -27
- package/dist/ports/receipts.js +9 -0
- package/dist/ports/reconcile.d.ts +33 -0
- package/dist/ports/reconcile.js +200 -0
- package/dist/ports/resource-ownership.d.ts +29 -0
- package/dist/ports/resource-ownership.js +1 -0
- package/dist/ports/router.d.ts +19 -0
- package/dist/ports/router.js +7 -0
- package/dist/ports/sms.d.ts +64 -0
- package/dist/ports/sms.js +24 -0
- package/dist/ports/uhubctl.d.ts +6 -0
- package/dist/ports/uhubctl.js +1 -0
- package/dist/providers/contracts.d.ts +124 -0
- package/dist/providers/contracts.js +10 -0
- package/dist/providers/huawei-hilink/index.d.ts +2 -0
- package/dist/providers/huawei-hilink/index.js +2 -0
- package/dist/providers/huawei-hilink/operations.d.ts +20 -0
- package/dist/providers/huawei-hilink/operations.js +56 -0
- package/dist/providers/huawei-hilink/provider.d.ts +52 -0
- package/dist/providers/huawei-hilink/provider.js +76 -0
- package/dist/providers/huawei-hilink/runtime.d.ts +22 -0
- package/dist/providers/huawei-hilink/runtime.js +171 -0
- package/dist/providers/huawei-hilink/session.d.ts +28 -0
- package/dist/providers/huawei-hilink/session.js +120 -0
- package/dist/providers/huawei-hilink/transport.d.ts +19 -0
- package/dist/providers/huawei-hilink/transport.js +1 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/matcher.d.ts +3 -0
- package/dist/providers/matcher.js +205 -0
- package/dist/providers/modem-manager/errors.d.ts +7 -0
- package/dist/providers/modem-manager/errors.js +37 -0
- package/dist/providers/modem-manager/generic-operations.d.ts +8 -0
- package/dist/providers/modem-manager/generic-operations.js +207 -0
- package/dist/providers/modem-manager/index.d.ts +3 -0
- package/dist/providers/modem-manager/index.js +3 -0
- package/dist/providers/modem-manager/module-operations.d.ts +21 -0
- package/dist/providers/modem-manager/module-operations.js +118 -0
- package/dist/providers/modem-manager/provider.d.ts +39 -0
- package/dist/providers/modem-manager/provider.js +152 -0
- package/dist/providers/modem-manager/snapshot.d.ts +5 -0
- package/dist/providers/modem-manager/snapshot.js +204 -0
- package/dist/providers/modem-manager/types.d.ts +135 -0
- package/dist/providers/modem-manager/types.js +1 -0
- package/dist/providers/network-manager/adapter.d.ts +71 -0
- package/dist/providers/network-manager/adapter.js +348 -0
- package/dist/providers/network-manager/index.d.ts +2 -0
- package/dist/providers/network-manager/index.js +2 -0
- package/dist/providers/network-manager/types.d.ts +163 -0
- package/dist/providers/network-manager/types.js +77 -0
- package/dist/providers/registry.d.ts +13 -0
- package/dist/providers/registry.js +33 -0
- package/dist/providers/ufi-himi/index.d.ts +6 -0
- package/dist/providers/ufi-himi/index.js +6 -0
- package/dist/providers/ufi-himi/operations.d.ts +41 -0
- package/dist/providers/ufi-himi/operations.js +66 -0
- package/dist/providers/ufi-himi/prohibitions.d.ts +62 -0
- package/dist/providers/ufi-himi/prohibitions.js +88 -0
- package/dist/providers/ufi-himi/provider.d.ts +41 -0
- package/dist/providers/ufi-himi/provider.js +204 -0
- package/dist/providers/ufi-himi/qualcomm-evidence.d.ts +32 -0
- package/dist/providers/ufi-himi/qualcomm-evidence.js +51 -0
- package/dist/providers/ufi-himi/session.d.ts +46 -0
- package/dist/providers/ufi-himi/session.js +92 -0
- package/dist/providers/ufi-himi/transport.d.ts +29 -0
- package/dist/providers/ufi-himi/transport.js +25 -0
- package/dist/providers/zte-goform/index.d.ts +2 -0
- package/dist/providers/zte-goform/index.js +2 -0
- package/dist/providers/zte-goform/provider.d.ts +51 -0
- package/dist/providers/zte-goform/provider.js +101 -0
- package/dist/providers/zte-goform/session.d.ts +17 -0
- package/dist/providers/zte-goform/session.js +133 -0
- package/dist/providers/zte-goform/transport.d.ts +16 -0
- package/dist/providers/zte-goform/transport.js +1 -0
- package/dist/radio/band-truth.d.ts +50 -0
- package/dist/radio/band-truth.js +92 -0
- package/dist/radio/index.d.ts +3 -0
- package/dist/radio/index.js +10 -0
- package/dist/radio/mode-combinations.d.ts +78 -0
- package/dist/radio/mode-combinations.js +198 -0
- package/dist/radio/mode-truth.d.ts +67 -0
- package/dist/radio/mode-truth.js +112 -0
- package/dist/redact.d.ts +15 -0
- package/dist/redact.js +189 -0
- package/dist/safety/composition-root.d.ts +28 -0
- package/dist/safety/composition-root.js +65 -0
- package/dist/safety/flock-resource-ownership.d.ts +11 -0
- package/dist/safety/flock-resource-ownership.js +151 -0
- package/dist/safety/index.d.ts +2 -0
- package/dist/safety/index.js +2 -0
- package/dist/sms/dbus-messaging.d.ts +17 -0
- package/dist/sms/dbus-messaging.js +185 -0
- package/dist/sms/inbox-store.d.ts +10 -0
- package/dist/sms/inbox-store.js +82 -0
- package/dist/sms/index.d.ts +4 -0
- package/dist/sms/index.js +10 -0
- package/dist/sms/mmcli-parse.d.ts +54 -0
- package/dist/sms/mmcli-parse.js +224 -0
- package/dist/sms/normalize.d.ts +42 -0
- package/dist/sms/normalize.js +95 -0
- package/dist/testing/domain-fakes.d.ts +58 -0
- package/dist/testing/domain-fakes.js +98 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +17 -0
- package/dist/testing/provider-fakes.d.ts +45 -0
- package/dist/testing/provider-fakes.js +64 -0
- package/dist/transport/calls.d.ts +9 -0
- package/dist/transport/calls.js +88 -0
- package/dist/transport/codec.d.ts +3 -0
- package/dist/transport/codec.js +207 -0
- package/dist/transport/dbus-native.d.ts +57 -0
- package/dist/transport/dbus-native.js +17 -0
- package/dist/transport/errors.d.ts +21 -0
- package/{src/transport/errors.ts → dist/transport/errors.js} +34 -46
- package/dist/transport/index.d.ts +4 -0
- package/dist/transport/index.js +9 -0
- package/dist/transport/signals.d.ts +15 -0
- package/dist/transport/signals.js +123 -0
- package/dist/transport/signature.d.ts +7 -0
- package/dist/transport/signature.js +94 -0
- package/dist/transport/transport.d.ts +2 -0
- package/dist/transport/transport.js +202 -0
- package/dist/transport/types.d.ts +61 -0
- package/dist/transport/types.js +19 -0
- package/dist/usb-mode/catalog-schema.d.ts +139 -0
- package/dist/usb-mode/catalog-schema.js +97 -0
- package/dist/usb-mode/catalog.d.ts +21 -0
- package/{src/usb-mode/catalog.ts → dist/usb-mode/catalog.js} +10 -32
- package/dist/usb-mode/certified-catalog.json +67 -0
- package/dist/usb-mode/index.d.ts +5 -0
- package/dist/usb-mode/index.js +15 -0
- package/dist/usb-mode/ingestion.d.ts +111 -0
- package/dist/usb-mode/ingestion.js +187 -0
- package/dist/usb-mode/promotion-review.d.ts +21 -0
- package/dist/usb-mode/promotion-review.js +87 -0
- package/dist/usb-mode/usb-devices-parse.d.ts +36 -0
- package/dist/usb-mode/usb-devices-parse.js +157 -0
- package/dist/ussd/calls.d.ts +32 -0
- package/dist/ussd/calls.js +96 -0
- package/dist/ussd/index.d.ts +5 -0
- package/dist/ussd/index.js +12 -0
- package/dist/ussd/mm-ussd.d.ts +37 -0
- package/dist/ussd/mm-ussd.js +205 -0
- package/dist/ussd/refusal.d.ts +53 -0
- package/dist/ussd/refusal.js +154 -0
- package/dist/ussd/registration.d.ts +20 -0
- package/dist/ussd/registration.js +101 -0
- package/dist/ussd/session.d.ts +84 -0
- package/dist/ussd/session.js +163 -0
- package/package.json +38 -4
- package/src/backend/at-lease.test.ts +0 -106
- package/src/backend/at-lease.ts +0 -158
- package/src/backend/cell-info.test.ts +0 -154
- package/src/backend/cell-info.ts +0 -160
- package/src/backend/device-classifier.test.ts +0 -168
- package/src/backend/device-classifier.ts +0 -248
- package/src/backend/enrichment.ts +0 -96
- package/src/backend/features.test.ts +0 -162
- package/src/backend/features.ts +0 -179
- package/src/backend/identity-ladder.test.ts +0 -117
- package/src/backend/identity-ladder.ts +0 -221
- package/src/backend/identity-registry.test.ts +0 -89
- package/src/backend/identity-registry.ts +0 -151
- package/src/backend/index.ts +0 -221
- package/src/backend/lifecycle-interlock.ts +0 -38
- package/src/backend/managed-objects.ts +0 -108
- package/src/backend/mapping.ts +0 -160
- package/src/backend/mm-backend.ts +0 -191
- package/src/backend/mm-mutations.ts +0 -228
- package/src/backend/modem-actor.test.ts +0 -95
- package/src/backend/modem-actor.ts +0 -112
- package/src/backend/nm-auto-apn.ts +0 -161
- package/src/backend/nm-gsm-fields.ts +0 -122
- package/src/backend/nmcli-nm-port.ts +0 -228
- package/src/backend/nmcli-runner.ts +0 -52
- package/src/backend/observer.ts +0 -297
- package/src/backend/power-contract.test.ts +0 -40
- package/src/backend/power-contract.ts +0 -83
- package/src/backend/recovery-attribution.test.ts +0 -102
- package/src/backend/recovery-attribution.ts +0 -86
- package/src/backend/recovery-budget.test.ts +0 -64
- package/src/backend/recovery-budget.ts +0 -84
- package/src/backend/recovery-ladder.test.ts +0 -257
- package/src/backend/recovery-ladder.ts +0 -249
- package/src/backend/router-ethernet.test.ts +0 -71
- package/src/backend/router-ethernet.ts +0 -90
- package/src/backend/row-store.ts +0 -105
- package/src/backend/signal-setup.ts +0 -112
- package/src/backend/sim-unlock.ts +0 -193
- package/src/backend/transition-preconditions.ts +0 -149
- package/src/backend/usage/accounting.test.ts +0 -147
- package/src/backend/usage/accounting.ts +0 -123
- package/src/backend/usage/billing-cycle.test.ts +0 -62
- package/src/backend/usage/billing-cycle.ts +0 -45
- package/src/backend/usage/index.ts +0 -37
- package/src/backend/usage/proc-net-dev.test.ts +0 -56
- package/src/backend/usage/sampler.test.ts +0 -219
- package/src/backend/usage/sampler.ts +0 -228
- package/src/backend/usage/store.test.ts +0 -148
- package/src/backend/usage/store.ts +0 -177
- package/src/backend/usb-enumerator.test.ts +0 -87
- package/src/backend/usb-enumerator.ts +0 -181
- package/src/backend/usb-mode-transition.test.ts +0 -323
- package/src/backend/usb-mode-transition.ts +0 -253
- package/src/domain/brand.ts +0 -29
- package/src/domain/errors.ts +0 -77
- package/src/domain/guards.test.ts +0 -218
- package/src/domain/guards.ts +0 -144
- package/src/domain/identity.test.ts +0 -83
- package/src/domain/identity.ts +0 -165
- package/src/domain/index.ts +0 -12
- package/src/domain/snapshot.test.ts +0 -266
- package/src/domain/snapshot.ts +0 -120
- package/src/index.test.ts +0 -6
- package/src/index.ts +0 -15
- package/src/ports/README.md +0 -61
- package/src/ports/forbidden-surface.test.ts +0 -241
- package/src/ports/modem-manager.ts +0 -72
- package/src/ports/network-manager.ts +0 -87
- package/src/ports/ops.ts +0 -60
- package/src/ports/ops.type-test.ts +0 -39
- package/src/ports/receipts.test.ts +0 -153
- package/src/ports/reconcile.test.ts +0 -152
- package/src/ports/reconcile.ts +0 -338
- package/src/ports/router.ts +0 -29
- package/src/redact.test.ts +0 -82
- package/src/redact.ts +0 -73
- package/src/transport/README.md +0 -65
- package/src/transport/calls.ts +0 -113
- package/src/transport/characterization.test.ts +0 -260
- package/src/transport/codec.test.ts +0 -118
- package/src/transport/codec.ts +0 -240
- package/src/transport/conformance-python.test.ts +0 -152
- package/src/transport/conformance-same-lib.test.ts +0 -115
- package/src/transport/dbus-native-lib.d.ts +0 -19
- package/src/transport/dbus-native.ts +0 -85
- package/src/transport/index.ts +0 -30
- package/src/transport/no-library-leak.test.ts +0 -61
- package/src/transport/reliability.test.ts +0 -173
- package/src/transport/signals.ts +0 -150
- package/src/transport/signature.ts +0 -110
- package/src/transport/test-support/fake-service.ts +0 -168
- package/src/transport/test-support/independent-producer.py +0 -110
- package/src/transport/test-support/private-bus.ts +0 -66
- package/src/transport/transport.ts +0 -250
- package/src/transport/types.ts +0 -118
- package/src/usb-mode/catalog-schema.test.ts +0 -181
- package/src/usb-mode/catalog-schema.ts +0 -113
- package/src/usb-mode/certified-catalog.json +0 -67
- package/src/usb-mode/index.ts +0 -27
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Brand } from './brand.js';
|
|
2
|
+
import type { ModemIdentity } from './identity.js';
|
|
3
|
+
import type { DataInterface, MmState, NmActivation, Presence, RadioPower, ReconcileStatus, RecoveryState, Registration, SimSlot, SourceHealth } from './state.js';
|
|
4
|
+
/** A monotonically increasing snapshot revision. */
|
|
5
|
+
export type Revision = Brand<number, 'Revision'>;
|
|
6
|
+
/** Construct a `Revision` from a non-negative integer. */
|
|
7
|
+
export declare function revision(value: number): Revision;
|
|
8
|
+
/** The revision every fresh identity starts at. */
|
|
9
|
+
export declare const INITIAL_REVISION: Revision;
|
|
10
|
+
/** The next revision after `current`. */
|
|
11
|
+
export declare function nextRevision(current: Revision): Revision;
|
|
12
|
+
/** The full coherent state of one modem at one point in time. */
|
|
13
|
+
export interface CellularSnapshot {
|
|
14
|
+
readonly identity: ModemIdentity;
|
|
15
|
+
readonly presence: Presence;
|
|
16
|
+
readonly sourceHealth: SourceHealth;
|
|
17
|
+
readonly simSlots: readonly SimSlot[];
|
|
18
|
+
readonly radioPower: RadioPower;
|
|
19
|
+
readonly mmState: MmState;
|
|
20
|
+
readonly registration: Registration;
|
|
21
|
+
readonly nmActivation: NmActivation;
|
|
22
|
+
readonly dataInterface: DataInterface;
|
|
23
|
+
readonly reconcileStatus: ReconcileStatus;
|
|
24
|
+
readonly recoveryState: RecoveryState;
|
|
25
|
+
readonly revision: Revision;
|
|
26
|
+
}
|
|
27
|
+
/** A partial update to a snapshot's dimensions; `revision` is managed, not patched. */
|
|
28
|
+
export type SnapshotPatch = Partial<Omit<CellularSnapshot, 'revision'>>;
|
|
29
|
+
/**
|
|
30
|
+
* Validate and return a snapshot. The guards run here: an impossible combination
|
|
31
|
+
* throws `ImpossibleStateError` rather than producing an incoherent value. This
|
|
32
|
+
* is the sole sanctioned constructor for an arbitrary snapshot.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createSnapshot(fields: CellularSnapshot): CellularSnapshot;
|
|
35
|
+
/** A valid baseline for a freshly-observed-but-absent modem, at revision 0. */
|
|
36
|
+
export declare function initialSnapshot(identity: ModemIdentity): CellularSnapshot;
|
|
37
|
+
/**
|
|
38
|
+
* Apply a dimension patch, bump the revision, and re-validate. Monotonicity is
|
|
39
|
+
* automatic (revision always advances by one); an impossible result throws.
|
|
40
|
+
*/
|
|
41
|
+
export declare function applyTransition(prev: CellularSnapshot, patch: SnapshotPatch): CellularSnapshot;
|
|
42
|
+
/**
|
|
43
|
+
* Replace a snapshot with a fully-formed successor that carries its own revision
|
|
44
|
+
* (the observer path). Enforces strict monotonicity — a stale or equal revision
|
|
45
|
+
* throws `RevisionMonotonicityError` — and validates the successor.
|
|
46
|
+
*/
|
|
47
|
+
export declare function supersede(prev: CellularSnapshot, next: CellularSnapshot): CellularSnapshot;
|
|
48
|
+
/**
|
|
49
|
+
* The source (MM daemon / bus) dropped: mark the data `sourceUnavailable` while
|
|
50
|
+
* KEEPING presence and all other facts. Stale is never removal — only an
|
|
51
|
+
* authoritative snapshot confirms absence (draft §Oracle round-1 lifecycle).
|
|
52
|
+
*/
|
|
53
|
+
export declare function markSourceUnavailable(prev: CellularSnapshot): CellularSnapshot;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// CellularSnapshot — the whole coherent state of one modem at one revision.
|
|
2
|
+
//
|
|
3
|
+
// A snapshot composes the identity and all eight orthogonal dimensions plus a
|
|
4
|
+
// monotonic `revision`. Every snapshot that exists has passed the guards: the
|
|
5
|
+
// constructors here are the ONLY sanctioned way to build or advance one, so an
|
|
6
|
+
// impossible combination can never be observed downstream. Revisions strictly
|
|
7
|
+
// increase, letting the observer (A3.1) and consumers order and dedupe events.
|
|
8
|
+
import { nonNegativeInteger } from './brand.js';
|
|
9
|
+
import { RevisionMonotonicityError } from './errors.js';
|
|
10
|
+
import { assertSnapshot } from './guards.js';
|
|
11
|
+
/** Construct a `Revision` from a non-negative integer. */
|
|
12
|
+
export function revision(value) {
|
|
13
|
+
return nonNegativeInteger(value, 'revision');
|
|
14
|
+
}
|
|
15
|
+
/** The revision every fresh identity starts at. */
|
|
16
|
+
export const INITIAL_REVISION = revision(0);
|
|
17
|
+
/** The next revision after `current`. */
|
|
18
|
+
export function nextRevision(current) {
|
|
19
|
+
return (current + 1);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate and return a snapshot. The guards run here: an impossible combination
|
|
23
|
+
* throws `ImpossibleStateError` rather than producing an incoherent value. This
|
|
24
|
+
* is the sole sanctioned constructor for an arbitrary snapshot.
|
|
25
|
+
*/
|
|
26
|
+
export function createSnapshot(fields) {
|
|
27
|
+
assertSnapshot(fields);
|
|
28
|
+
return fields;
|
|
29
|
+
}
|
|
30
|
+
/** A valid baseline for a freshly-observed-but-absent modem, at revision 0. */
|
|
31
|
+
export function initialSnapshot(identity) {
|
|
32
|
+
return {
|
|
33
|
+
identity,
|
|
34
|
+
presence: 'absent',
|
|
35
|
+
sourceHealth: 'live',
|
|
36
|
+
simSlots: [],
|
|
37
|
+
radioPower: 'unknown',
|
|
38
|
+
mmState: 'unknown',
|
|
39
|
+
registration: { status: 'unknown', activeRats: new Set() },
|
|
40
|
+
nmActivation: 'unavailable',
|
|
41
|
+
dataInterface: { present: false },
|
|
42
|
+
reconcileStatus: 'pending',
|
|
43
|
+
recoveryState: { stage: 'idle', attempts: 0 },
|
|
44
|
+
revision: INITIAL_REVISION,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Apply a dimension patch, bump the revision, and re-validate. Monotonicity is
|
|
49
|
+
* automatic (revision always advances by one); an impossible result throws.
|
|
50
|
+
*/
|
|
51
|
+
export function applyTransition(prev, patch) {
|
|
52
|
+
const next = { ...prev, ...patch, revision: nextRevision(prev.revision) };
|
|
53
|
+
assertSnapshot(next);
|
|
54
|
+
return next;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Replace a snapshot with a fully-formed successor that carries its own revision
|
|
58
|
+
* (the observer path). Enforces strict monotonicity — a stale or equal revision
|
|
59
|
+
* throws `RevisionMonotonicityError` — and validates the successor.
|
|
60
|
+
*/
|
|
61
|
+
export function supersede(prev, next) {
|
|
62
|
+
if (next.revision <= prev.revision) {
|
|
63
|
+
throw new RevisionMonotonicityError(prev.revision, next.revision);
|
|
64
|
+
}
|
|
65
|
+
assertSnapshot(next);
|
|
66
|
+
return next;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The source (MM daemon / bus) dropped: mark the data `sourceUnavailable` while
|
|
70
|
+
* KEEPING presence and all other facts. Stale is never removal — only an
|
|
71
|
+
* authoritative snapshot confirms absence (draft §Oracle round-1 lifecycle).
|
|
72
|
+
*/
|
|
73
|
+
export function markSourceUnavailable(prev) {
|
|
74
|
+
return applyTransition(prev, { sourceHealth: 'sourceUnavailable' });
|
|
75
|
+
}
|
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
// Draft §Oracle round-1: modem state is NOT one enum. It is a set of independent
|
|
4
|
-
// dimensions that vary separately — presence, SIM, radio, registration,
|
|
5
|
-
// NM-activation, data interface, reconcile, recovery. Collapsing them into a
|
|
6
|
-
// single enum loses real, simultaneously-true facts (e.g. "present + radio on +
|
|
7
|
-
// searching + no NM connection"). Each dimension below mirrors a real
|
|
8
|
-
// ModemManager / NetworkManager concept; values track those enums.
|
|
9
|
-
|
|
10
|
-
import type { Brand } from './brand';
|
|
11
|
-
import { nonNegativeInteger } from './brand';
|
|
12
|
-
|
|
1
|
+
import type { Brand } from './brand.js';
|
|
13
2
|
/** Milliseconds since the Unix epoch. */
|
|
14
3
|
export type EpochMillis = Brand<number, 'EpochMillis'>;
|
|
15
|
-
|
|
16
4
|
/** Construct an `EpochMillis` from a non-negative integer timestamp. */
|
|
17
|
-
export function epochMillis(value: number): EpochMillis
|
|
18
|
-
return nonNegativeInteger(value, 'epochMillis') as EpochMillis;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// --- 1. presence + source health -------------------------------------------
|
|
22
|
-
|
|
5
|
+
export declare function epochMillis(value: number): EpochMillis;
|
|
23
6
|
/** Whether the modem is in the current authoritative observation snapshot. */
|
|
24
7
|
export type Presence = 'present' | 'absent';
|
|
25
|
-
|
|
26
8
|
/**
|
|
27
9
|
* Health of the observation SOURCE (the ModemManager daemon / bus), independent
|
|
28
10
|
* of presence. When the source drops (owner loss, bus disconnect) the last data
|
|
@@ -30,128 +12,59 @@ export type Presence = 'present' | 'absent';
|
|
|
30
12
|
* `absent`. Only an authoritative snapshot confirms real removal (A3.1 epochs).
|
|
31
13
|
*/
|
|
32
14
|
export type SourceHealth = 'live' | 'stale' | 'sourceUnavailable';
|
|
33
|
-
|
|
34
|
-
// --- 2. SIM slots + lock ----------------------------------------------------
|
|
35
|
-
|
|
36
15
|
/** SIM lock state — subset of `MMModemLock` plus `unknown`. */
|
|
37
|
-
export type SimLock =
|
|
38
|
-
| 'unknown'
|
|
39
|
-
| 'none'
|
|
40
|
-
| 'sim-pin'
|
|
41
|
-
| 'sim-puk'
|
|
42
|
-
| 'sim-pin2'
|
|
43
|
-
| 'sim-puk2'
|
|
44
|
-
| 'net-pers'
|
|
45
|
-
| 'permanently-blocked';
|
|
46
|
-
|
|
16
|
+
export type SimLock = 'unknown' | 'none' | 'sim-pin' | 'sim-puk' | 'sim-pin2' | 'sim-puk2' | 'net-pers' | 'permanently-blocked';
|
|
47
17
|
/** A single physical SIM slot. */
|
|
48
18
|
export interface SimSlot {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
19
|
+
/** 1-based slot index (ModemManager numbers slots from 1). */
|
|
20
|
+
readonly index: number;
|
|
21
|
+
/** A SIM card is physically inserted in this slot. */
|
|
22
|
+
readonly occupied: boolean;
|
|
23
|
+
/** This is the primary/active slot the modem is currently using. */
|
|
24
|
+
readonly active: boolean;
|
|
25
|
+
readonly lock: SimLock;
|
|
56
26
|
}
|
|
57
|
-
|
|
58
27
|
/** Lock states that require a SIM to actually be present in the slot. */
|
|
59
|
-
export const SIM_LOCK_REQUIRES_CARD: ReadonlySet<SimLock
|
|
60
|
-
'sim-pin',
|
|
61
|
-
'sim-puk',
|
|
62
|
-
'sim-pin2',
|
|
63
|
-
'sim-puk2',
|
|
64
|
-
'net-pers',
|
|
65
|
-
'permanently-blocked',
|
|
66
|
-
]);
|
|
67
|
-
|
|
68
|
-
// --- 3. radio power + MM state ---------------------------------------------
|
|
69
|
-
|
|
28
|
+
export declare const SIM_LOCK_REQUIRES_CARD: ReadonlySet<SimLock>;
|
|
70
29
|
/** Radio power state — `MMModemPowerState`. */
|
|
71
30
|
export type RadioPower = 'unknown' | 'off' | 'low' | 'on';
|
|
72
|
-
|
|
73
31
|
/** Modem lifecycle state — `MMModemState`. */
|
|
74
|
-
export type MmState =
|
|
75
|
-
| 'failed'
|
|
76
|
-
| 'unknown'
|
|
77
|
-
| 'initializing'
|
|
78
|
-
| 'locked'
|
|
79
|
-
| 'disabled'
|
|
80
|
-
| 'disabling'
|
|
81
|
-
| 'enabling'
|
|
82
|
-
| 'enabled'
|
|
83
|
-
| 'searching'
|
|
84
|
-
| 'registered'
|
|
85
|
-
| 'disconnecting'
|
|
86
|
-
| 'connecting'
|
|
87
|
-
| 'connected';
|
|
88
|
-
|
|
32
|
+
export type MmState = 'failed' | 'unknown' | 'initializing' | 'locked' | 'disabled' | 'disabling' | 'enabling' | 'enabled' | 'searching' | 'registered' | 'disconnecting' | 'connecting' | 'connected';
|
|
89
33
|
/**
|
|
90
34
|
* MM states that imply the radio is powered and actively on the air — none of
|
|
91
35
|
* these can coexist with `radioPower: 'off'`, and all imply the modem is present.
|
|
92
36
|
*/
|
|
93
|
-
export const MM_STATES_REQUIRING_RADIO: ReadonlySet<MmState
|
|
94
|
-
'enabled',
|
|
95
|
-
'searching',
|
|
96
|
-
'registered',
|
|
97
|
-
'connecting',
|
|
98
|
-
'connected',
|
|
99
|
-
'disconnecting',
|
|
100
|
-
]);
|
|
101
|
-
|
|
102
|
-
// --- 4. registration + RAT set ---------------------------------------------
|
|
103
|
-
|
|
37
|
+
export declare const MM_STATES_REQUIRING_RADIO: ReadonlySet<MmState>;
|
|
104
38
|
/** 3GPP registration state — `MMModem3gppRegistrationState`. */
|
|
105
39
|
export type RegistrationStatus = 'idle' | 'home' | 'searching' | 'denied' | 'unknown' | 'roaming';
|
|
106
|
-
|
|
107
40
|
/** Radio access technology family — subset of `MMModemAccessTechnology` groups. */
|
|
108
41
|
export type RadioAccessTechnology = 'gsm' | 'umts' | 'lte' | '5gnr';
|
|
109
|
-
|
|
110
42
|
/**
|
|
111
43
|
* Registration dimension: a status plus the SET of currently-active access
|
|
112
44
|
* technologies. MM's access-technology field is a bitmask (carrier aggregation
|
|
113
45
|
* can light more than one), so a set — not a single value — is the faithful model.
|
|
114
46
|
*/
|
|
115
47
|
export interface Registration {
|
|
116
|
-
|
|
117
|
-
|
|
48
|
+
readonly status: RegistrationStatus;
|
|
49
|
+
readonly activeRats: ReadonlySet<RadioAccessTechnology>;
|
|
118
50
|
}
|
|
119
|
-
|
|
120
51
|
/** Registration statuses that mean the modem is attached to a network. */
|
|
121
|
-
export function isRegistered(status: RegistrationStatus): boolean
|
|
122
|
-
return status === 'home' || status === 'roaming';
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// --- 5. NM activation -------------------------------------------------------
|
|
126
|
-
|
|
52
|
+
export declare function isRegistered(status: RegistrationStatus): boolean;
|
|
127
53
|
/**
|
|
128
54
|
* NetworkManager connection/activation state for this modem's device — `NMDeviceState`
|
|
129
55
|
* collapsed to the states that matter. NM is the SOLE owner of activation; this
|
|
130
56
|
* dimension reflects, never drives, that ownership.
|
|
131
57
|
*/
|
|
132
|
-
export type NmActivation =
|
|
133
|
-
| 'unmanaged'
|
|
134
|
-
| 'unavailable'
|
|
135
|
-
| 'disconnected'
|
|
136
|
-
| 'activating'
|
|
137
|
-
| 'activated'
|
|
138
|
-
| 'deactivating'
|
|
139
|
-
| 'failed';
|
|
140
|
-
|
|
141
|
-
// --- 6. data interface ------------------------------------------------------
|
|
142
|
-
|
|
58
|
+
export type NmActivation = 'unmanaged' | 'unavailable' | 'disconnected' | 'activating' | 'activated' | 'deactivating' | 'failed';
|
|
143
59
|
/**
|
|
144
60
|
* The net device the modem exposes for data (e.g. `wwan0`). `name` may be absent
|
|
145
61
|
* even when `present` (MM can report a bearer whose ip-interface is not yet
|
|
146
62
|
* named); a `name` without `present` is impossible and guarded.
|
|
147
63
|
*/
|
|
148
64
|
export interface DataInterface {
|
|
149
|
-
|
|
150
|
-
|
|
65
|
+
readonly present: boolean;
|
|
66
|
+
readonly name?: string;
|
|
151
67
|
}
|
|
152
|
-
|
|
153
|
-
// --- 7. reconcile status ----------------------------------------------------
|
|
154
|
-
|
|
155
68
|
/**
|
|
156
69
|
* Aggregate desired-state reconciliation status. Mirrors the A2.2 receipt
|
|
157
70
|
* taxonomy at snapshot granularity: `unsupported` means the desired state cannot
|
|
@@ -159,31 +72,19 @@ export interface DataInterface {
|
|
|
159
72
|
* never silently dropped.
|
|
160
73
|
*/
|
|
161
74
|
export type ReconcileStatus = 'converged' | 'reconciling' | 'pending' | 'divergent' | 'unsupported';
|
|
162
|
-
|
|
163
|
-
// --- 8. recovery state ------------------------------------------------------
|
|
164
|
-
|
|
165
75
|
/**
|
|
166
76
|
* Recovery-ladder stage. Ordered rungs mirror A3.4:
|
|
167
77
|
* nm-cycle → mm-cycle → reset → power-cycle, gated by attribution and budgets.
|
|
168
78
|
* `idle` = nothing in flight; `exhausted` = budget spent, gave up.
|
|
169
79
|
*/
|
|
170
|
-
export type RecoveryStage =
|
|
171
|
-
| 'idle'
|
|
172
|
-
| 'attributing'
|
|
173
|
-
| 'nm-cycle'
|
|
174
|
-
| 'mm-cycle'
|
|
175
|
-
| 'reset'
|
|
176
|
-
| 'power-cycle'
|
|
177
|
-
| 'cooldown'
|
|
178
|
-
| 'exhausted';
|
|
179
|
-
|
|
80
|
+
export type RecoveryStage = 'idle' | 'attributing' | 'nm-cycle' | 'mm-cycle' | 'reset' | 'power-cycle' | 'cooldown' | 'exhausted';
|
|
180
81
|
/**
|
|
181
82
|
* Recovery dimension. `cooldownUntil` is present ONLY while `stage` is `cooldown`
|
|
182
83
|
* (guarded); `attempts` counts disruptive rungs fired in the current budget window
|
|
183
84
|
* and resets to 0 at `idle`.
|
|
184
85
|
*/
|
|
185
86
|
export interface RecoveryState {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
87
|
+
readonly stage: RecoveryStage;
|
|
88
|
+
readonly attempts: number;
|
|
89
|
+
readonly cooldownUntil?: EpochMillis;
|
|
189
90
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Orthogonal state dimensions.
|
|
2
|
+
//
|
|
3
|
+
// Draft §Oracle round-1: modem state is NOT one enum. It is a set of independent
|
|
4
|
+
// dimensions that vary separately — presence, SIM, radio, registration,
|
|
5
|
+
// NM-activation, data interface, reconcile, recovery. Collapsing them into a
|
|
6
|
+
// single enum loses real, simultaneously-true facts (e.g. "present + radio on +
|
|
7
|
+
// searching + no NM connection"). Each dimension below mirrors a real
|
|
8
|
+
// ModemManager / NetworkManager concept; values track those enums.
|
|
9
|
+
import { nonNegativeInteger } from './brand.js';
|
|
10
|
+
/** Construct an `EpochMillis` from a non-negative integer timestamp. */
|
|
11
|
+
export function epochMillis(value) {
|
|
12
|
+
return nonNegativeInteger(value, 'epochMillis');
|
|
13
|
+
}
|
|
14
|
+
/** Lock states that require a SIM to actually be present in the slot. */
|
|
15
|
+
export const SIM_LOCK_REQUIRES_CARD = new Set([
|
|
16
|
+
'sim-pin',
|
|
17
|
+
'sim-puk',
|
|
18
|
+
'sim-pin2',
|
|
19
|
+
'sim-puk2',
|
|
20
|
+
'net-pers',
|
|
21
|
+
'permanently-blocked',
|
|
22
|
+
]);
|
|
23
|
+
/**
|
|
24
|
+
* MM states that imply the radio is powered and actively on the air — none of
|
|
25
|
+
* these can coexist with `radioPower: 'off'`, and all imply the modem is present.
|
|
26
|
+
*/
|
|
27
|
+
export const MM_STATES_REQUIRING_RADIO = new Set([
|
|
28
|
+
'enabled',
|
|
29
|
+
'searching',
|
|
30
|
+
'registered',
|
|
31
|
+
'connecting',
|
|
32
|
+
'connected',
|
|
33
|
+
'disconnecting',
|
|
34
|
+
]);
|
|
35
|
+
/** Registration statuses that mean the modem is attached to a network. */
|
|
36
|
+
export function isRegistered(status) {
|
|
37
|
+
return status === 'home' || status === 'roaming';
|
|
38
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** The four vendor scripts ModemManager 1.24.2 ships, and what each one drives. */
|
|
2
|
+
export declare const MM_FCC_UNLOCK_VENDOR_SCRIPTS: {
|
|
3
|
+
readonly '105b': "mbimcli";
|
|
4
|
+
readonly '1199': "qmicli";
|
|
5
|
+
readonly '14c3': "mbimcli";
|
|
6
|
+
readonly '2c7c': "qmicli";
|
|
7
|
+
};
|
|
8
|
+
export type MmFccUnlockVendorScript = keyof typeof MM_FCC_UNLOCK_VENDOR_SCRIPTS;
|
|
9
|
+
/** The interpreters those scripts invoke, and the packages that provide them. */
|
|
10
|
+
export declare const MM_FCC_UNLOCK_RUNTIME_PACKAGES: {
|
|
11
|
+
readonly qmicli: "libqmi-utils";
|
|
12
|
+
readonly mbimcli: "libmbim-utils";
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* ModemManager 1.24.2's COMPLETE shipped mapping — `data/dispatcher-fcc-unlock/
|
|
16
|
+
* meson.build`'s `vidpids` dict, verbatim. Fourteen entries; there are no others.
|
|
17
|
+
*/
|
|
18
|
+
export declare const MM_FCC_UNLOCK_COVERAGE: {
|
|
19
|
+
readonly '03f0:4e1d': "1199";
|
|
20
|
+
readonly '105b:e0ab': "105b";
|
|
21
|
+
readonly '105b:e0c3': "105b";
|
|
22
|
+
readonly '1199:9079': "1199";
|
|
23
|
+
readonly '14c3:4d75': "14c3";
|
|
24
|
+
readonly '1eac:1001': "2c7c";
|
|
25
|
+
readonly '1eac:1004': "2c7c";
|
|
26
|
+
readonly '1eac:1007': "2c7c";
|
|
27
|
+
readonly '2c7c:030a': "2c7c";
|
|
28
|
+
readonly '2c7c:0313': "2c7c";
|
|
29
|
+
readonly '2c7c:0314': "2c7c";
|
|
30
|
+
readonly '2c7c:0801': "2c7c";
|
|
31
|
+
readonly '413c:81a3': "1199";
|
|
32
|
+
readonly '413c:81a8': "1199";
|
|
33
|
+
};
|
|
34
|
+
export type MmFccUnlockKey = keyof typeof MM_FCC_UNLOCK_COVERAGE;
|
|
35
|
+
/**
|
|
36
|
+
* Fold a vid/pid pair into the dispatcher's key, or `undefined` when it is not a
|
|
37
|
+
* pair of 4-hex ids. Case is folded because sysfs and udev disagree about it
|
|
38
|
+
* (`ID_VENDOR_ID` is lowercase, some vendor strings are not) while the dispatcher's
|
|
39
|
+
* `%04x` is unambiguously lowercase; a `0x` prefix is tolerated for the same reason.
|
|
40
|
+
* NOTHING ELSE is normalized — a 3-digit or 5-digit id is a different device, not a
|
|
41
|
+
* sloppy spelling of this one.
|
|
42
|
+
*/
|
|
43
|
+
export declare function normalizeVidPid(vid: string, pid: string): string | undefined;
|
|
44
|
+
/** True for a string already in the dispatcher's `<vid>:<pid>` shape. */
|
|
45
|
+
export declare function isFccUnlockKey(value: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Does ModemManager ship an unlock procedure for this device?
|
|
48
|
+
*
|
|
49
|
+
* The three answers are NOT interchangeable, and the third is why this returns a
|
|
50
|
+
* tri-state rather than a boolean:
|
|
51
|
+
* present — a `<vid>:<pid>` entry exists; the toggle can do something.
|
|
52
|
+
* absent — the ids are well-formed and are NOT in the mapping. A positive
|
|
53
|
+
* statement about the device, so the module reads `unavailable` and no
|
|
54
|
+
* control is offered.
|
|
55
|
+
* unknown — we could not read the ids at all. That is a statement about the READ,
|
|
56
|
+
* and reporting it as `absent` would hide the module on hardware that
|
|
57
|
+
* may well be covered.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveFccUnlockCoverage(vid: string | undefined, pid: string | undefined): 'present' | 'absent' | 'unknown';
|
|
60
|
+
/** The vendor script a covered key resolves to, for diagnostics and docs. */
|
|
61
|
+
export declare function fccUnlockVendorScript(key: string): MmFccUnlockVendorScript | undefined;
|
|
62
|
+
/** The interpreter a covered key's script invokes (`qmicli` / `mbimcli`). */
|
|
63
|
+
export declare function fccUnlockRuntimeBinary(key: string): 'qmicli' | 'mbimcli' | undefined;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// The FCC-unlock COVERAGE CATALOG — which `<vid>:<pid>` ModemManager can unlock.
|
|
2
|
+
//
|
|
3
|
+
// This is the evidence source for the `fcc-auto-unlock` capability module.
|
|
4
|
+
// `capability/detect.ts` answers `unknown` for that module on purpose and says why:
|
|
5
|
+
// FCC unlock is carried out by a ModemManager DISPATCHER keyed on the device, and
|
|
6
|
+
// nothing on the modem's own D-Bus surface says whether a procedure applies. So the
|
|
7
|
+
// answer has to come from a catalog, and this is it.
|
|
8
|
+
//
|
|
9
|
+
// Pinned to ModemManager 1.24.2 (`packaging/upstream-pins.yaml`) — the exact release
|
|
10
|
+
// this repository rebuilds. Prose walkthrough, per-device fleet verdicts and the
|
|
11
|
+
// market table: `docs/FCC-UNLOCK-COVERAGE.md`.
|
|
12
|
+
//
|
|
13
|
+
// THE KEY IS `<vid>:<pid>` AND NOTHING ELSE. `mm-dispatcher-fcc-unlock.c` builds
|
|
14
|
+
// exactly one filename — `g_strdup_printf("%04x:%04x", vid, pid)` — and looks for it
|
|
15
|
+
// in the two enabled tiers. A vendor-only name is never opened by the dispatcher; it
|
|
16
|
+
// only ever exists as the TARGET of a `<vid>:<pid>` link in the available tier. And a
|
|
17
|
+
// vendor-keyed rule would be wrong twice over: Sierra silicon ships under three
|
|
18
|
+
// vendor ids (`1199` its own, `03f0` HP-branded, `413c` Dell-branded), so keying on
|
|
19
|
+
// the vendor misses two of the three, while keying on the model misses the rebrands.
|
|
20
|
+
/** The four vendor scripts ModemManager 1.24.2 ships, and what each one drives. */
|
|
21
|
+
export const MM_FCC_UNLOCK_VENDOR_SCRIPTS = {
|
|
22
|
+
'105b': 'mbimcli',
|
|
23
|
+
'1199': 'qmicli',
|
|
24
|
+
'14c3': 'mbimcli',
|
|
25
|
+
'2c7c': 'qmicli',
|
|
26
|
+
};
|
|
27
|
+
/** The interpreters those scripts invoke, and the packages that provide them. */
|
|
28
|
+
export const MM_FCC_UNLOCK_RUNTIME_PACKAGES = {
|
|
29
|
+
qmicli: 'libqmi-utils',
|
|
30
|
+
mbimcli: 'libmbim-utils',
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* ModemManager 1.24.2's COMPLETE shipped mapping — `data/dispatcher-fcc-unlock/
|
|
34
|
+
* meson.build`'s `vidpids` dict, verbatim. Fourteen entries; there are no others.
|
|
35
|
+
*/
|
|
36
|
+
export const MM_FCC_UNLOCK_COVERAGE = {
|
|
37
|
+
'03f0:4e1d': '1199',
|
|
38
|
+
'105b:e0ab': '105b',
|
|
39
|
+
'105b:e0c3': '105b',
|
|
40
|
+
'1199:9079': '1199',
|
|
41
|
+
'14c3:4d75': '14c3',
|
|
42
|
+
'1eac:1001': '2c7c',
|
|
43
|
+
'1eac:1004': '2c7c',
|
|
44
|
+
'1eac:1007': '2c7c',
|
|
45
|
+
'2c7c:030a': '2c7c',
|
|
46
|
+
'2c7c:0313': '2c7c',
|
|
47
|
+
'2c7c:0314': '2c7c',
|
|
48
|
+
'2c7c:0801': '2c7c',
|
|
49
|
+
'413c:81a3': '1199',
|
|
50
|
+
'413c:81a8': '1199',
|
|
51
|
+
};
|
|
52
|
+
/** `<4 lowercase hex>:<4 lowercase hex>` — the dispatcher's own filename shape. */
|
|
53
|
+
const VID_PID_RE = /^[0-9a-f]{4}:[0-9a-f]{4}$/;
|
|
54
|
+
/**
|
|
55
|
+
* Fold a vid/pid pair into the dispatcher's key, or `undefined` when it is not a
|
|
56
|
+
* pair of 4-hex ids. Case is folded because sysfs and udev disagree about it
|
|
57
|
+
* (`ID_VENDOR_ID` is lowercase, some vendor strings are not) while the dispatcher's
|
|
58
|
+
* `%04x` is unambiguously lowercase; a `0x` prefix is tolerated for the same reason.
|
|
59
|
+
* NOTHING ELSE is normalized — a 3-digit or 5-digit id is a different device, not a
|
|
60
|
+
* sloppy spelling of this one.
|
|
61
|
+
*/
|
|
62
|
+
export function normalizeVidPid(vid, pid) {
|
|
63
|
+
const fold = (raw) => raw.trim().toLowerCase().replace(/^0x/, '');
|
|
64
|
+
const key = `${fold(vid)}:${fold(pid)}`;
|
|
65
|
+
return VID_PID_RE.test(key) ? key : undefined;
|
|
66
|
+
}
|
|
67
|
+
/** True for a string already in the dispatcher's `<vid>:<pid>` shape. */
|
|
68
|
+
export function isFccUnlockKey(value) {
|
|
69
|
+
return VID_PID_RE.test(value);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Does ModemManager ship an unlock procedure for this device?
|
|
73
|
+
*
|
|
74
|
+
* The three answers are NOT interchangeable, and the third is why this returns a
|
|
75
|
+
* tri-state rather than a boolean:
|
|
76
|
+
* present — a `<vid>:<pid>` entry exists; the toggle can do something.
|
|
77
|
+
* absent — the ids are well-formed and are NOT in the mapping. A positive
|
|
78
|
+
* statement about the device, so the module reads `unavailable` and no
|
|
79
|
+
* control is offered.
|
|
80
|
+
* unknown — we could not read the ids at all. That is a statement about the READ,
|
|
81
|
+
* and reporting it as `absent` would hide the module on hardware that
|
|
82
|
+
* may well be covered.
|
|
83
|
+
*/
|
|
84
|
+
export function resolveFccUnlockCoverage(vid, pid) {
|
|
85
|
+
if (vid === undefined || pid === undefined) {
|
|
86
|
+
return 'unknown';
|
|
87
|
+
}
|
|
88
|
+
const key = normalizeVidPid(vid, pid);
|
|
89
|
+
if (key === undefined) {
|
|
90
|
+
return 'unknown';
|
|
91
|
+
}
|
|
92
|
+
return key in MM_FCC_UNLOCK_COVERAGE ? 'present' : 'absent';
|
|
93
|
+
}
|
|
94
|
+
/** The vendor script a covered key resolves to, for diagnostics and docs. */
|
|
95
|
+
export function fccUnlockVendorScript(key) {
|
|
96
|
+
return MM_FCC_UNLOCK_COVERAGE[key];
|
|
97
|
+
}
|
|
98
|
+
/** The interpreter a covered key's script invokes (`qmicli` / `mbimcli`). */
|
|
99
|
+
export function fccUnlockRuntimeBinary(key) {
|
|
100
|
+
const script = fccUnlockVendorScript(key);
|
|
101
|
+
return script === undefined ? undefined : MM_FCC_UNLOCK_VENDOR_SCRIPTS[script];
|
|
102
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// FCC auto-unlock — the opt-in POLICY surface, and the catalog that gates it.
|
|
2
|
+
//
|
|
3
|
+
// This module implements NO unlock procedure and ships NO unlock script. All it does
|
|
4
|
+
// is record which `<vid>:<pid>` models an operator has opted in for, so that
|
|
5
|
+
// `ceralive-fcc-reconcile` can re-derive ModemManager's own admin-tier symlinks from
|
|
6
|
+
// that record on every boot. The unlocking itself is ModemManager's dispatcher's job,
|
|
7
|
+
// start to finish.
|
|
8
|
+
//
|
|
9
|
+
// Full model, coverage matrix and certification status: `docs/FCC-UNLOCK-COVERAGE.md`.
|
|
10
|
+
export * from './coverage.js';
|
|
11
|
+
export * from './policy-store.js';
|
|
12
|
+
export * from './policy-write.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** The current on-disk schema version. Bump when the persisted shape changes. */
|
|
2
|
+
export declare const FCC_UNLOCK_SCHEMA_VERSION = 1;
|
|
3
|
+
/** The pinned location of the policy of record. `/data` survives a slot swap. */
|
|
4
|
+
export declare const FCC_UNLOCK_POLICY_PATH = "/data/ceralive/fcc-unlock-policy.json";
|
|
5
|
+
/**
|
|
6
|
+
* The persisted document.
|
|
7
|
+
*
|
|
8
|
+
* `unlock` is a TOTAL map from `<vid>:<pid>` to the operator's answer. An absent key
|
|
9
|
+
* and an explicit `false` are the same fact (not opted in) and both are legal on
|
|
10
|
+
* disk: a `false` is what an opt-OUT leaves behind, and keeping it is what lets the
|
|
11
|
+
* shell reconciler prove it parsed a real answer rather than an empty document.
|
|
12
|
+
*/
|
|
13
|
+
export interface PersistedFccUnlockPolicy {
|
|
14
|
+
readonly schemaVersion: typeof FCC_UNLOCK_SCHEMA_VERSION;
|
|
15
|
+
readonly savedAtMs: number;
|
|
16
|
+
readonly unlock: Readonly<Record<string, boolean>>;
|
|
17
|
+
}
|
|
18
|
+
/** A metadata-only log event. Corruption NEVER carries the raw file content. */
|
|
19
|
+
export type FccUnlockLogEvent = {
|
|
20
|
+
readonly kind: 'corrupt-policy';
|
|
21
|
+
readonly bytes: number;
|
|
22
|
+
readonly reason: string;
|
|
23
|
+
};
|
|
24
|
+
export type FccUnlockLogger = (event: FccUnlockLogEvent) => void;
|
|
25
|
+
/** The persistence seam `setFccUnlockPolicy` drives. */
|
|
26
|
+
export interface FccUnlockPolicyStore {
|
|
27
|
+
/** Load persisted policy; an absent or unreadable file loads as EMPTY. */
|
|
28
|
+
load(nowMs: number): Promise<PersistedFccUnlockPolicy>;
|
|
29
|
+
/** Atomically write policy with mode 0600 (temp → chmod → rename). */
|
|
30
|
+
save(state: PersistedFccUnlockPolicy): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export interface FccUnlockPolicyFileStoreOptions {
|
|
33
|
+
readonly path?: string;
|
|
34
|
+
readonly logger?: FccUnlockLogger;
|
|
35
|
+
}
|
|
36
|
+
/** The `<vid>:<pid>` models the policy positively enables. Sorted, for stability. */
|
|
37
|
+
export declare function enabledFccUnlockKeys(state: PersistedFccUnlockPolicy): string[];
|
|
38
|
+
/** One model's answer. An unmentioned model is NOT enabled — absence is not consent. */
|
|
39
|
+
export declare function isFccUnlockEnabled(state: PersistedFccUnlockPolicy, key: string): boolean;
|
|
40
|
+
export declare function createFccUnlockPolicyFileStore(options?: FccUnlockPolicyFileStoreOptions): FccUnlockPolicyStore;
|