@patchstack/connect 0.5.2 → 0.5.4
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/AGENT-INSTALL.md +53 -9
- package/README.md +9 -6
- package/dist/{chunk-3G2I6QL6.js → chunk-IOODP4ZB.js} +19 -2
- package/dist/chunk-IOODP4ZB.js.map +1 -0
- package/dist/cli.js +4014 -3351
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +102 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -55
- package/dist/index.d.ts +68 -55
- package/dist/index.js +102 -11
- package/dist/index.js.map +1 -1
- package/dist/protect.cjs +298 -35
- package/dist/protect.cjs.map +1 -1
- package/dist/protect.d.cts +26 -0
- package/dist/protect.d.ts +26 -0
- package/dist/protect.edge.js +172 -21
- package/dist/protect.edge.js.map +3 -3
- package/dist/protect.js +162 -24
- package/dist/protect.js.map +1 -1
- package/dist/{refresh-manifest-2MMPQN2A.js → refresh-manifest-K3RT4XNH.js} +99 -11
- package/dist/refresh-manifest-K3RT4XNH.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-3G2I6QL6.js.map +0 -1
- package/dist/refresh-manifest-2MMPQN2A.js.map +0 -1
package/dist/protect.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
canonicalBuildId,
|
|
2
3
|
pulseAuthHeader,
|
|
3
|
-
pulseFetch
|
|
4
|
-
|
|
4
|
+
pulseFetch,
|
|
5
|
+
readBuildStamp
|
|
6
|
+
} from "./chunk-IOODP4ZB.js";
|
|
5
7
|
|
|
6
8
|
// src/protect/client-ip.js
|
|
7
9
|
var ZONE = /^[A-Za-z0-9._-]{1,64}$/;
|
|
@@ -1835,6 +1837,18 @@ var RULE_PROPERTY_SHAPES = Object.freeze({
|
|
|
1835
1837
|
});
|
|
1836
1838
|
var ENFORCEMENT_VALUES = Object.freeze(["dry-run"]);
|
|
1837
1839
|
var WHEN_KEYS = Object.freeze(["path", "method"]);
|
|
1840
|
+
var BUILD_SCOPE_PROPERTY = "build_scope";
|
|
1841
|
+
var BUILD_SCOPE = Object.freeze({
|
|
1842
|
+
applies_to: Object.freeze(["firewall"]),
|
|
1843
|
+
usable: Object.freeze({
|
|
1844
|
+
type: "string",
|
|
1845
|
+
trim: true,
|
|
1846
|
+
pattern: "^[0-9a-fA-F]{64}$",
|
|
1847
|
+
canonical: "lowercase"
|
|
1848
|
+
}),
|
|
1849
|
+
unreadable: "the rule remains accepted and detects only by default",
|
|
1850
|
+
local_override: "trustLocalRuleScope may explicitly enforce a caller-supplied rule"
|
|
1851
|
+
});
|
|
1838
1852
|
var RULE_PROPERTIES = Object.freeze([
|
|
1839
1853
|
"id",
|
|
1840
1854
|
"rule_id",
|
|
@@ -1854,12 +1868,13 @@ var RULE_PROPERTIES = Object.freeze([
|
|
|
1854
1868
|
"remove_headers",
|
|
1855
1869
|
"cookie_flags",
|
|
1856
1870
|
"ensure",
|
|
1857
|
-
"capture"
|
|
1871
|
+
"capture",
|
|
1872
|
+
BUILD_SCOPE_PROPERTY
|
|
1858
1873
|
]);
|
|
1859
1874
|
var CAPTURE_VERSION = 1;
|
|
1860
1875
|
var CAPTURE_KEYS = Object.freeze(["version", "raw_chars"]);
|
|
1861
1876
|
var CAPTURE_RAW_CHARS_MAX = 512;
|
|
1862
|
-
var NULL_EXEMPT_PROPERTIES = Object.freeze(["capture"]);
|
|
1877
|
+
var NULL_EXEMPT_PROPERTIES = Object.freeze(["capture", BUILD_SCOPE_PROPERTY]);
|
|
1863
1878
|
function captureProblem(capture) {
|
|
1864
1879
|
if (capture === void 0 || capture === null) return null;
|
|
1865
1880
|
if (typeof capture !== "object" || Array.isArray(capture)) return "capture must be an object";
|
|
@@ -2100,6 +2115,10 @@ function validateBundle(bundle, opts = {}) {
|
|
|
2100
2115
|
rejected.push({ id: idOf(wl), reason: "whitelist has no rule_id (would suppress every rule); set allowGlobalWhitelists to permit" });
|
|
2101
2116
|
continue;
|
|
2102
2117
|
}
|
|
2118
|
+
if (wl && typeof wl === "object" && BUILD_SCOPE_PROPERTY in wl) {
|
|
2119
|
+
rejected.push({ id: idOf(wl), reason: `whitelist may not carry ${BUILD_SCOPE_PROPERTY}` });
|
|
2120
|
+
continue;
|
|
2121
|
+
}
|
|
2103
2122
|
const reason = conditionsProblem(wl?.rule_v2);
|
|
2104
2123
|
if (reason) rejected.push({ id: idOf(wl), reason: `whitelist: ${reason}` });
|
|
2105
2124
|
else whitelists.push(wl);
|
|
@@ -2371,6 +2390,8 @@ function asText(value) {
|
|
|
2371
2390
|
// src/protect/engine/pulse-client.js
|
|
2372
2391
|
var DEFAULT_BASE_URL2 = "https://api.patchstack.com/monitor/pulse";
|
|
2373
2392
|
var DEFAULT_CACHE_TTL2 = 3e5;
|
|
2393
|
+
var BUILD_VERDICT_HEADER = "X-Patchstack-Build-Match";
|
|
2394
|
+
var BUILD_IDENTITY_HEADER = "X-Patchstack-Build-ID";
|
|
2374
2395
|
var JITTER_FRACTION2 = 0.1;
|
|
2375
2396
|
var PulseRuleClient = class {
|
|
2376
2397
|
#siteUuid;
|
|
@@ -2383,7 +2404,8 @@ var PulseRuleClient = class {
|
|
|
2383
2404
|
#etag;
|
|
2384
2405
|
#pulseAuth;
|
|
2385
2406
|
#detectionState;
|
|
2386
|
-
|
|
2407
|
+
#buildId;
|
|
2408
|
+
constructor({ siteUuid, baseUrl, cacheTtl, etag, timeoutMs, pulseAuth, detectionState, buildId } = {}) {
|
|
2387
2409
|
this.#timeoutMs = Number(timeoutMs) > 0 ? Number(timeoutMs) : 3e4;
|
|
2388
2410
|
this.#siteUuid = siteUuid ?? process.env.PATCHSTACK_SITE_UUID;
|
|
2389
2411
|
this.#baseUrl = safeBaseUrl(baseUrl ?? process.env.PATCHSTACK_PULSE_RULES_URL, DEFAULT_BASE_URL2, "rule endpoint");
|
|
@@ -2391,6 +2413,7 @@ var PulseRuleClient = class {
|
|
|
2391
2413
|
this.#etag = etag ?? null;
|
|
2392
2414
|
this.#pulseAuth = pulseAuth ?? null;
|
|
2393
2415
|
this.#detectionState = typeof detectionState === "string" ? detectionState : null;
|
|
2416
|
+
this.#buildId = canonicalBuildId(buildId);
|
|
2394
2417
|
if (!this.#siteUuid) {
|
|
2395
2418
|
throw new Error("Patchstack site UUID is required. Pass { siteUuid } or set PATCHSTACK_SITE_UUID.");
|
|
2396
2419
|
}
|
|
@@ -2410,11 +2433,23 @@ var PulseRuleClient = class {
|
|
|
2410
2433
|
if (this.#detectionState !== null && typeof auth.Authorization === "string") {
|
|
2411
2434
|
headers["X-Patchstack-Detections"] = this.#detectionState;
|
|
2412
2435
|
}
|
|
2436
|
+
if (this.#buildId !== null && typeof auth.Authorization === "string") {
|
|
2437
|
+
headers["X-Patchstack-Build"] = this.#buildId;
|
|
2438
|
+
}
|
|
2413
2439
|
if (this.#etag) headers["If-None-Match"] = this.#etag;
|
|
2414
2440
|
const response = await fetch(url, { method: "GET", headers, signal: AbortSignal.timeout(this.#timeoutMs) });
|
|
2415
2441
|
if (response.status === 304) {
|
|
2416
2442
|
this.#touch(now);
|
|
2417
|
-
|
|
2443
|
+
const result2 = {
|
|
2444
|
+
...this.#cache ?? { firewall: [], whitelists: [], whitelist_keys: {} },
|
|
2445
|
+
success: true,
|
|
2446
|
+
notModified: true,
|
|
2447
|
+
etag: response.headers?.get?.("etag") ?? this.#etag,
|
|
2448
|
+
build: buildVerdictOf(response.headers)
|
|
2449
|
+
};
|
|
2450
|
+
this.#cache = result2;
|
|
2451
|
+
this.#etag = result2.etag;
|
|
2452
|
+
return result2;
|
|
2418
2453
|
}
|
|
2419
2454
|
if (!response.ok) {
|
|
2420
2455
|
return { success: false, error: `API returned ${response.status}`, firewall: [], whitelists: [], whitelist_keys: {} };
|
|
@@ -2430,7 +2465,10 @@ var PulseRuleClient = class {
|
|
|
2430
2465
|
firewall: data.firewall,
|
|
2431
2466
|
whitelists: Array.isArray(data.whitelists) ? data.whitelists : [],
|
|
2432
2467
|
whitelist_keys: data.whitelist_keys ?? {},
|
|
2433
|
-
...enforcementField(data)
|
|
2468
|
+
...enforcementField(data),
|
|
2469
|
+
// Carried through so the caller can decide what a build-scoped rule may do. Response metadata,
|
|
2470
|
+
// rather than bundle content, because it varies with the build asking and is also present on 304.
|
|
2471
|
+
build: buildVerdictOf(response.headers)
|
|
2434
2472
|
};
|
|
2435
2473
|
this.#cache = result;
|
|
2436
2474
|
this.#etag = result.etag;
|
|
@@ -2456,6 +2494,13 @@ var PulseRuleClient = class {
|
|
|
2456
2494
|
this.#etag = null;
|
|
2457
2495
|
}
|
|
2458
2496
|
};
|
|
2497
|
+
function buildVerdictOf(headers) {
|
|
2498
|
+
const get = headers !== null && typeof headers === "object" && typeof headers.get === "function" ? (name) => headers.get(name) : () => null;
|
|
2499
|
+
const stated = get(BUILD_VERDICT_HEADER);
|
|
2500
|
+
const verdict = stated === "match" || stated === "missing" || stated === "mismatch" ? stated : "unknown";
|
|
2501
|
+
const matched = get(BUILD_IDENTITY_HEADER);
|
|
2502
|
+
return { verdict, matchedBuildId: typeof matched === "string" ? matched : null };
|
|
2503
|
+
}
|
|
2459
2504
|
function enforcementField(data) {
|
|
2460
2505
|
if (!data || typeof data !== "object") return {};
|
|
2461
2506
|
const v = data.enforcement ?? data.mode;
|
|
@@ -3298,10 +3343,19 @@ async function cacheRead(dir) {
|
|
|
3298
3343
|
function toEnvelope(value) {
|
|
3299
3344
|
if (!value || typeof value !== "object") return null;
|
|
3300
3345
|
if (value.bundle && typeof value.bundle === "object") {
|
|
3301
|
-
|
|
3346
|
+
const buildId = canonicalBuildId(value.buildId);
|
|
3347
|
+
const matched = canonicalBuildId(value.matchedBuildId);
|
|
3348
|
+
return {
|
|
3349
|
+
bundle: value.bundle,
|
|
3350
|
+
etag: value.etag ?? null,
|
|
3351
|
+
buildId,
|
|
3352
|
+
// A confirmation belongs to the presentation stored beside it. A crossed or partially written
|
|
3353
|
+
// envelope confirms nothing, even when one of its fields happens to name the current map.
|
|
3354
|
+
matchedBuildId: buildId !== null && matched === buildId ? matched : null
|
|
3355
|
+
};
|
|
3302
3356
|
}
|
|
3303
3357
|
if (Array.isArray(value.firewall) || Array.isArray(value.whitelists)) {
|
|
3304
|
-
return { bundle: value, etag: null };
|
|
3358
|
+
return { bundle: value, etag: null, buildId: null, matchedBuildId: null };
|
|
3305
3359
|
}
|
|
3306
3360
|
return null;
|
|
3307
3361
|
}
|
|
@@ -3333,62 +3387,146 @@ function fromSource(bundle, origin, reason) {
|
|
|
3333
3387
|
source: reason === void 0 ? { ok: true, origin } : { ok: false, origin, reason }
|
|
3334
3388
|
};
|
|
3335
3389
|
}
|
|
3390
|
+
function buildIdentity(options) {
|
|
3391
|
+
if (options.buildId !== void 0 && options.buildId !== null) {
|
|
3392
|
+
const explicit = canonicalBuildId(options.buildId);
|
|
3393
|
+
return explicit === null ? { id: null, reason: "the buildId option is not a complete 64-hex SHA-256 identity" } : { id: explicit };
|
|
3394
|
+
}
|
|
3395
|
+
const stamped = readBuildStamp(options.rules);
|
|
3396
|
+
if (stamped !== null) return { id: stamped };
|
|
3397
|
+
return {
|
|
3398
|
+
id: null,
|
|
3399
|
+
reason: options.rules ? "the guard rules file carries no build identity \u2014 the build did not stamp one" : "this guard was configured without bundled rules, so it carries no build identity"
|
|
3400
|
+
};
|
|
3401
|
+
}
|
|
3402
|
+
function withScopedDryRun(bundle, confirmed, reason, options = {}) {
|
|
3403
|
+
let held = 0;
|
|
3404
|
+
let unusable = 0;
|
|
3405
|
+
const firewall = bundle.firewall.map((rule) => {
|
|
3406
|
+
if (rule === null || typeof rule !== "object") return rule;
|
|
3407
|
+
if (!(BUILD_SCOPE_PROPERTY in rule)) return rule;
|
|
3408
|
+
const scope = rule[BUILD_SCOPE_PROPERTY];
|
|
3409
|
+
const target = canonicalBuildId(scope);
|
|
3410
|
+
if (target !== null && confirmed !== null && target === confirmed) return rule;
|
|
3411
|
+
if (rule.enforcement === "dry-run") return rule;
|
|
3412
|
+
held += 1;
|
|
3413
|
+
if (target === null) unusable += 1;
|
|
3414
|
+
return { ...rule, enforcement: "dry-run" };
|
|
3415
|
+
});
|
|
3416
|
+
if (held === 0) return bundle;
|
|
3417
|
+
const explanations = [
|
|
3418
|
+
...unusable > 0 ? [`${unusable} rule(s) carry an unusable ${BUILD_SCOPE_PROPERTY}`] : [],
|
|
3419
|
+
...held > unusable ? [reason] : []
|
|
3420
|
+
];
|
|
3421
|
+
notify(
|
|
3422
|
+
options.onError,
|
|
3423
|
+
new Error(`${held} build-scoped rule(s) are detecting only, not blocking: ${explanations.join("; ")}`),
|
|
3424
|
+
"onError"
|
|
3425
|
+
);
|
|
3426
|
+
return { ...bundle, firewall };
|
|
3427
|
+
}
|
|
3428
|
+
function confirmedBy(res, presented) {
|
|
3429
|
+
if (presented === null) return null;
|
|
3430
|
+
const verdict = res?.build;
|
|
3431
|
+
if (verdict?.verdict !== "match") return null;
|
|
3432
|
+
return canonicalBuildId(verdict.matchedBuildId) === presented ? presented : null;
|
|
3433
|
+
}
|
|
3336
3434
|
async function resolveRules(options, store, ctx = {}) {
|
|
3337
3435
|
const timeoutMs = ctx.timeoutMs;
|
|
3338
3436
|
if (options.siteUuid) {
|
|
3339
3437
|
const prior = await store.read();
|
|
3340
|
-
const
|
|
3438
|
+
const identity = buildIdentity(options);
|
|
3439
|
+
const sameBuild = prior?.buildId === identity.id;
|
|
3440
|
+
const cacheConfirmed = identity.id !== null && sameBuild && prior?.matchedBuildId === identity.id ? identity.id : null;
|
|
3441
|
+
const unconfirmed = identity.reason ?? "the platform did not confirm that these coordinates belong to this map";
|
|
3442
|
+
const served = (bundle, confirmed) => withScopedDryRun(bundle, confirmed, unconfirmed, options);
|
|
3443
|
+
const local = (bundle) => options.trustLocalRuleScope === true ? bundle : withScopedDryRun(bundle, identity.id, identity.reason ?? "these rules name a different map", options);
|
|
3444
|
+
const client = new PulseRuleClient({
|
|
3445
|
+
siteUuid: options.siteUuid,
|
|
3446
|
+
baseUrl: options.pulseRulesUrl,
|
|
3447
|
+
etag: sameBuild ? prior?.etag : null,
|
|
3448
|
+
timeoutMs,
|
|
3449
|
+
pulseAuth: ctx.pulseAuth,
|
|
3450
|
+
detectionState: ctx.detectionState,
|
|
3451
|
+
buildId: identity.id
|
|
3452
|
+
});
|
|
3341
3453
|
const res = await client.getRules();
|
|
3342
|
-
if (res.success && res.notModified && prior?.bundle)
|
|
3454
|
+
if (res.success && res.notModified && prior?.bundle) {
|
|
3455
|
+
const confirmed = confirmedBy(res, identity.id);
|
|
3456
|
+
await store.write({
|
|
3457
|
+
bundle: prior.bundle,
|
|
3458
|
+
etag: res.etag ?? prior.etag ?? null,
|
|
3459
|
+
buildId: identity.id,
|
|
3460
|
+
matchedBuildId: confirmed
|
|
3461
|
+
});
|
|
3462
|
+
return fromSource(served(normalizeBundle(prior.bundle, options), confirmed), "cache");
|
|
3463
|
+
}
|
|
3343
3464
|
if (res.success && !res.notModified) {
|
|
3465
|
+
const confirmed = confirmedBy(res, identity.id);
|
|
3344
3466
|
const rejected = liveUpdateRejections(res, options);
|
|
3345
3467
|
if (rejected.length > 0) {
|
|
3346
3468
|
reportRejections(rejected, options, "rule update rejected");
|
|
3347
|
-
if (prior?.bundle) return fromSource(normalizeBundle(prior.bundle, options), "cache", "update rejected");
|
|
3348
|
-
if (options.rules) return fromSource(normalizeBundle(options.rules, options), "bundled", "update rejected");
|
|
3469
|
+
if (prior?.bundle) return fromSource(served(normalizeBundle(prior.bundle, options), cacheConfirmed), "cache", "update rejected");
|
|
3470
|
+
if (options.rules) return fromSource(local(normalizeBundle(options.rules, options)), "bundled", "update rejected");
|
|
3349
3471
|
return fromSource(emptyBundle(), "empty", "update rejected");
|
|
3350
3472
|
}
|
|
3351
3473
|
const bundle = normalizeBundle(res, options);
|
|
3352
|
-
await store.write({ bundle, etag: res.etag ?? null });
|
|
3353
|
-
return fromSource(bundle, "api");
|
|
3474
|
+
await store.write({ bundle, etag: res.etag ?? null, buildId: identity.id, matchedBuildId: confirmed });
|
|
3475
|
+
return fromSource(served(bundle, confirmed), "api");
|
|
3354
3476
|
}
|
|
3355
3477
|
if (prior?.bundle) {
|
|
3356
3478
|
notify(options.onError, new Error(`pulse rule fetch failed (${res.error ?? "no usable response"}); using cached bundle`), "onError");
|
|
3357
|
-
return fromSource(normalizeBundle(prior.bundle, options), "cache", res.error ?? "no usable response");
|
|
3479
|
+
return fromSource(served(normalizeBundle(prior.bundle, options), cacheConfirmed), "cache", res.error ?? "no usable response");
|
|
3358
3480
|
}
|
|
3359
3481
|
if (options.rules) {
|
|
3360
3482
|
notify(options.onError, new Error(`pulse rule fetch failed (${res.error ?? "no usable response"}); using bundled fallback`), "onError");
|
|
3361
|
-
return fromSource(normalizeBundle(options.rules, options), "bundled", res.error ?? "no usable response");
|
|
3483
|
+
return fromSource(local(normalizeBundle(options.rules, options)), "bundled", res.error ?? "no usable response");
|
|
3362
3484
|
}
|
|
3363
3485
|
notify(options.onError, new Error(`pulse rule fetch failed (${res.error ?? "no usable response"}); no cache \u2014 running with no rules`), "onError");
|
|
3364
3486
|
return fromSource(emptyBundle(), "empty", res.error ?? "no usable response");
|
|
3365
3487
|
}
|
|
3366
3488
|
if (options.token) {
|
|
3489
|
+
const identity = buildIdentity(options);
|
|
3490
|
+
const remote = (bundle) => withScopedDryRun(
|
|
3491
|
+
bundle,
|
|
3492
|
+
null,
|
|
3493
|
+
"the token-authenticated rules service did not corroborate this map",
|
|
3494
|
+
options
|
|
3495
|
+
);
|
|
3496
|
+
const local = (bundle) => options.trustLocalRuleScope === true ? bundle : withScopedDryRun(bundle, identity.id, identity.reason ?? "these rules name a different map", options);
|
|
3367
3497
|
const prior = await store.read();
|
|
3368
3498
|
const client = new PatchstackRuleClient({ token: options.token, baseUrl: options.baseUrl, etag: prior?.etag, timeoutMs });
|
|
3369
3499
|
const res = await client.getRules();
|
|
3370
|
-
if (res.success && res.notModified && prior?.bundle)
|
|
3500
|
+
if (res.success && res.notModified && prior?.bundle) {
|
|
3501
|
+
return fromSource(remote(normalizeBundle(prior.bundle, options)), "cache");
|
|
3502
|
+
}
|
|
3371
3503
|
if (res.success && !res.notModified) {
|
|
3372
3504
|
const rejected = liveUpdateRejections(res, options);
|
|
3373
3505
|
if (rejected.length > 0) {
|
|
3374
3506
|
reportRejections(rejected, options, "rule update rejected");
|
|
3375
|
-
if (prior?.bundle) return fromSource(normalizeBundle(prior.bundle, options), "cache", "update rejected");
|
|
3376
|
-
if (options.rules) return fromSource(normalizeBundle(options.rules, options), "bundled", "update rejected");
|
|
3507
|
+
if (prior?.bundle) return fromSource(remote(normalizeBundle(prior.bundle, options)), "cache", "update rejected");
|
|
3508
|
+
if (options.rules) return fromSource(local(normalizeBundle(options.rules, options)), "bundled", "update rejected");
|
|
3377
3509
|
return fromSource(emptyBundle(), "empty", "update rejected");
|
|
3378
3510
|
}
|
|
3379
3511
|
const bundle = normalizeBundle(res, options);
|
|
3380
3512
|
await store.write({ bundle, etag: res.etag ?? null });
|
|
3381
|
-
return fromSource(bundle, "api");
|
|
3513
|
+
return fromSource(remote(bundle), "api");
|
|
3382
3514
|
}
|
|
3383
3515
|
if (prior?.bundle) {
|
|
3384
3516
|
notify(options.onError, new Error(`rule fetch failed (${res.error ?? "no usable response"}); using cached bundle`), "onError");
|
|
3385
|
-
return fromSource(normalizeBundle(prior.bundle, options), "cache", res.error ?? "no usable response");
|
|
3517
|
+
return fromSource(remote(normalizeBundle(prior.bundle, options)), "cache", res.error ?? "no usable response");
|
|
3386
3518
|
}
|
|
3387
3519
|
notify(options.onError, new Error(`rule fetch failed (${res.error ?? "no usable response"}); no cache \u2014 running with no rules`), "onError");
|
|
3388
3520
|
return fromSource(emptyBundle(), "empty", res.error ?? "no usable response");
|
|
3389
3521
|
}
|
|
3390
3522
|
if (options.rules) {
|
|
3391
|
-
|
|
3523
|
+
const identity = buildIdentity(options);
|
|
3524
|
+
const bundle = normalizeBundle(options.rules, options);
|
|
3525
|
+
if (options.trustLocalRuleScope === true) return fromSource(bundle, "bundled");
|
|
3526
|
+
return fromSource(
|
|
3527
|
+
withScopedDryRun(bundle, identity.id, identity.reason ?? "these rules name a different map", options),
|
|
3528
|
+
"bundled"
|
|
3529
|
+
);
|
|
3392
3530
|
}
|
|
3393
3531
|
return fromSource(emptyBundle(), "empty");
|
|
3394
3532
|
}
|
|
@@ -5317,7 +5455,7 @@ async function createProtection(options = {}) {
|
|
|
5317
5455
|
let reporter = null;
|
|
5318
5456
|
if (refreshable && options.siteUuid && options.reportManifest !== false && cwd) {
|
|
5319
5457
|
try {
|
|
5320
|
-
({ reportManifest: reporter } = await import("./refresh-manifest-
|
|
5458
|
+
({ reportManifest: reporter } = await import("./refresh-manifest-K3RT4XNH.js"));
|
|
5321
5459
|
} catch (err) {
|
|
5322
5460
|
notify(onError, err, "onError");
|
|
5323
5461
|
}
|