memeloop 0.2.8 → 0.2.9
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/dist/{chunk-NVJCRIEK.js → chunk-34B7MUI6.js} +2 -2
- package/dist/{chunk-DACM5AMS.js → chunk-7W4FMKMO.js} +190 -56
- package/dist/chunk-7W4FMKMO.js.map +1 -0
- package/dist/{chunk-OD6U6VAR.js → chunk-GH5RDPLJ.js} +2 -2
- package/dist/{chunk-OD6U6VAR.js.map → chunk-GH5RDPLJ.js.map} +1 -1
- package/dist/device-network/cloudDeviceFetchClient.d.ts +9 -7
- package/dist/device-network/cloudDeviceFetchClient.d.ts.map +1 -1
- package/dist/device-network/deviceCloudConnectionCoordinator.d.ts +5 -5
- package/dist/device-network/deviceCloudConnectionCoordinator.d.ts.map +1 -1
- package/dist/device-network/deviceOrchestrationTransport.d.ts +7 -0
- package/dist/device-network/deviceOrchestrationTransport.d.ts.map +1 -1
- package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts +16 -8
- package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts.map +1 -1
- package/dist/device-network/types.d.ts +4 -2
- package/dist/device-network/types.d.ts.map +1 -1
- package/dist/device-network-portable.cjs +190 -55
- package/dist/device-network-portable.cjs.map +1 -1
- package/dist/device-network-portable.js +189 -55
- package/dist/device-network-portable.js.map +1 -1
- package/dist/device-network.cjs +190 -55
- package/dist/device-network.cjs.map +1 -1
- package/dist/device-network.js +4 -2
- package/dist/index.cjs +488 -180
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +302 -127
- package/dist/index.js.map +1 -1
- package/dist/loop-api.cjs +1 -1
- package/dist/loop-api.cjs.map +1 -1
- package/dist/loop-api.js +1 -1
- package/dist/mobile.cjs.map +1 -1
- package/dist/orchestration/externalOrchestrationController.d.ts.map +1 -1
- package/dist/orchestration/workloadExecutionController.d.ts.map +1 -1
- package/dist/plugin/loader.d.ts +1 -1
- package/package.json +2 -1
- package/dist/chunk-DACM5AMS.js.map +0 -1
- /package/dist/{chunk-NVJCRIEK.js.map → chunk-34B7MUI6.js.map} +0 -0
|
@@ -4392,14 +4392,28 @@ var MemoryDeviceCloudTokenStorage = class {
|
|
|
4392
4392
|
loadConnectionGrant(input) {
|
|
4393
4393
|
return this.grants.get(connectionGrantCacheKey(input));
|
|
4394
4394
|
}
|
|
4395
|
-
saveConnectionGrant(input, grant) {
|
|
4396
|
-
|
|
4395
|
+
saveConnectionGrant(input, grant, fence) {
|
|
4396
|
+
const write = () => {
|
|
4397
|
+
this.grants.set(connectionGrantCacheKey(input), grant);
|
|
4398
|
+
};
|
|
4399
|
+
if (!fence) {
|
|
4400
|
+
write();
|
|
4401
|
+
return;
|
|
4402
|
+
}
|
|
4403
|
+
if (!fence.commitSynchronous(write)) fence.throwIfStale();
|
|
4397
4404
|
}
|
|
4398
4405
|
loadRelayReservation(peerId) {
|
|
4399
4406
|
return this.relayReservations.get(peerId);
|
|
4400
4407
|
}
|
|
4401
|
-
saveRelayReservation(peerId, token) {
|
|
4402
|
-
|
|
4408
|
+
saveRelayReservation(peerId, token, fence) {
|
|
4409
|
+
const write = () => {
|
|
4410
|
+
this.relayReservations.set(peerId, token);
|
|
4411
|
+
};
|
|
4412
|
+
if (!fence) {
|
|
4413
|
+
write();
|
|
4414
|
+
return;
|
|
4415
|
+
}
|
|
4416
|
+
if (!fence.commitSynchronous(write)) fence.throwIfStale();
|
|
4403
4417
|
}
|
|
4404
4418
|
clear() {
|
|
4405
4419
|
this.grants.clear();
|
|
@@ -4514,13 +4528,16 @@ var CloudDeviceFetchClient = class {
|
|
|
4514
4528
|
}
|
|
4515
4529
|
return { issuer: value.issuer, publicKeyMultibase: value.publicKeyMultibase };
|
|
4516
4530
|
}
|
|
4517
|
-
async createConnectionGrant(input, signal) {
|
|
4531
|
+
async createConnectionGrant(input, signal, fence) {
|
|
4532
|
+
assertFenceSignal(signal, fence);
|
|
4533
|
+
fence?.throwIfStale();
|
|
4518
4534
|
if (!isCanonicalConnectionGrantRequest(input)) {
|
|
4519
4535
|
throw new TypeError("invalid_connection_grant_scope");
|
|
4520
4536
|
}
|
|
4521
4537
|
const cacheInput = normalizedConnectionGrantRequest(input);
|
|
4522
4538
|
const cached = await this.loadCachedGrant(cacheInput);
|
|
4523
4539
|
throwIfAborted(signal);
|
|
4540
|
+
fence?.throwIfStale();
|
|
4524
4541
|
if (isUsableConnectionGrant(cached, cacheInput, this.now() + this.tokenSafetyMarginMs)) {
|
|
4525
4542
|
return cached;
|
|
4526
4543
|
}
|
|
@@ -4529,12 +4546,17 @@ var CloudDeviceFetchClient = class {
|
|
|
4529
4546
|
body: JSON.stringify(input)
|
|
4530
4547
|
}, signal);
|
|
4531
4548
|
if (!isUsableConnectionGrant(value, cacheInput, this.now())) throw invalidShape();
|
|
4532
|
-
|
|
4549
|
+
fence?.throwIfStale();
|
|
4550
|
+
await this.saveCachedGrant(cacheInput, value, fence);
|
|
4551
|
+
fence?.throwIfStale();
|
|
4533
4552
|
return value;
|
|
4534
4553
|
}
|
|
4535
|
-
async createRelayReservation(input, signal) {
|
|
4554
|
+
async createRelayReservation(input, signal, fence) {
|
|
4555
|
+
assertFenceSignal(signal, fence);
|
|
4556
|
+
fence?.throwIfStale();
|
|
4536
4557
|
const cached = await this.loadCachedRelayReservation(input.peerId);
|
|
4537
4558
|
throwIfAborted(signal);
|
|
4559
|
+
fence?.throwIfStale();
|
|
4538
4560
|
if (isUsableRelayReservation(cached, input.peerId, this.now() + this.tokenSafetyMarginMs)) {
|
|
4539
4561
|
return cached;
|
|
4540
4562
|
}
|
|
@@ -4543,7 +4565,9 @@ var CloudDeviceFetchClient = class {
|
|
|
4543
4565
|
body: JSON.stringify(input)
|
|
4544
4566
|
}, signal);
|
|
4545
4567
|
if (!isUsableRelayReservation(value, input.peerId, this.now())) throw invalidShape();
|
|
4546
|
-
|
|
4568
|
+
fence?.throwIfStale();
|
|
4569
|
+
await this.saveCachedRelayReservation(input.peerId, value, fence);
|
|
4570
|
+
fence?.throwIfStale();
|
|
4547
4571
|
return value;
|
|
4548
4572
|
}
|
|
4549
4573
|
async heartbeat(input, signal) {
|
|
@@ -4617,10 +4641,11 @@ var CloudDeviceFetchClient = class {
|
|
|
4617
4641
|
return void 0;
|
|
4618
4642
|
}
|
|
4619
4643
|
}
|
|
4620
|
-
async saveCachedGrant(input, grant) {
|
|
4644
|
+
async saveCachedGrant(input, grant, fence) {
|
|
4621
4645
|
try {
|
|
4622
|
-
await this.tokenStorage.saveConnectionGrant(input, grant);
|
|
4646
|
+
await this.tokenStorage.saveConnectionGrant(input, grant, fence);
|
|
4623
4647
|
} catch (error) {
|
|
4648
|
+
if (fence && !fence.isCurrent()) fence.throwIfStale();
|
|
4624
4649
|
this.options.onTokenStorageError?.("save", error);
|
|
4625
4650
|
}
|
|
4626
4651
|
}
|
|
@@ -4632,14 +4657,20 @@ var CloudDeviceFetchClient = class {
|
|
|
4632
4657
|
return void 0;
|
|
4633
4658
|
}
|
|
4634
4659
|
}
|
|
4635
|
-
async saveCachedRelayReservation(peerId, token) {
|
|
4660
|
+
async saveCachedRelayReservation(peerId, token, fence) {
|
|
4636
4661
|
try {
|
|
4637
|
-
await this.tokenStorage.saveRelayReservation(peerId, token);
|
|
4662
|
+
await this.tokenStorage.saveRelayReservation(peerId, token, fence);
|
|
4638
4663
|
} catch (error) {
|
|
4664
|
+
if (fence && !fence.isCurrent()) fence.throwIfStale();
|
|
4639
4665
|
this.options.onTokenStorageError?.("save", error);
|
|
4640
4666
|
}
|
|
4641
4667
|
}
|
|
4642
4668
|
};
|
|
4669
|
+
function assertFenceSignal(signal, fence) {
|
|
4670
|
+
if (fence && signal && fence.signal !== signal) {
|
|
4671
|
+
throw new TypeError("device_cloud_generation_signal_mismatch");
|
|
4672
|
+
}
|
|
4673
|
+
}
|
|
4643
4674
|
function normalizeCloudDeviceBaseUrl(value) {
|
|
4644
4675
|
const baseUrl = value.trim();
|
|
4645
4676
|
if (!baseUrl || baseUrl.length > CLOUD_URL_MAX_CHARACTERS) throw new Error("invalid_cloud_url");
|
|
@@ -5066,16 +5097,16 @@ var DeviceCloudConnectionCoordinator = class {
|
|
|
5066
5097
|
try {
|
|
5067
5098
|
if (this.snapshotValue.components.authorizer !== "ready") {
|
|
5068
5099
|
activeComponent = "authorizer";
|
|
5069
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.ensureAuthorizer(configuration, signal));
|
|
5100
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.ensureAuthorizer(configuration, signal, fence));
|
|
5070
5101
|
}
|
|
5071
5102
|
if (this.snapshotValue.components.registration !== "ready") {
|
|
5072
5103
|
activeComponent = "registration";
|
|
5073
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.registerDevice(configuration, signal));
|
|
5104
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.registerDevice(configuration, signal, fence));
|
|
5074
5105
|
}
|
|
5075
5106
|
let relayFailure;
|
|
5076
5107
|
try {
|
|
5077
5108
|
activeComponent = "relay";
|
|
5078
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.ensureRelay(configuration, signal));
|
|
5109
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.ensureRelay(configuration, signal, fence));
|
|
5079
5110
|
} catch (error) {
|
|
5080
5111
|
const classification = this.classify(error);
|
|
5081
5112
|
if (classification === "registration-invalid") throw error;
|
|
@@ -5083,11 +5114,11 @@ var DeviceCloudConnectionCoordinator = class {
|
|
|
5083
5114
|
this.warn("Device Cloud relay maintenance failed", relayFailure);
|
|
5084
5115
|
}
|
|
5085
5116
|
activeComponent = "heartbeat";
|
|
5086
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.heartbeat(configuration, signal));
|
|
5117
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.heartbeat(configuration, signal, fence));
|
|
5087
5118
|
let directoryFailure;
|
|
5088
5119
|
try {
|
|
5089
5120
|
activeComponent = "directory";
|
|
5090
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.syncDirectory(configuration, signal));
|
|
5121
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.syncDirectory(configuration, signal, fence));
|
|
5091
5122
|
} catch (error) {
|
|
5092
5123
|
const classification = this.classify(error);
|
|
5093
5124
|
if (classification === "registration-invalid") throw error;
|
|
@@ -5127,9 +5158,9 @@ var DeviceCloudConnectionCoordinator = class {
|
|
|
5127
5158
|
if (!this.isCurrent(generation, signal)) return;
|
|
5128
5159
|
await this.setComponent(component, "pending", generation);
|
|
5129
5160
|
try {
|
|
5130
|
-
const result = await operation();
|
|
5131
|
-
if (!this.isCurrent(generation, signal)) return;
|
|
5132
5161
|
const fence = this.createCommitFence(generation, signal);
|
|
5162
|
+
const result = await operation(fence);
|
|
5163
|
+
if (!this.isCurrent(generation, signal)) return;
|
|
5133
5164
|
await result?.commit?.(fence);
|
|
5134
5165
|
if (!this.isCurrent(generation, signal)) return;
|
|
5135
5166
|
await this.setComponent(component, "ready", generation);
|
|
@@ -5857,11 +5888,18 @@ function createJsonFrameReader(source, options) {
|
|
|
5857
5888
|
|
|
5858
5889
|
// src/device-network/deviceOrchestrationTransport.ts
|
|
5859
5890
|
var DEVICE_ORCHESTRATION_PROTOCOL = "/memeloop/orchestration/2.0.0";
|
|
5860
|
-
var
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5891
|
+
var DEVICE_ORCHESTRATION_FRAME_LIMITS = Object.freeze({
|
|
5892
|
+
maxPayloadBytes: 1024 * 1024,
|
|
5893
|
+
requestIdleTimeoutMs: 1e4,
|
|
5894
|
+
requestTotalTimeoutMs: 3e4,
|
|
5895
|
+
watchIdleTimeoutMs: 9e4,
|
|
5896
|
+
watchBookmarkIntervalMs: 3e4
|
|
5897
|
+
});
|
|
5898
|
+
var DEFAULT_MAX_FRAME_BYTES = DEVICE_ORCHESTRATION_FRAME_LIMITS.maxPayloadBytes;
|
|
5899
|
+
var REQUEST_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestIdleTimeoutMs;
|
|
5900
|
+
var REQUEST_TOTAL_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestTotalTimeoutMs;
|
|
5901
|
+
var WATCH_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchIdleTimeoutMs;
|
|
5902
|
+
var WATCH_BOOKMARK_INTERVAL_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchBookmarkIntervalMs;
|
|
5865
5903
|
function orchestrationTransportError(code, message) {
|
|
5866
5904
|
return new OrchestrationError({
|
|
5867
5905
|
code,
|
|
@@ -6142,6 +6180,13 @@ function createDeviceOrchestrationStreamHandler(options) {
|
|
|
6142
6180
|
assertFrameLimit(maxFrameBytes);
|
|
6143
6181
|
return async ({ remotePeerId, stream, authorize }) => {
|
|
6144
6182
|
const abort = new AbortController();
|
|
6183
|
+
const abortFromStream = () => {
|
|
6184
|
+
if (!abort.signal.aborted) {
|
|
6185
|
+
abort.abort(stream.signal?.reason ?? new Error("device orchestration stream closed"));
|
|
6186
|
+
}
|
|
6187
|
+
};
|
|
6188
|
+
stream.signal?.addEventListener("abort", abortFromStream, { once: true });
|
|
6189
|
+
if (stream.signal?.aborted) abortFromStream();
|
|
6145
6190
|
try {
|
|
6146
6191
|
const envelope = await readSingleRequest(stream, maxFrameBytes);
|
|
6147
6192
|
if (authorize && !await authorize(envelope.grant)) {
|
|
@@ -6165,7 +6210,8 @@ function createDeviceOrchestrationStreamHandler(options) {
|
|
|
6165
6210
|
await stream.sink(encodeJsonFrames([response], maxFrameBytes));
|
|
6166
6211
|
}
|
|
6167
6212
|
} finally {
|
|
6168
|
-
|
|
6213
|
+
stream.signal?.removeEventListener("abort", abortFromStream);
|
|
6214
|
+
if (!abort.signal.aborted) abort.abort();
|
|
6169
6215
|
await stream.close().catch(() => void 0);
|
|
6170
6216
|
}
|
|
6171
6217
|
};
|
|
@@ -6700,6 +6746,23 @@ function sameTrustedDevice(left, right) {
|
|
|
6700
6746
|
|
|
6701
6747
|
// src/device-network/standardDeviceCloudConnectionAdapter.ts
|
|
6702
6748
|
var DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS = 2 * 6e4;
|
|
6749
|
+
var REGISTRATION_INVALID_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
6750
|
+
"device_not_found",
|
|
6751
|
+
"device_registration_invalid",
|
|
6752
|
+
"device_registration_not_found",
|
|
6753
|
+
"invalid_device_registration",
|
|
6754
|
+
"registration_invalid"
|
|
6755
|
+
]);
|
|
6756
|
+
var DeviceCloudRegistrationInvalidError = class extends Error {
|
|
6757
|
+
code = "DEVICE_CLOUD_REGISTRATION_INVALID";
|
|
6758
|
+
constructor(cause) {
|
|
6759
|
+
super(
|
|
6760
|
+
"cloud device heartbeat rejected",
|
|
6761
|
+
cause === void 0 ? void 0 : { cause }
|
|
6762
|
+
);
|
|
6763
|
+
this.name = "DeviceCloudRegistrationInvalidError";
|
|
6764
|
+
}
|
|
6765
|
+
};
|
|
6703
6766
|
var StandardDeviceCloudConnectionAdapter = class {
|
|
6704
6767
|
constructor(options) {
|
|
6705
6768
|
this.options = options;
|
|
@@ -6719,9 +6782,9 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
6719
6782
|
}
|
|
6720
6783
|
relayRequiredForOnline(_configuration) {
|
|
6721
6784
|
const addresses = this.options.network.getMultiaddrs();
|
|
6722
|
-
return this.options.relayRequiredForOnline?.(addresses) ?? !hasValidDirectCloudDeviceAddress(addresses);
|
|
6785
|
+
return this.options.relayRequiredForOnline?.(addresses) ?? !hasValidDirectCloudDeviceAddress(addresses, this.options.identity.peerId);
|
|
6723
6786
|
}
|
|
6724
|
-
async ensureAuthorizer(client, signal) {
|
|
6787
|
+
async ensureAuthorizer(client, signal, _fence) {
|
|
6725
6788
|
const publicKey = await client.getConnectionGrantPublicKey(signal);
|
|
6726
6789
|
return {
|
|
6727
6790
|
commit: async (fence) => {
|
|
@@ -6731,7 +6794,7 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
6731
6794
|
}
|
|
6732
6795
|
};
|
|
6733
6796
|
}
|
|
6734
|
-
async registerDevice(client, signal) {
|
|
6797
|
+
async registerDevice(client, signal, _fence) {
|
|
6735
6798
|
const nonce = await client.createBindingNonce(signal);
|
|
6736
6799
|
throwIfAborted3(signal);
|
|
6737
6800
|
const signature = await this.options.signDeviceBinding({
|
|
@@ -6759,27 +6822,28 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
6759
6822
|
}
|
|
6760
6823
|
return void 0;
|
|
6761
6824
|
}
|
|
6762
|
-
async ensureRelay(client, signal) {
|
|
6825
|
+
async ensureRelay(client, signal, fence) {
|
|
6763
6826
|
if (this.relayReservationClient === client && this.relayReservation && this.relayReservation.expiresAt > this.now() + this.relayTokenSafetyMarginMs) {
|
|
6764
6827
|
return void 0;
|
|
6765
6828
|
}
|
|
6766
6829
|
const relayReservation = await client.createRelayReservation(
|
|
6767
6830
|
{ peerId: this.options.identity.peerId },
|
|
6768
|
-
signal
|
|
6831
|
+
signal,
|
|
6832
|
+
fence
|
|
6769
6833
|
);
|
|
6770
6834
|
return {
|
|
6771
|
-
commit: async (
|
|
6772
|
-
|
|
6773
|
-
await this.options.network.configureRelayReservation(relayReservation, signal,
|
|
6774
|
-
|
|
6775
|
-
|
|
6835
|
+
commit: async (fence2) => {
|
|
6836
|
+
fence2.throwIfStale();
|
|
6837
|
+
await this.options.network.configureRelayReservation(relayReservation, signal, fence2);
|
|
6838
|
+
fence2.throwIfStale();
|
|
6839
|
+
fence2.commitSynchronous(() => {
|
|
6776
6840
|
this.relayReservation = relayReservation;
|
|
6777
6841
|
this.relayReservationClient = client;
|
|
6778
6842
|
});
|
|
6779
6843
|
}
|
|
6780
6844
|
};
|
|
6781
6845
|
}
|
|
6782
|
-
async heartbeat(client, signal) {
|
|
6846
|
+
async heartbeat(client, signal, _fence) {
|
|
6783
6847
|
throwIfAborted3(signal);
|
|
6784
6848
|
const capabilities = await this.options.capabilities();
|
|
6785
6849
|
throwIfAborted3(signal);
|
|
@@ -6797,8 +6861,16 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
6797
6861
|
if (!boundedProofSignature(heartbeat.signature)) {
|
|
6798
6862
|
throw new Error("invalid device heartbeat signature");
|
|
6799
6863
|
}
|
|
6800
|
-
|
|
6801
|
-
|
|
6864
|
+
let result;
|
|
6865
|
+
try {
|
|
6866
|
+
result = await client.heartbeat(heartbeat, signal);
|
|
6867
|
+
} catch (error) {
|
|
6868
|
+
if (isHeartbeatRegistrationInvalid(error)) {
|
|
6869
|
+
throw new DeviceCloudRegistrationInvalidError(error);
|
|
6870
|
+
}
|
|
6871
|
+
throw error;
|
|
6872
|
+
}
|
|
6873
|
+
if (!result.ok) throw new DeviceCloudRegistrationInvalidError();
|
|
6802
6874
|
return void 0;
|
|
6803
6875
|
}
|
|
6804
6876
|
async dispose(client, signal) {
|
|
@@ -6834,7 +6906,7 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
6834
6906
|
throw new AggregateError(errors, "device cloud generation cleanup failed");
|
|
6835
6907
|
}
|
|
6836
6908
|
}
|
|
6837
|
-
async syncDirectory(client, signal) {
|
|
6909
|
+
async syncDirectory(client, signal, _fence) {
|
|
6838
6910
|
const cloudDevices = await client.listDevices(signal);
|
|
6839
6911
|
return {
|
|
6840
6912
|
commit: async (fence) => {
|
|
@@ -6862,6 +6934,7 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
6862
6934
|
return this.options.syncDevice(client, peerId, signal);
|
|
6863
6935
|
}
|
|
6864
6936
|
classifyError(error) {
|
|
6937
|
+
if (error instanceof DeviceCloudRegistrationInvalidError) return "registration-invalid";
|
|
6865
6938
|
if (error instanceof CloudDeviceFetchError) {
|
|
6866
6939
|
return error.code === "cloud_request_failed" ? "offline" : "error";
|
|
6867
6940
|
}
|
|
@@ -6872,6 +6945,35 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
6872
6945
|
return active.length > 0 ? [...active] : [...this.relayReservation?.relayMultiaddrs ?? []];
|
|
6873
6946
|
}
|
|
6874
6947
|
};
|
|
6948
|
+
function isHeartbeatRegistrationInvalid(error) {
|
|
6949
|
+
if (!(error instanceof CloudDeviceFetchError) || error.code !== "cloud_http_error") {
|
|
6950
|
+
return false;
|
|
6951
|
+
}
|
|
6952
|
+
if (error.status === 404) return true;
|
|
6953
|
+
return error.status === 401 && hasExplicitRegistrationInvalidCode(error.responseBody);
|
|
6954
|
+
}
|
|
6955
|
+
function hasExplicitRegistrationInvalidCode(responseBody) {
|
|
6956
|
+
const body = responseBody?.trim();
|
|
6957
|
+
if (!body) return false;
|
|
6958
|
+
let value;
|
|
6959
|
+
try {
|
|
6960
|
+
value = JSON.parse(body);
|
|
6961
|
+
} catch {
|
|
6962
|
+
return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(body));
|
|
6963
|
+
}
|
|
6964
|
+
return registrationInvalidCodeFromValue(value);
|
|
6965
|
+
}
|
|
6966
|
+
function registrationInvalidCodeFromValue(value) {
|
|
6967
|
+
if (typeof value === "string") {
|
|
6968
|
+
return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(value));
|
|
6969
|
+
}
|
|
6970
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
6971
|
+
const record = value;
|
|
6972
|
+
return registrationInvalidCodeFromValue(record.code) || registrationInvalidCodeFromValue(record.errorCode) || registrationInvalidCodeFromValue(record.error);
|
|
6973
|
+
}
|
|
6974
|
+
function normalizeErrorCode(value) {
|
|
6975
|
+
return value.trim().toLowerCase().replaceAll("-", "_");
|
|
6976
|
+
}
|
|
6875
6977
|
function toPublicDeviceIdentity(identity) {
|
|
6876
6978
|
return {
|
|
6877
6979
|
peerId: identity.peerId,
|
|
@@ -6881,21 +6983,42 @@ function toPublicDeviceIdentity(identity) {
|
|
|
6881
6983
|
platform: identity.platform
|
|
6882
6984
|
};
|
|
6883
6985
|
}
|
|
6884
|
-
function hasValidDirectCloudDeviceAddress(addresses) {
|
|
6885
|
-
return addresses.some((address) =>
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6986
|
+
function hasValidDirectCloudDeviceAddress(addresses, expectedPeerId) {
|
|
6987
|
+
return addresses.some((address) => isDialableDirectMultiaddr(address, expectedPeerId));
|
|
6988
|
+
}
|
|
6989
|
+
function isDialableDirectMultiaddr(address, expectedPeerId) {
|
|
6990
|
+
if (address.length === 0 || address.length > 4096 || address !== address.trim() || !address.startsWith("/") || address.endsWith("/") || address.includes("//") || address.includes("/p2p-circuit")) return false;
|
|
6991
|
+
const parts = address.split("/").slice(1);
|
|
6992
|
+
if (parts.some((part) => part.length === 0 || containsAsciiControlOrSpace3(part))) return false;
|
|
6993
|
+
const hostProtocol = parts[0];
|
|
6994
|
+
const host = parts[1]?.toLowerCase();
|
|
6995
|
+
if (host === void 0 || hostProtocol !== "ip4" && hostProtocol !== "ip6" && hostProtocol !== "dns" && hostProtocol !== "dns4" && hostProtocol !== "dns6") return false;
|
|
6996
|
+
const publicHost = hostProtocol === "ip4" ? isPublicIpv4(host) : hostProtocol === "ip6" ? isPublicIpv6(host) : isPlausiblePublicDnsHost(host);
|
|
6997
|
+
if (!publicHost) return false;
|
|
6998
|
+
const transport = parts[2];
|
|
6999
|
+
const port = parsePort(parts[3]);
|
|
7000
|
+
if (transport !== "tcp" || port === void 0) return false;
|
|
7001
|
+
let index = 4;
|
|
7002
|
+
if (parts[index] === "ws" || parts[index] === "wss") index += 1;
|
|
7003
|
+
if (parts[index] === "p2p") {
|
|
7004
|
+
const peerId = parts[index + 1];
|
|
7005
|
+
if (!peerId || containsAsciiControlOrSpace3(peerId)) return false;
|
|
7006
|
+
if (expectedPeerId !== void 0 && peerId !== expectedPeerId) return false;
|
|
7007
|
+
index += 2;
|
|
7008
|
+
}
|
|
7009
|
+
return index === parts.length;
|
|
7010
|
+
}
|
|
7011
|
+
function parsePort(value) {
|
|
7012
|
+
if (value === void 0 || !/^\d{1,5}$/u.test(value)) return void 0;
|
|
7013
|
+
const port = Number(value);
|
|
7014
|
+
return port >= 1 && port <= 65535 ? port : void 0;
|
|
7015
|
+
}
|
|
7016
|
+
function containsAsciiControlOrSpace3(value) {
|
|
7017
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
7018
|
+
const code = value.charCodeAt(index);
|
|
7019
|
+
if (code <= 32 || code === 127) return true;
|
|
7020
|
+
}
|
|
7021
|
+
return false;
|
|
6899
7022
|
}
|
|
6900
7023
|
function isPublicIpv4(host) {
|
|
6901
7024
|
const octets = host.split(".").map((part) => Number(part));
|
|
@@ -6935,7 +7058,17 @@ function isPlausiblePublicDnsHost(host) {
|
|
|
6935
7058
|
const normalized = host.endsWith(".") ? host.slice(0, -1) : host;
|
|
6936
7059
|
if (isIpv4Syntax(normalized)) return isPublicIpv4(normalized);
|
|
6937
7060
|
if (normalized.includes(":")) return isPublicIpv6(normalized);
|
|
6938
|
-
|
|
7061
|
+
const specialUseSuffixes = [
|
|
7062
|
+
"example",
|
|
7063
|
+
"home.arpa",
|
|
7064
|
+
"internal",
|
|
7065
|
+
"invalid",
|
|
7066
|
+
"local",
|
|
7067
|
+
"localhost",
|
|
7068
|
+
"onion",
|
|
7069
|
+
"test"
|
|
7070
|
+
];
|
|
7071
|
+
if (specialUseSuffixes.some((suffix) => normalized === suffix || normalized.endsWith(`.${suffix}`))) return false;
|
|
6939
7072
|
const labels = normalized.split(".");
|
|
6940
7073
|
return labels.length > 1 && labels.every(
|
|
6941
7074
|
(label) => label.length > 0 && label.length <= 63 && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label)
|
|
@@ -7905,6 +8038,7 @@ export {
|
|
|
7905
8038
|
DEVICE_HEARTBEAT_DEFAULT_MAX_CLOCK_SKEW_MS,
|
|
7906
8039
|
DEVICE_HEARTBEAT_LIMITS,
|
|
7907
8040
|
DEVICE_HEARTBEAT_SIGNATURE_DOMAIN,
|
|
8041
|
+
DEVICE_ORCHESTRATION_FRAME_LIMITS,
|
|
7908
8042
|
DEVICE_ORCHESTRATION_PROTOCOL,
|
|
7909
8043
|
DEVICE_PAIRING_INVITE_MAX_CLOCK_SKEW_MS,
|
|
7910
8044
|
DEVICE_PAIRING_INVITE_PROTOCOL,
|