@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,57 @@
|
|
|
1
|
+
import { type EquipmentId, type IdentityConfidence, type ModemIdentity } from '../domain/index.js';
|
|
2
|
+
import { type DecodedManagedObjects } from './managed-objects.js';
|
|
3
|
+
/** Which rung of the ladder produced the stable key. */
|
|
4
|
+
export type SlotSource = 'device-slot-uid' | 'physdev' | 'sysfs-walk' | 'equipment-fallback';
|
|
5
|
+
/** The prefix OUR udev rules use to label a slot in `Modem.Device`. */
|
|
6
|
+
export declare const SLOT_UID_PREFIX = "slot-";
|
|
7
|
+
/** The raw facts the ladder resolves from — one modem's observed identity inputs. */
|
|
8
|
+
export interface ModemIdentityFacts {
|
|
9
|
+
/** The live MM object path (becomes `runtimePath`; never a durable key). */
|
|
10
|
+
readonly runtimePath: string;
|
|
11
|
+
/** `Modem.Device` — a `slot-*` UID (ours) or MM's path-shaped default. */
|
|
12
|
+
readonly device?: string;
|
|
13
|
+
/** `Modem.Physdev` — physical topology path (1.22+; absent on 1.20). */
|
|
14
|
+
readonly physdev?: string;
|
|
15
|
+
/** The modem's port device names (e.g. `ttyUSB0`, `wwan0`) for the sysfs walk. */
|
|
16
|
+
readonly ports?: readonly string[];
|
|
17
|
+
/** IMEI/serial equipment id with its own confidence (A2.1). */
|
|
18
|
+
readonly equipmentId: EquipmentId;
|
|
19
|
+
}
|
|
20
|
+
/** The ladder's output: a resolved identity plus how (and how firmly) we got it. */
|
|
21
|
+
export interface ResolvedIdentity {
|
|
22
|
+
/** The four-part identity; `logicalSlotId` is set for rungs 1-3 only. */
|
|
23
|
+
readonly identity: ModemIdentity;
|
|
24
|
+
/** Which rung produced the result. */
|
|
25
|
+
readonly slotSource: SlotSource;
|
|
26
|
+
/** Confidence in the SLOT resolution (rung 4 is always `low`). */
|
|
27
|
+
readonly confidence: IdentityConfidence;
|
|
28
|
+
/** The durable row key — stable across replug for rungs 1-3 (and unique-IMEI rung 4). */
|
|
29
|
+
readonly stableKey: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether a `Modem.Device` value is one of OUR slot UIDs (shaped `slot-*`) rather
|
|
33
|
+
* than MM's path-shaped default. This is the documented Phase-A heuristic that
|
|
34
|
+
* keeps a hand-labelled slot preferred over a `/sys/devices/...` path.
|
|
35
|
+
*/
|
|
36
|
+
export declare function looksLikeSlotUid(device: string | undefined): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Resolve ONE modem's stable identity by walking the ladder. Pure — no I/O.
|
|
39
|
+
*
|
|
40
|
+
* Rungs 1-3 yield a `logicalSlotId` and a stable key that survives replug into the
|
|
41
|
+
* same slot. Rung 4 (equipment fallback) yields NO slot and `confidence: 'low'`,
|
|
42
|
+
* so a durable policy bound via `policyBindingKey` is refused for an ambiguous
|
|
43
|
+
* (duplicate/zero) equipment id.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveModemIdentity(facts: ModemIdentityFacts): ResolvedIdentity;
|
|
46
|
+
/**
|
|
47
|
+
* Resolve a batch of modems, demoting any equipment id that appears on more than
|
|
48
|
+
* one modem to LOW confidence FIRST (cross-modem duplicate detection A2.1 cannot do
|
|
49
|
+
* from a single value). A duplicate IMEI thus reaches rung 4 with a low-confidence
|
|
50
|
+
* equipment id, and `canBindPolicy` refuses durable binding on it.
|
|
51
|
+
*/
|
|
52
|
+
export declare function resolveModemIdentities(factsList: readonly ModemIdentityFacts[]): ResolvedIdentity[];
|
|
53
|
+
/**
|
|
54
|
+
* Extract one modem's `ModemIdentityFacts` from a decoded `GetManagedObjects` tree —
|
|
55
|
+
* the bridge real backends use to feed the ladder from an observed snapshot.
|
|
56
|
+
*/
|
|
57
|
+
export declare function modemIdentityFactsFromTree(tree: DecodedManagedObjects, modemPath: string): ModemIdentityFacts;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// The identity ladder — resolving a STABLE slot handle for a live modem.
|
|
2
|
+
//
|
|
3
|
+
// A modem's D-Bus object path (`/org/freedesktop/ModemManager1/Modem/3`) is a
|
|
4
|
+
// per-boot, per-plug value: it changes on replug and daemon restart, so it can
|
|
5
|
+
// never be the durable key. The ladder derives a stable key by trying, in order:
|
|
6
|
+
//
|
|
7
|
+
// 1. slot-UID in `Modem.Device` — when OUR udev rules label the slot they set
|
|
8
|
+
// `Device` to a `slot-*` UID (e.g. `slot-usb2-1`). That is stable and ours,
|
|
9
|
+
// distinguishable from MM's own path-shaped default (`/sys/devices/...`).
|
|
10
|
+
// 2. `Modem.Physdev` (1.22+) — the physical USB topology path. Stable across
|
|
11
|
+
// replug into the same port; used when no slot-UID is present.
|
|
12
|
+
// 3. a ports-derived sysfs walk — a deterministic key from the modem's port
|
|
13
|
+
// list when neither of the above is available (MM 1.20, no udev rule yet).
|
|
14
|
+
// 4. equipment-id fallback — LOW confidence. Per A2.1's ambiguity rules a
|
|
15
|
+
// low-confidence identity must never bind durable policy, so this rung sets
|
|
16
|
+
// `confidence: 'low'` and `canBindPolicy` refuses on an ambiguous equipment id.
|
|
17
|
+
//
|
|
18
|
+
// Phase A note: no image-pipeline udev rules ship yet, so on the bench `Device`
|
|
19
|
+
// is usually MM's path-shaped default and the ladder lands on Physdev / sysfs.
|
|
20
|
+
// The `slot-*` heuristic is documented here so a bench operator can label a slot
|
|
21
|
+
// by hand and see rung 1 fire.
|
|
22
|
+
import { demoteToLowConfidence, imeiEquipmentId, logicalSlotId, runtimePath, } from '../domain/index.js';
|
|
23
|
+
import { MODEM_IFACE, MODEM3GPP_IFACE } from './constants.js';
|
|
24
|
+
import { findInterface, propValue, stringProp, } from './managed-objects.js';
|
|
25
|
+
/** The prefix OUR udev rules use to label a slot in `Modem.Device`. */
|
|
26
|
+
export const SLOT_UID_PREFIX = 'slot-';
|
|
27
|
+
/**
|
|
28
|
+
* Whether a `Modem.Device` value is one of OUR slot UIDs (shaped `slot-*`) rather
|
|
29
|
+
* than MM's path-shaped default. This is the documented Phase-A heuristic that
|
|
30
|
+
* keeps a hand-labelled slot preferred over a `/sys/devices/...` path.
|
|
31
|
+
*/
|
|
32
|
+
export function looksLikeSlotUid(device) {
|
|
33
|
+
if (device === undefined) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return device.startsWith(SLOT_UID_PREFIX) && device.length > SLOT_UID_PREFIX.length;
|
|
37
|
+
}
|
|
38
|
+
/** Derive a deterministic key from a modem's port list (sorted, stable across replug). */
|
|
39
|
+
function sysfsWalkKey(ports) {
|
|
40
|
+
const named = ports.map((p) => p.trim()).filter((p) => p.length > 0);
|
|
41
|
+
if (named.length === 0) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return [...named].sort().join('+');
|
|
45
|
+
}
|
|
46
|
+
function buildIdentity(facts, slot) {
|
|
47
|
+
return {
|
|
48
|
+
equipmentId: facts.equipmentId,
|
|
49
|
+
runtimePath: runtimePath(facts.runtimePath),
|
|
50
|
+
...(slot !== undefined ? { logicalSlotId: slot } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Resolve ONE modem's stable identity by walking the ladder. Pure — no I/O.
|
|
55
|
+
*
|
|
56
|
+
* Rungs 1-3 yield a `logicalSlotId` and a stable key that survives replug into the
|
|
57
|
+
* same slot. Rung 4 (equipment fallback) yields NO slot and `confidence: 'low'`,
|
|
58
|
+
* so a durable policy bound via `policyBindingKey` is refused for an ambiguous
|
|
59
|
+
* (duplicate/zero) equipment id.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveModemIdentity(facts) {
|
|
62
|
+
// Rung 1 — our slot-UID in `Device`.
|
|
63
|
+
if (looksLikeSlotUid(facts.device)) {
|
|
64
|
+
const device = facts.device;
|
|
65
|
+
const slot = logicalSlotId(device);
|
|
66
|
+
return {
|
|
67
|
+
identity: buildIdentity(facts, slot),
|
|
68
|
+
slotSource: 'device-slot-uid',
|
|
69
|
+
confidence: 'high',
|
|
70
|
+
stableKey: `slot:${device}`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Rung 2 — `Physdev` physical topology path (1.22+).
|
|
74
|
+
const physdev = facts.physdev?.trim();
|
|
75
|
+
if (physdev !== undefined && physdev.length > 0) {
|
|
76
|
+
const slot = logicalSlotId(`physdev:${physdev}`);
|
|
77
|
+
return {
|
|
78
|
+
identity: buildIdentity(facts, slot),
|
|
79
|
+
slotSource: 'physdev',
|
|
80
|
+
confidence: 'high',
|
|
81
|
+
stableKey: `physdev:${physdev}`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Rung 3 — ports-derived sysfs walk.
|
|
85
|
+
const walk = facts.ports !== undefined ? sysfsWalkKey(facts.ports) : undefined;
|
|
86
|
+
if (walk !== undefined) {
|
|
87
|
+
const slot = logicalSlotId(`sysfs:${walk}`);
|
|
88
|
+
return {
|
|
89
|
+
identity: buildIdentity(facts, slot),
|
|
90
|
+
slotSource: 'sysfs-walk',
|
|
91
|
+
confidence: 'medium',
|
|
92
|
+
stableKey: `sysfs:${walk}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Rung 4 — equipment fallback, LOW confidence, no durable slot.
|
|
96
|
+
const equip = facts.equipmentId;
|
|
97
|
+
const stableKey = equip.provenance !== 'none' && equip.value.trim().length > 0
|
|
98
|
+
? `equip:${equip.value}`
|
|
99
|
+
: `path:${facts.runtimePath}`;
|
|
100
|
+
return {
|
|
101
|
+
identity: buildIdentity(facts, undefined),
|
|
102
|
+
slotSource: 'equipment-fallback',
|
|
103
|
+
confidence: 'low',
|
|
104
|
+
stableKey,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Resolve a batch of modems, demoting any equipment id that appears on more than
|
|
109
|
+
* one modem to LOW confidence FIRST (cross-modem duplicate detection A2.1 cannot do
|
|
110
|
+
* from a single value). A duplicate IMEI thus reaches rung 4 with a low-confidence
|
|
111
|
+
* equipment id, and `canBindPolicy` refuses durable binding on it.
|
|
112
|
+
*/
|
|
113
|
+
export function resolveModemIdentities(factsList) {
|
|
114
|
+
const counts = new Map();
|
|
115
|
+
for (const facts of factsList) {
|
|
116
|
+
const { equipmentId } = facts;
|
|
117
|
+
if (equipmentId.provenance !== 'none' && equipmentId.value.trim().length > 0) {
|
|
118
|
+
counts.set(equipmentId.value, (counts.get(equipmentId.value) ?? 0) + 1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return factsList.map((facts) => {
|
|
122
|
+
const { equipmentId } = facts;
|
|
123
|
+
const duplicated = equipmentId.provenance !== 'none' && (counts.get(equipmentId.value) ?? 0) > 1;
|
|
124
|
+
const resolvedFacts = duplicated
|
|
125
|
+
? { ...facts, equipmentId: demoteToLowConfidence(equipmentId) }
|
|
126
|
+
: facts;
|
|
127
|
+
return resolveModemIdentity(resolvedFacts);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/** MM `Modem.Ports` is `a(su)`: entries of `[portName, portType]`. */
|
|
131
|
+
function portNames(value) {
|
|
132
|
+
if (!Array.isArray(value)) {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
const names = value
|
|
136
|
+
.map((entry) => (Array.isArray(entry) ? entry[0] : undefined))
|
|
137
|
+
.filter((name) => typeof name === 'string');
|
|
138
|
+
return names.length > 0 ? names : undefined;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Extract one modem's `ModemIdentityFacts` from a decoded `GetManagedObjects` tree —
|
|
142
|
+
* the bridge real backends use to feed the ladder from an observed snapshot.
|
|
143
|
+
*/
|
|
144
|
+
export function modemIdentityFactsFromTree(tree, modemPath) {
|
|
145
|
+
const modem = findInterface(tree, modemPath, MODEM_IFACE);
|
|
146
|
+
const modem3gpp = findInterface(tree, modemPath, MODEM3GPP_IFACE);
|
|
147
|
+
const equipment = stringProp(modem, 'EquipmentIdentifier') ?? stringProp(modem3gpp, 'Imei') ?? '';
|
|
148
|
+
const device = stringProp(modem, 'Device');
|
|
149
|
+
const physdev = stringProp(modem, 'Physdev');
|
|
150
|
+
const ports = portNames(propValue(modem, 'Ports'));
|
|
151
|
+
return {
|
|
152
|
+
runtimePath: modemPath,
|
|
153
|
+
equipmentId: imeiEquipmentId(equipment),
|
|
154
|
+
...(device !== undefined ? { device } : {}),
|
|
155
|
+
...(physdev !== undefined ? { physdev } : {}),
|
|
156
|
+
...(ports !== undefined ? { ports } : {}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { EquipmentId, LogicalSlotId, RuntimePath } from '../domain/index.js';
|
|
2
|
+
import type { ResolvedIdentity } from './identity-ladder.js';
|
|
3
|
+
/** One durable logical row, keyed by the ladder's stable identifier. */
|
|
4
|
+
export interface IdentityRow {
|
|
5
|
+
/** The stable durable key (`slot:…` / `physdev:…` / `sysfs:…` / `equip:…`). */
|
|
6
|
+
readonly stableKey: string;
|
|
7
|
+
/** The resolved slot, when the row was slot-resolved (rungs 1-3). */
|
|
8
|
+
readonly logicalSlotId?: LogicalSlotId;
|
|
9
|
+
/** The equipment currently occupying this slot. */
|
|
10
|
+
readonly equipmentId: EquipmentId;
|
|
11
|
+
/** The live MM path — updated on every replug (never a durable key). */
|
|
12
|
+
readonly runtimePath: RuntimePath;
|
|
13
|
+
}
|
|
14
|
+
/** A transition the registry detected while applying a resolved identity. */
|
|
15
|
+
export type IdentityTransition = {
|
|
16
|
+
readonly kind: 'attached';
|
|
17
|
+
readonly row: IdentityRow;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'replugged';
|
|
20
|
+
readonly row: IdentityRow;
|
|
21
|
+
readonly previousPath: RuntimePath;
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: 'equipment-swapped-in-slot';
|
|
24
|
+
readonly row: IdentityRow;
|
|
25
|
+
readonly previousEquipment: EquipmentId;
|
|
26
|
+
} | {
|
|
27
|
+
readonly kind: 'equipment-moved';
|
|
28
|
+
readonly row: IdentityRow;
|
|
29
|
+
readonly previousKey: string;
|
|
30
|
+
readonly previousSlot?: LogicalSlotId;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Tracks logical modem rows across replug/swap/move. Stateful by design — it holds
|
|
34
|
+
* the last-known row per stable key. `apply()` folds one resolved identity in and
|
|
35
|
+
* reports the transition it produced.
|
|
36
|
+
*/
|
|
37
|
+
export declare class IdentityRegistry {
|
|
38
|
+
#private;
|
|
39
|
+
/** A snapshot of the current logical rows, in insertion order. */
|
|
40
|
+
get rows(): IdentityRow[];
|
|
41
|
+
/** The row for a stable key, or `undefined`. */
|
|
42
|
+
get(stableKey: string): IdentityRow | undefined;
|
|
43
|
+
/** Drop a row (e.g. after a current-epoch removal). */
|
|
44
|
+
remove(stableKey: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Fold one resolved identity into the registry and report the transition.
|
|
47
|
+
* Keeps ONE row per stable key: a replug into the same slot updates the live
|
|
48
|
+
* path in place rather than adding a duplicate.
|
|
49
|
+
*/
|
|
50
|
+
apply(resolved: ResolvedIdentity): IdentityTransition;
|
|
51
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// The identity registry — ONE logical row per physical slot, across replugs.
|
|
2
|
+
//
|
|
3
|
+
// The epoch observer (A3.1) keys rows by the MM object path, which CHANGES on
|
|
4
|
+
// replug and daemon restart. This registry sits above it and keys rows by the
|
|
5
|
+
// STABLE identifier the ladder resolves (slot-UID / Physdev / sysfs / unique
|
|
6
|
+
// equipment id), so a modem that disconnects and reconnects to the SAME slot
|
|
7
|
+
// resolves to the SAME logical row instead of a duplicate.
|
|
8
|
+
//
|
|
9
|
+
// It also names the transitions the ladder can observe:
|
|
10
|
+
//
|
|
11
|
+
// - `attached` — a stable key we have not seen before.
|
|
12
|
+
// - `replugged` — same stable key, same equipment: one row, new path.
|
|
13
|
+
// - `equipment-swapped-in-slot` — same slot, DIFFERENT equipment. The slot keeps
|
|
14
|
+
// its policy (slot-inherits-policy): unplug modem A,
|
|
15
|
+
// plug modem B into the same slot, B adopts A's
|
|
16
|
+
// slot-bound policy.
|
|
17
|
+
// - `equipment-moved` — same equipment, DIFFERENT slot: the modem was
|
|
18
|
+
// physically moved to another port.
|
|
19
|
+
const equipmentValue = (equipment) => equipment.provenance !== 'none' && equipment.value.trim().length > 0
|
|
20
|
+
? equipment.value
|
|
21
|
+
: undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Tracks logical modem rows across replug/swap/move. Stateful by design — it holds
|
|
24
|
+
* the last-known row per stable key. `apply()` folds one resolved identity in and
|
|
25
|
+
* reports the transition it produced.
|
|
26
|
+
*/
|
|
27
|
+
export class IdentityRegistry {
|
|
28
|
+
#rows = new Map();
|
|
29
|
+
/** A snapshot of the current logical rows, in insertion order. */
|
|
30
|
+
get rows() {
|
|
31
|
+
return [...this.#rows.values()];
|
|
32
|
+
}
|
|
33
|
+
/** The row for a stable key, or `undefined`. */
|
|
34
|
+
get(stableKey) {
|
|
35
|
+
return this.#rows.get(stableKey);
|
|
36
|
+
}
|
|
37
|
+
/** Drop a row (e.g. after a current-epoch removal). */
|
|
38
|
+
remove(stableKey) {
|
|
39
|
+
this.#rows.delete(stableKey);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Fold one resolved identity into the registry and report the transition.
|
|
43
|
+
* Keeps ONE row per stable key: a replug into the same slot updates the live
|
|
44
|
+
* path in place rather than adding a duplicate.
|
|
45
|
+
*/
|
|
46
|
+
apply(resolved) {
|
|
47
|
+
const row = this.#rowFrom(resolved);
|
|
48
|
+
const existing = this.#rows.get(row.stableKey);
|
|
49
|
+
if (existing !== undefined) {
|
|
50
|
+
return this.#applyToExisting(existing, resolved, row);
|
|
51
|
+
}
|
|
52
|
+
// A unique equipment id at a NEW stable key that already lives elsewhere
|
|
53
|
+
// means the modem physically moved to a different slot/port.
|
|
54
|
+
const moved = this.#findByEquipment(row.equipmentId, row.stableKey);
|
|
55
|
+
if (moved !== undefined) {
|
|
56
|
+
this.#rows.delete(moved.stableKey);
|
|
57
|
+
this.#rows.set(row.stableKey, row);
|
|
58
|
+
return {
|
|
59
|
+
kind: 'equipment-moved',
|
|
60
|
+
row,
|
|
61
|
+
previousKey: moved.stableKey,
|
|
62
|
+
...(moved.logicalSlotId !== undefined ? { previousSlot: moved.logicalSlotId } : {}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
this.#rows.set(row.stableKey, row);
|
|
66
|
+
return { kind: 'attached', row };
|
|
67
|
+
}
|
|
68
|
+
#applyToExisting(existing, resolved, row) {
|
|
69
|
+
const before = equipmentValue(existing.equipmentId);
|
|
70
|
+
const after = equipmentValue(resolved.identity.equipmentId);
|
|
71
|
+
if (before !== undefined && after !== undefined && before !== after) {
|
|
72
|
+
// Same slot, different equipment — the slot keeps its policy binding.
|
|
73
|
+
this.#rows.set(row.stableKey, row);
|
|
74
|
+
return { kind: 'equipment-swapped-in-slot', row, previousEquipment: existing.equipmentId };
|
|
75
|
+
}
|
|
76
|
+
// Same slot, same (or unchanged) equipment — a replug: one row, new path.
|
|
77
|
+
this.#rows.set(row.stableKey, row);
|
|
78
|
+
return { kind: 'replugged', row, previousPath: existing.runtimePath };
|
|
79
|
+
}
|
|
80
|
+
#rowFrom(resolved) {
|
|
81
|
+
const { identity, stableKey } = resolved;
|
|
82
|
+
return {
|
|
83
|
+
stableKey,
|
|
84
|
+
equipmentId: identity.equipmentId,
|
|
85
|
+
runtimePath: identity.runtimePath,
|
|
86
|
+
...(identity.logicalSlotId !== undefined ? { logicalSlotId: identity.logicalSlotId } : {}),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
#findByEquipment(equipment, exceptKey) {
|
|
90
|
+
const value = equipmentValue(equipment);
|
|
91
|
+
if (value === undefined) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
for (const row of this.#rows.values()) {
|
|
95
|
+
if (row.stableKey !== exceptKey && equipmentValue(row.equipmentId) === value) {
|
|
96
|
+
return row;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export { AT_BASELINE_ALLOWLIST, type AtAuditEntry, type AtAuditSink, AtCommandLease, type AtCommandLeaseDeps, AtCommandNotAllowedError, type AtCommandSender, AtCommandTimeoutError, type AtResponse, computeAtAllowlist, } from './at-lease.js';
|
|
2
|
+
export { type CellInfoProvenance, type CellReading, compareServing, normalizeCellInfo, normalizeCellReading, selectServingCell, } from './cell-info.js';
|
|
3
|
+
export { MM_BUS_NAME, MM_MANAGER_IFACE, MM_ROOT_PATH, MODEM_IFACE, MODEM_LOCATION_IFACE, MODEM3GPP_IFACE, MODEM3GPP_USSD_IFACE, SIM_IFACE, } from './constants.js';
|
|
4
|
+
export { CELLULAR_USB_VENDOR_IDS, cellularEvidence, cellularVendorName, classifyDevice, classifyUsbNetDevice, type DeviceClass, type DeviceClassification, descriptorsMatch, detectUsbMode, modelLabel, publishesGenericIdentity, type UsbDeviceSnapshot, type UsbInterface, type UsbNetClass, type UsbNetClassification, unitDiscriminator, vendorLabel, } from './device-classifier.js';
|
|
5
|
+
export { buildEnrichment, type EsimInfo, type EsimStatus, type ModemEnrichment, readEsimInfo, readRevision, type SimType, } from './enrichment.js';
|
|
6
|
+
export { detectMmFeatures, detectModemFeatures, type MmFeatures, type MmPropertyProbe, type MmVersion, parseMmVersion, probeModemProperties, } from './features.js';
|
|
7
|
+
export { looksLikeSlotUid, type ModemIdentityFacts, modemIdentityFactsFromTree, type ResolvedIdentity, resolveModemIdentities, resolveModemIdentity, SLOT_UID_PREFIX, type SlotSource, } from './identity-ladder.js';
|
|
8
|
+
export { IdentityRegistry, type IdentityRow, type IdentityTransition, } from './identity-registry.js';
|
|
9
|
+
export { ALLOW_ALL_INTERLOCK, type InterlockDecision, type InterlockTarget, type LifecycleInterlock, } from './lifecycle-interlock.js';
|
|
10
|
+
export { asManagedObjects, type DecodedInterfaces, type DecodedManagedObjects, type DecodedObject, type DecodedProps, fetchManagedObjects, findInterface, findObject, followObjectPath, hasInterface, numberProp, objectPaths, pathsWithInterface, propValue, stringProp, } from './managed-objects.js';
|
|
11
|
+
export { createMmDbusBackend, MmDbusBackend, type MmDbusBackendOptions, } from './mm-backend.js';
|
|
12
|
+
export { decodeLocationSources, encodeLocationSources, MmLocation, type MmLocationDeps, } from './mm-location.js';
|
|
13
|
+
export { MmMutations, type MmMutationsDeps } from './mm-mutations.js';
|
|
14
|
+
export { ModemActor, NO_OP_QUIESCE, type QuiesceHook, type QuiesceLeaseHandle, type QuiesceTarget, } from './modem-actor.js';
|
|
15
|
+
export { AUTO_APN_ADVISORY, type AutoApnAdvisory, type AutoApnTransitionResult, autoApnCapableFromVersion, autoApnSupportedByVersion, classifyActivation, type ManualApn, parseNmVersion, probeAutoApnCapability, toAutoArgs, toManualArgs, } from './nm-auto-apn.js';
|
|
16
|
+
export { buildProfile, cliArg, createGsmArgs, flattenPairs, gsmFieldPairs, passwordFlags, patchPairs, } from './nm-gsm-fields.js';
|
|
17
|
+
export { NmcliNmPort, type NmcliNmPortOptions, } from './nmcli-nm-port.js';
|
|
18
|
+
export { type NmcliResult, type NmcliRunner, parseTerse, runNmcli, SpawnNmcliRunner, } from './nmcli-runner.js';
|
|
19
|
+
export { createMmDbusObserver, type EpochRefreshEvent, MmDbusObserver, type MmDbusObserverOptions, } from './observer.js';
|
|
20
|
+
export { NONE_POWER_CAPABILITY, NONE_POWER_HOOK, type PowerCapability, type PowerCapabilityKind, type PowerCycleContext, type PowerCycleResult, type PowerHook, type PreferredUsbMode, unsupportedPowerHook, } from './power-contract.js';
|
|
21
|
+
export { attributeFault, attributeSnapshot, type FaultAttribution, type FaultSymptoms, symptomsFromSnapshot, } from './recovery-attribution.js';
|
|
22
|
+
export { type BudgetDecision, beginAttempt, DEFAULT_RECOVERY_BUDGET, INITIAL_BUDGET_STATE, markRecovered, type RecoveryBudget, type RecoveryBudgetState, } from './recovery-budget.js';
|
|
23
|
+
export { DEFAULT_LADDER_CONFIG, LADDER_ORDER, RecoveryLadder, type RecoveryLadderConfig, type RecoveryLadderDeps, type RecoveryOutcome, type RecoveryOutcomeKind, type RecoveryRequest, type RecoveryRung, type RecoveryStepContext, type RecoveryStepGate, type RecoveryStepReport, type RecoverySteps, type StepOutcome, } from './recovery-ladder.js';
|
|
24
|
+
export { createRouterEthernetProbe, type RouterEthernetProbeDeps } from './router-ethernet.js';
|
|
25
|
+
export { DEFAULT_SIGNAL_INTERVAL_SECONDS, type SignalCadence, SignalSetupManager, type SignalSetupManagerOptions, } from './signal-setup.js';
|
|
26
|
+
export { sendSimPin, sendSimPuk } from './sim-unlock.js';
|
|
27
|
+
export { ALLOW_ALL_TRANSITION_INTERLOCK, checkTransitionPreconditions, type InterlockHold, type PreconditionResult, type TransitionInterlock, type TransitionReadiness, type UsbModeTransitionOutcome, type UsbModeTransitionRequest, } from './transition-preconditions.js';
|
|
28
|
+
export * from './usage/index.js';
|
|
29
|
+
export { createUsbEnumerator, enumerateUsbDevices, parseUdevDatabase, type UsbEnumerator, type UsbEnumeratorDeps, } from './usb-enumerator.js';
|
|
30
|
+
export { UsbModeTransition, type UsbModeTransitionDeps } from './usb-mode-transition.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Backend adapters — the concrete D-Bus implementations of the port contracts.
|
|
2
|
+
//
|
|
3
|
+
// A3.1 lands the epoch-scoped `MmDbusObserver` (the read side). A3.2 adds MM
|
|
4
|
+
// feature detection + the stable identity ladder. Later A3 waves add mutations +
|
|
5
|
+
// Signal.Setup (A3.3) and the recovery ladder (A3.4) here.
|
|
6
|
+
export { AT_BASELINE_ALLOWLIST, AtCommandLease, AtCommandNotAllowedError, AtCommandTimeoutError, computeAtAllowlist, } from './at-lease.js';
|
|
7
|
+
export { compareServing, normalizeCellInfo, normalizeCellReading, selectServingCell, } from './cell-info.js';
|
|
8
|
+
export { MM_BUS_NAME, MM_MANAGER_IFACE, MM_ROOT_PATH, MODEM_IFACE, MODEM_LOCATION_IFACE, MODEM3GPP_IFACE, MODEM3GPP_USSD_IFACE, SIM_IFACE, } from './constants.js';
|
|
9
|
+
export { CELLULAR_USB_VENDOR_IDS, cellularEvidence, cellularVendorName, classifyDevice, classifyUsbNetDevice, descriptorsMatch, detectUsbMode, modelLabel, publishesGenericIdentity, unitDiscriminator, vendorLabel, } from './device-classifier.js';
|
|
10
|
+
export { buildEnrichment, readEsimInfo, readRevision, } from './enrichment.js';
|
|
11
|
+
export { detectMmFeatures, detectModemFeatures, parseMmVersion, probeModemProperties, } from './features.js';
|
|
12
|
+
export { looksLikeSlotUid, modemIdentityFactsFromTree, resolveModemIdentities, resolveModemIdentity, SLOT_UID_PREFIX, } from './identity-ladder.js';
|
|
13
|
+
export { IdentityRegistry, } from './identity-registry.js';
|
|
14
|
+
export { ALLOW_ALL_INTERLOCK, } from './lifecycle-interlock.js';
|
|
15
|
+
export { asManagedObjects, fetchManagedObjects, findInterface, findObject, followObjectPath, hasInterface, numberProp, objectPaths, pathsWithInterface, propValue, stringProp, } from './managed-objects.js';
|
|
16
|
+
export { createMmDbusBackend, MmDbusBackend, } from './mm-backend.js';
|
|
17
|
+
export { decodeLocationSources, encodeLocationSources, MmLocation, } from './mm-location.js';
|
|
18
|
+
export { MmMutations } from './mm-mutations.js';
|
|
19
|
+
export { ModemActor, NO_OP_QUIESCE, } from './modem-actor.js';
|
|
20
|
+
export { AUTO_APN_ADVISORY, autoApnCapableFromVersion, autoApnSupportedByVersion, classifyActivation, parseNmVersion, probeAutoApnCapability, toAutoArgs, toManualArgs, } from './nm-auto-apn.js';
|
|
21
|
+
export { buildProfile, cliArg, createGsmArgs, flattenPairs, gsmFieldPairs, passwordFlags, patchPairs, } from './nm-gsm-fields.js';
|
|
22
|
+
export { NmcliNmPort, } from './nmcli-nm-port.js';
|
|
23
|
+
export { parseTerse, runNmcli, SpawnNmcliRunner, } from './nmcli-runner.js';
|
|
24
|
+
export { createMmDbusObserver, MmDbusObserver, } from './observer.js';
|
|
25
|
+
export { NONE_POWER_CAPABILITY, NONE_POWER_HOOK, unsupportedPowerHook, } from './power-contract.js';
|
|
26
|
+
export { attributeFault, attributeSnapshot, symptomsFromSnapshot, } from './recovery-attribution.js';
|
|
27
|
+
export { beginAttempt, DEFAULT_RECOVERY_BUDGET, INITIAL_BUDGET_STATE, markRecovered, } from './recovery-budget.js';
|
|
28
|
+
export { DEFAULT_LADDER_CONFIG, LADDER_ORDER, RecoveryLadder, } from './recovery-ladder.js';
|
|
29
|
+
export { createRouterEthernetProbe } from './router-ethernet.js';
|
|
30
|
+
export { DEFAULT_SIGNAL_INTERVAL_SECONDS, SignalSetupManager, } from './signal-setup.js';
|
|
31
|
+
export { sendSimPin, sendSimPuk } from './sim-unlock.js';
|
|
32
|
+
export { ALLOW_ALL_TRANSITION_INTERLOCK, checkTransitionPreconditions, } from './transition-preconditions.js';
|
|
33
|
+
export * from './usage/index.js';
|
|
34
|
+
export { createUsbEnumerator, enumerateUsbDevices, parseUdevDatabase, } from './usb-enumerator.js';
|
|
35
|
+
export { UsbModeTransition } from './usb-mode-transition.js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** What a disruptive step is about to act on — enough for an interlock to decide. */
|
|
2
|
+
export interface InterlockTarget {
|
|
3
|
+
readonly stableKey: string;
|
|
4
|
+
}
|
|
5
|
+
/** An interlock verdict. A denial ALWAYS carries a reason (why it is unsafe now). */
|
|
6
|
+
export type InterlockDecision = {
|
|
7
|
+
readonly allow: true;
|
|
8
|
+
} | {
|
|
9
|
+
readonly allow: false;
|
|
10
|
+
readonly reason: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The safety interlock consulted before each disruptive recovery step. Returning
|
|
14
|
+
* `{ allow: false, reason }` stops the ladder — the modem is left as-is rather than
|
|
15
|
+
* disrupted mid-stream.
|
|
16
|
+
*/
|
|
17
|
+
export interface LifecycleInterlock {
|
|
18
|
+
canDisrupt(target: InterlockTarget): Promise<InterlockDecision>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The Phase-A interlock: always allows. There is no streaming-admission signal in
|
|
22
|
+
* the CLI, so nothing to block against. Phase B replaces this instance with a
|
|
23
|
+
* real streaming-aware interlock; no ladder code changes.
|
|
24
|
+
*/
|
|
25
|
+
export declare const ALLOW_ALL_INTERLOCK: LifecycleInterlock;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// The pluggable safety interlock the recovery ladder consults before disruption.
|
|
2
|
+
//
|
|
3
|
+
// A disruptive recovery step (deactivate NM, disable MM, Reset(), power-cycle) must
|
|
4
|
+
// never fire while the modem is carrying a live stream. The ladder therefore asks a
|
|
5
|
+
// `LifecycleInterlock` BEFORE every disruptive step. Phase A (CLI) injects the
|
|
6
|
+
// always-allow stub below; Phase B wires CeraUI's real streaming-admission check
|
|
7
|
+
// into this SAME interface — the ladder code does not change, only the injected
|
|
8
|
+
// instance. A4.2's USB-mode transition reuses this exact interlock shape.
|
|
9
|
+
/**
|
|
10
|
+
* The Phase-A interlock: always allows. There is no streaming-admission signal in
|
|
11
|
+
* the CLI, so nothing to block against. Phase B replaces this instance with a
|
|
12
|
+
* real streaming-aware interlock; no ladder code changes.
|
|
13
|
+
*/
|
|
14
|
+
export const ALLOW_ALL_INTERLOCK = {
|
|
15
|
+
canDisrupt() {
|
|
16
|
+
return Promise.resolve({ allow: true });
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { DbusTransport, DbusValue, DbusVariant } from '../transport/index.js';
|
|
2
|
+
/** One interface's property entries: `[propertyName, variant][]`. */
|
|
3
|
+
export type DecodedProps = ReadonlyArray<readonly [string, DbusVariant]>;
|
|
4
|
+
/** One object's interfaces: `[interfaceName, props][]`. */
|
|
5
|
+
export type DecodedInterfaces = ReadonlyArray<readonly [string, DecodedProps]>;
|
|
6
|
+
/** One managed object: `[objectPath, interfaces]`. */
|
|
7
|
+
export type DecodedObject = readonly [string, DecodedInterfaces];
|
|
8
|
+
/** The whole `a{oa{sa{sv}}}` payload. */
|
|
9
|
+
export type DecodedManagedObjects = readonly DecodedObject[];
|
|
10
|
+
/** Treat a `GetManagedObjects` reply body value as the decoded tree. */
|
|
11
|
+
export declare function asManagedObjects(value: DbusValue | undefined): DecodedManagedObjects;
|
|
12
|
+
/** Call `ObjectManager.GetManagedObjects` on `destination` and decode the reply. */
|
|
13
|
+
export declare function fetchManagedObjects(transport: DbusTransport, destination: string): Promise<DecodedManagedObjects>;
|
|
14
|
+
/** Treat an `InterfacesAdded` body (`[path, interfaces]`) as one decoded object. */
|
|
15
|
+
export declare function asAddedObject(path: DbusValue, interfaces: DbusValue): DecodedObject;
|
|
16
|
+
/** Every object path in the tree, in wire order. */
|
|
17
|
+
export declare function objectPaths(tree: DecodedManagedObjects): string[];
|
|
18
|
+
/** The object at `path`, or `undefined`. */
|
|
19
|
+
export declare function findObject(tree: DecodedManagedObjects, path: string): DecodedObject | undefined;
|
|
20
|
+
/** The property entries of one interface on one object, or `undefined`. */
|
|
21
|
+
export declare function findInterface(tree: DecodedManagedObjects, path: string, iface: string): DecodedProps | undefined;
|
|
22
|
+
/** Object paths that carry a given interface. */
|
|
23
|
+
export declare function pathsWithInterface(tree: DecodedManagedObjects, iface: string): string[];
|
|
24
|
+
/** Whether an object exposes a given interface. */
|
|
25
|
+
export declare function hasInterface(tree: DecodedManagedObjects, path: string, iface: string): boolean;
|
|
26
|
+
/** The inner value of a property (a variant's `.value`), or `undefined`. */
|
|
27
|
+
export declare function propValue(props: DecodedProps | undefined, name: string): DbusValue | undefined;
|
|
28
|
+
/** A string-typed property, or `undefined` if absent / not a string. */
|
|
29
|
+
export declare function stringProp(props: DecodedProps | undefined, name: string): string | undefined;
|
|
30
|
+
/** A number-typed property, or `undefined` if absent / not a number. */
|
|
31
|
+
export declare function numberProp(props: DecodedProps | undefined, name: string): number | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* A string-array (`as`) property, or `undefined` if absent / not an array. An
|
|
34
|
+
* EMPTY array answers `[]` — the device saying "none", a different fact from an
|
|
35
|
+
* absent property. Non-string members are dropped, never coerced.
|
|
36
|
+
*/
|
|
37
|
+
export declare function stringArrayProp(props: DecodedProps | undefined, name: string): readonly string[] | undefined;
|
|
38
|
+
/** Resolve an object-path property (e.g. a modem's `Sim`) to that object's props. */
|
|
39
|
+
export declare function followObjectPath(tree: DecodedManagedObjects, props: DecodedProps | undefined, propName: string, iface: string): DecodedProps | undefined;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Walkers over a DECODED `GetManagedObjects` / `InterfacesAdded` tree.
|
|
2
|
+
//
|
|
3
|
+
// The transport decodes `a{oa{sa{sv}}}` into nested tuple arrays: a dict `a{sv}`
|
|
4
|
+
// becomes `[key, variant][]` and a variant becomes `{ signature, value }`. These
|
|
5
|
+
// accessors navigate that structure by object path and interface name. They live in
|
|
6
|
+
// `src` (not the A2.3 test fake's `tree.ts`) because the observer that ships must not
|
|
7
|
+
// import test-support — the published package would not contain it.
|
|
8
|
+
import { MM_ROOT_PATH, OBJECT_MANAGER_IFACE } from './constants.js';
|
|
9
|
+
/** Treat a `GetManagedObjects` reply body value as the decoded tree. */
|
|
10
|
+
export function asManagedObjects(value) {
|
|
11
|
+
if (!Array.isArray(value)) {
|
|
12
|
+
throw new TypeError('managed-objects payload is not an array');
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
/** Call `ObjectManager.GetManagedObjects` on `destination` and decode the reply. */
|
|
17
|
+
export async function fetchManagedObjects(transport, destination) {
|
|
18
|
+
const reply = await transport.callMethod({
|
|
19
|
+
destination,
|
|
20
|
+
path: MM_ROOT_PATH,
|
|
21
|
+
interface: OBJECT_MANAGER_IFACE,
|
|
22
|
+
member: 'GetManagedObjects',
|
|
23
|
+
});
|
|
24
|
+
return asManagedObjects(reply.body[0]);
|
|
25
|
+
}
|
|
26
|
+
/** Treat an `InterfacesAdded` body (`[path, interfaces]`) as one decoded object. */
|
|
27
|
+
export function asAddedObject(path, interfaces) {
|
|
28
|
+
if (typeof path !== 'string' || !Array.isArray(interfaces)) {
|
|
29
|
+
throw new TypeError('InterfacesAdded body is not [objectPath, interfaces]');
|
|
30
|
+
}
|
|
31
|
+
return [path, interfaces];
|
|
32
|
+
}
|
|
33
|
+
/** Every object path in the tree, in wire order. */
|
|
34
|
+
export function objectPaths(tree) {
|
|
35
|
+
return tree.map(([path]) => path);
|
|
36
|
+
}
|
|
37
|
+
/** The object at `path`, or `undefined`. */
|
|
38
|
+
export function findObject(tree, path) {
|
|
39
|
+
return tree.find(([objectPath]) => objectPath === path);
|
|
40
|
+
}
|
|
41
|
+
/** The property entries of one interface on one object, or `undefined`. */
|
|
42
|
+
export function findInterface(tree, path, iface) {
|
|
43
|
+
return findObject(tree, path)?.[1].find(([name]) => name === iface)?.[1];
|
|
44
|
+
}
|
|
45
|
+
/** Object paths that carry a given interface. */
|
|
46
|
+
export function pathsWithInterface(tree, iface) {
|
|
47
|
+
return tree
|
|
48
|
+
.filter(([, interfaces]) => interfaces.some(([name]) => name === iface))
|
|
49
|
+
.map(([path]) => path);
|
|
50
|
+
}
|
|
51
|
+
/** Whether an object exposes a given interface. */
|
|
52
|
+
export function hasInterface(tree, path, iface) {
|
|
53
|
+
return findInterface(tree, path, iface) !== undefined;
|
|
54
|
+
}
|
|
55
|
+
/** The inner value of a property (a variant's `.value`), or `undefined`. */
|
|
56
|
+
export function propValue(props, name) {
|
|
57
|
+
return props?.find(([key]) => key === name)?.[1]?.value;
|
|
58
|
+
}
|
|
59
|
+
/** A string-typed property, or `undefined` if absent / not a string. */
|
|
60
|
+
export function stringProp(props, name) {
|
|
61
|
+
const value = propValue(props, name);
|
|
62
|
+
return typeof value === 'string' ? value : undefined;
|
|
63
|
+
}
|
|
64
|
+
/** A number-typed property, or `undefined` if absent / not a number. */
|
|
65
|
+
export function numberProp(props, name) {
|
|
66
|
+
const value = propValue(props, name);
|
|
67
|
+
return typeof value === 'number' ? value : undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A string-array (`as`) property, or `undefined` if absent / not an array. An
|
|
71
|
+
* EMPTY array answers `[]` — the device saying "none", a different fact from an
|
|
72
|
+
* absent property. Non-string members are dropped, never coerced.
|
|
73
|
+
*/
|
|
74
|
+
export function stringArrayProp(props, name) {
|
|
75
|
+
const value = propValue(props, name);
|
|
76
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : undefined;
|
|
77
|
+
}
|
|
78
|
+
/** Resolve an object-path property (e.g. a modem's `Sim`) to that object's props. */
|
|
79
|
+
export function followObjectPath(tree, props, propName, iface) {
|
|
80
|
+
const target = propValue(props, propName);
|
|
81
|
+
return typeof target === 'string' ? findInterface(tree, target, iface) : undefined;
|
|
82
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CellularSnapshot } from '../domain/index.js';
|
|
2
|
+
import { type DecodedManagedObjects } from './managed-objects.js';
|
|
3
|
+
/** The dimensions of a mapped modem, WITHOUT a revision (the observer stamps that). */
|
|
4
|
+
export type MappedModem = Omit<CellularSnapshot, 'revision'>;
|
|
5
|
+
/** Map ONE modem object to its dimensions. The modem must expose `Modem`. */
|
|
6
|
+
export declare function mapModem(tree: DecodedManagedObjects, modemPath: string): MappedModem;
|
|
7
|
+
/** Every modem path in the tree (objects exposing the `Modem` interface), in order. */
|
|
8
|
+
export declare function modemPaths(tree: DecodedManagedObjects): string[];
|
|
9
|
+
/** A stable fingerprint of a mapped modem's meaningful dimensions (ignores revision
|
|
10
|
+
* and source health), used to suppress redundant revision bumps on identical reads. */
|
|
11
|
+
export declare function fingerprint(mapped: MappedModem): string;
|