@hasna/uptime 0.1.10 → 0.1.11
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/CHANGELOG.md +21 -0
- package/dist/api.js +75 -11
- package/dist/cli/index.js +76 -12
- package/dist/cloud-plan.js +1 -1
- package/dist/imports.d.ts +6 -2
- package/dist/imports.d.ts.map +1 -1
- package/dist/imports.js +72 -8
- package/dist/index.js +76 -12
- package/dist/mcp/index.js +74 -10
- package/dist/service.d.ts +3 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +74 -10
- package/dist/store.js +62 -1
- package/docs/aws-deployment-runbook.md +155 -51
- package/infra/aws/outputs.tf +35 -0
- package/infra/aws/terraform.tfvars.example +1 -1
- package/infra/aws/variables.tf +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,27 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.11] - 2026-06-28
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Added Terraform outputs for log groups, web alarms, backup vault, and backup
|
|
14
|
+
plan, KMS key ARN, and secret refs so the AWS runbook can use output-driven
|
|
15
|
+
commands.
|
|
16
|
+
- Expanded the AWS deployment runbook restore drill with AWS Backup restore-job,
|
|
17
|
+
polling, staging mount-target, validation, and cleanup steps.
|
|
18
|
+
- Made the AWS runbook command blocks use explicit shell variables and
|
|
19
|
+
consistent Terraform working-directory flags.
|
|
20
|
+
- Hardened hosted target policy to normalize IPv4-mapped IPv6 literals before
|
|
21
|
+
rejecting loopback, private, link-local, metadata, carrier-grade NAT,
|
|
22
|
+
unspecified, and multicast IPv4 ranges.
|
|
23
|
+
- Hardened hosted target policy to reject the full IPv6 link-local `fe80::/10`
|
|
24
|
+
range.
|
|
25
|
+
- Scoped hosted import preview lookups by workspace so preview responses cannot
|
|
26
|
+
reveal monitors from another hosted workspace.
|
|
27
|
+
- Documented DNS resolution, redirect, and rebinding enforcement as required
|
|
28
|
+
gates before enabling hosted public probe execution.
|
|
29
|
+
|
|
9
30
|
## [0.1.10] - 2026-06-28
|
|
10
31
|
|
|
11
32
|
### Changed
|
package/dist/api.js
CHANGED
|
@@ -276,13 +276,74 @@ function isDeniedIpv4(ip) {
|
|
|
276
276
|
}
|
|
277
277
|
function isDeniedIpv6(ip) {
|
|
278
278
|
const normalized = ip.toLowerCase();
|
|
279
|
-
|
|
279
|
+
const mappedIpv4 = ipv4FromMappedIpv6(normalized);
|
|
280
|
+
if (mappedIpv4)
|
|
281
|
+
return isDeniedIpv4(mappedIpv4);
|
|
282
|
+
const words = parseIpv6Words(normalized);
|
|
283
|
+
return normalized === "::" || normalized === "::1" || words !== null && (words[0] & 65472) === 65152 || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("ff");
|
|
284
|
+
}
|
|
285
|
+
function ipv4FromMappedIpv6(ip) {
|
|
286
|
+
const words = parseIpv6Words(ip);
|
|
287
|
+
if (!words)
|
|
288
|
+
return null;
|
|
289
|
+
if (words[0] !== 0 || words[1] !== 0 || words[2] !== 0 || words[3] !== 0 || words[4] !== 0 || words[5] !== 65535) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
return [
|
|
293
|
+
words[6] >> 8,
|
|
294
|
+
words[6] & 255,
|
|
295
|
+
words[7] >> 8,
|
|
296
|
+
words[7] & 255
|
|
297
|
+
].join(".");
|
|
298
|
+
}
|
|
299
|
+
function parseIpv6Words(value) {
|
|
300
|
+
let ip = value.toLowerCase();
|
|
301
|
+
const zoneIndex = ip.indexOf("%");
|
|
302
|
+
if (zoneIndex >= 0)
|
|
303
|
+
ip = ip.slice(0, zoneIndex);
|
|
304
|
+
if (ip.includes(".")) {
|
|
305
|
+
const lastColon = ip.lastIndexOf(":");
|
|
306
|
+
if (lastColon < 0)
|
|
307
|
+
return null;
|
|
308
|
+
const ipv4 = parseIpv4Words(ip.slice(lastColon + 1));
|
|
309
|
+
if (!ipv4)
|
|
310
|
+
return null;
|
|
311
|
+
ip = `${ip.slice(0, lastColon)}:${(ipv4[0] << 8 | ipv4[1]).toString(16)}:${(ipv4[2] << 8 | ipv4[3]).toString(16)}`;
|
|
312
|
+
}
|
|
313
|
+
const compressed = ip.split("::");
|
|
314
|
+
if (compressed.length > 2)
|
|
315
|
+
return null;
|
|
316
|
+
const left = parseIpv6Side(compressed[0]);
|
|
317
|
+
const right = compressed.length === 2 ? parseIpv6Side(compressed[1]) : [];
|
|
318
|
+
if (!left || !right)
|
|
319
|
+
return null;
|
|
320
|
+
if (compressed.length === 1)
|
|
321
|
+
return left.length === 8 ? left : null;
|
|
322
|
+
const missing = 8 - left.length - right.length;
|
|
323
|
+
if (missing < 1)
|
|
324
|
+
return null;
|
|
325
|
+
return [...left, ...Array(missing).fill(0), ...right];
|
|
326
|
+
}
|
|
327
|
+
function parseIpv6Side(value) {
|
|
328
|
+
if (!value)
|
|
329
|
+
return [];
|
|
330
|
+
const words = value.split(":");
|
|
331
|
+
if (words.some((word) => !/^[0-9a-f]{1,4}$/.test(word)))
|
|
332
|
+
return null;
|
|
333
|
+
return words.map((word) => Number.parseInt(word, 16));
|
|
334
|
+
}
|
|
335
|
+
function parseIpv4Words(value) {
|
|
336
|
+
const words = value.split(".").map((part) => Number(part));
|
|
337
|
+
if (words.length !== 4 || words.some((word) => !Number.isInteger(word) || word < 0 || word > 255)) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
return words;
|
|
280
341
|
}
|
|
281
342
|
|
|
282
343
|
// src/imports.ts
|
|
283
|
-
function previewImport(store, request) {
|
|
344
|
+
function previewImport(store, request, options = {}) {
|
|
284
345
|
const source = normalizeSource(request.source);
|
|
285
|
-
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {})));
|
|
346
|
+
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {}, options)));
|
|
286
347
|
return {
|
|
287
348
|
source,
|
|
288
349
|
generatedAt: new Date().toISOString(),
|
|
@@ -356,7 +417,7 @@ function rollbackImport(store, batchId) {
|
|
|
356
417
|
items
|
|
357
418
|
};
|
|
358
419
|
}
|
|
359
|
-
function previewRecord(store, source, record, defaults) {
|
|
420
|
+
function previewRecord(store, source, record, defaults, options) {
|
|
360
421
|
const warnings = [];
|
|
361
422
|
let candidate;
|
|
362
423
|
try {
|
|
@@ -376,13 +437,16 @@ function previewRecord(store, source, record, defaults) {
|
|
|
376
437
|
reason: error instanceof Error ? error.message : String(error)
|
|
377
438
|
};
|
|
378
439
|
}
|
|
379
|
-
const
|
|
380
|
-
const
|
|
381
|
-
|
|
440
|
+
const monitorOptions = options.workspaceId ? { workspaceId: options.workspaceId } : undefined;
|
|
441
|
+
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId);
|
|
442
|
+
const provenanceMonitor = rawProvenance ? store.getMonitor(rawProvenance.monitorId, monitorOptions) : null;
|
|
443
|
+
const provenance = provenanceMonitor ? rawProvenance : null;
|
|
444
|
+
const monitor = provenanceMonitor ?? store.getMonitor(candidate.name, monitorOptions);
|
|
445
|
+
if (rawProvenance && !provenanceMonitor && !options.workspaceId) {
|
|
382
446
|
return { candidate, action: "create", monitor: null, provenance, warnings: ["source provenance points to a missing monitor"], reason: null };
|
|
383
447
|
}
|
|
384
448
|
if (provenance && monitor) {
|
|
385
|
-
const nameOwner = store.getMonitor(candidate.name);
|
|
449
|
+
const nameOwner = store.getMonitor(candidate.name, monitorOptions);
|
|
386
450
|
if (nameOwner && nameOwner.id !== monitor.id) {
|
|
387
451
|
return {
|
|
388
452
|
candidate,
|
|
@@ -2729,8 +2793,8 @@ class UptimeService {
|
|
|
2729
2793
|
const execute = () => this.submitProbeResultInTransaction(input);
|
|
2730
2794
|
return this.store.runInTransaction ? this.store.runInTransaction(execute) : execute();
|
|
2731
2795
|
}
|
|
2732
|
-
previewImport(request) {
|
|
2733
|
-
return previewImport(this.store, request);
|
|
2796
|
+
previewImport(request, options = {}) {
|
|
2797
|
+
return previewImport(this.store, request, options);
|
|
2734
2798
|
}
|
|
2735
2799
|
applyImport(request) {
|
|
2736
2800
|
return applyImport(this.store, request);
|
|
@@ -3758,7 +3822,7 @@ async function handleApiRoute(service, request, url, apiPath, options, hosted, a
|
|
|
3758
3822
|
return json(service.submitProbeResult(await jsonBody(request)), 201);
|
|
3759
3823
|
}
|
|
3760
3824
|
if (request.method === "POST" && apiPath === "/api/imports/preview") {
|
|
3761
|
-
return json(service.previewImport(await jsonBody(request)));
|
|
3825
|
+
return json(service.previewImport(await jsonBody(request), { workspaceId: actor?.workspaceId }));
|
|
3762
3826
|
}
|
|
3763
3827
|
if (request.method === "POST" && apiPath === "/api/imports/apply") {
|
|
3764
3828
|
if (hosted)
|
package/dist/cli/index.js
CHANGED
|
@@ -2856,13 +2856,74 @@ function isDeniedIpv4(ip) {
|
|
|
2856
2856
|
}
|
|
2857
2857
|
function isDeniedIpv6(ip) {
|
|
2858
2858
|
const normalized = ip.toLowerCase();
|
|
2859
|
-
|
|
2859
|
+
const mappedIpv4 = ipv4FromMappedIpv6(normalized);
|
|
2860
|
+
if (mappedIpv4)
|
|
2861
|
+
return isDeniedIpv4(mappedIpv4);
|
|
2862
|
+
const words = parseIpv6Words(normalized);
|
|
2863
|
+
return normalized === "::" || normalized === "::1" || words !== null && (words[0] & 65472) === 65152 || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("ff");
|
|
2864
|
+
}
|
|
2865
|
+
function ipv4FromMappedIpv6(ip) {
|
|
2866
|
+
const words = parseIpv6Words(ip);
|
|
2867
|
+
if (!words)
|
|
2868
|
+
return null;
|
|
2869
|
+
if (words[0] !== 0 || words[1] !== 0 || words[2] !== 0 || words[3] !== 0 || words[4] !== 0 || words[5] !== 65535) {
|
|
2870
|
+
return null;
|
|
2871
|
+
}
|
|
2872
|
+
return [
|
|
2873
|
+
words[6] >> 8,
|
|
2874
|
+
words[6] & 255,
|
|
2875
|
+
words[7] >> 8,
|
|
2876
|
+
words[7] & 255
|
|
2877
|
+
].join(".");
|
|
2878
|
+
}
|
|
2879
|
+
function parseIpv6Words(value) {
|
|
2880
|
+
let ip = value.toLowerCase();
|
|
2881
|
+
const zoneIndex = ip.indexOf("%");
|
|
2882
|
+
if (zoneIndex >= 0)
|
|
2883
|
+
ip = ip.slice(0, zoneIndex);
|
|
2884
|
+
if (ip.includes(".")) {
|
|
2885
|
+
const lastColon = ip.lastIndexOf(":");
|
|
2886
|
+
if (lastColon < 0)
|
|
2887
|
+
return null;
|
|
2888
|
+
const ipv4 = parseIpv4Words(ip.slice(lastColon + 1));
|
|
2889
|
+
if (!ipv4)
|
|
2890
|
+
return null;
|
|
2891
|
+
ip = `${ip.slice(0, lastColon)}:${(ipv4[0] << 8 | ipv4[1]).toString(16)}:${(ipv4[2] << 8 | ipv4[3]).toString(16)}`;
|
|
2892
|
+
}
|
|
2893
|
+
const compressed = ip.split("::");
|
|
2894
|
+
if (compressed.length > 2)
|
|
2895
|
+
return null;
|
|
2896
|
+
const left = parseIpv6Side(compressed[0]);
|
|
2897
|
+
const right = compressed.length === 2 ? parseIpv6Side(compressed[1]) : [];
|
|
2898
|
+
if (!left || !right)
|
|
2899
|
+
return null;
|
|
2900
|
+
if (compressed.length === 1)
|
|
2901
|
+
return left.length === 8 ? left : null;
|
|
2902
|
+
const missing = 8 - left.length - right.length;
|
|
2903
|
+
if (missing < 1)
|
|
2904
|
+
return null;
|
|
2905
|
+
return [...left, ...Array(missing).fill(0), ...right];
|
|
2906
|
+
}
|
|
2907
|
+
function parseIpv6Side(value) {
|
|
2908
|
+
if (!value)
|
|
2909
|
+
return [];
|
|
2910
|
+
const words = value.split(":");
|
|
2911
|
+
if (words.some((word) => !/^[0-9a-f]{1,4}$/.test(word)))
|
|
2912
|
+
return null;
|
|
2913
|
+
return words.map((word) => Number.parseInt(word, 16));
|
|
2914
|
+
}
|
|
2915
|
+
function parseIpv4Words(value) {
|
|
2916
|
+
const words = value.split(".").map((part) => Number(part));
|
|
2917
|
+
if (words.length !== 4 || words.some((word) => !Number.isInteger(word) || word < 0 || word > 255)) {
|
|
2918
|
+
return null;
|
|
2919
|
+
}
|
|
2920
|
+
return words;
|
|
2860
2921
|
}
|
|
2861
2922
|
|
|
2862
2923
|
// src/imports.ts
|
|
2863
|
-
function previewImport(store, request) {
|
|
2924
|
+
function previewImport(store, request, options = {}) {
|
|
2864
2925
|
const source = normalizeSource(request.source);
|
|
2865
|
-
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {})));
|
|
2926
|
+
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {}, options)));
|
|
2866
2927
|
return {
|
|
2867
2928
|
source,
|
|
2868
2929
|
generatedAt: new Date().toISOString(),
|
|
@@ -2936,7 +2997,7 @@ function rollbackImport(store, batchId) {
|
|
|
2936
2997
|
items
|
|
2937
2998
|
};
|
|
2938
2999
|
}
|
|
2939
|
-
function previewRecord(store, source, record, defaults) {
|
|
3000
|
+
function previewRecord(store, source, record, defaults, options) {
|
|
2940
3001
|
const warnings = [];
|
|
2941
3002
|
let candidate;
|
|
2942
3003
|
try {
|
|
@@ -2956,13 +3017,16 @@ function previewRecord(store, source, record, defaults) {
|
|
|
2956
3017
|
reason: error instanceof Error ? error.message : String(error)
|
|
2957
3018
|
};
|
|
2958
3019
|
}
|
|
2959
|
-
const
|
|
2960
|
-
const
|
|
2961
|
-
|
|
3020
|
+
const monitorOptions = options.workspaceId ? { workspaceId: options.workspaceId } : undefined;
|
|
3021
|
+
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId);
|
|
3022
|
+
const provenanceMonitor = rawProvenance ? store.getMonitor(rawProvenance.monitorId, monitorOptions) : null;
|
|
3023
|
+
const provenance = provenanceMonitor ? rawProvenance : null;
|
|
3024
|
+
const monitor = provenanceMonitor ?? store.getMonitor(candidate.name, monitorOptions);
|
|
3025
|
+
if (rawProvenance && !provenanceMonitor && !options.workspaceId) {
|
|
2962
3026
|
return { candidate, action: "create", monitor: null, provenance, warnings: ["source provenance points to a missing monitor"], reason: null };
|
|
2963
3027
|
}
|
|
2964
3028
|
if (provenance && monitor) {
|
|
2965
|
-
const nameOwner = store.getMonitor(candidate.name);
|
|
3029
|
+
const nameOwner = store.getMonitor(candidate.name, monitorOptions);
|
|
2966
3030
|
if (nameOwner && nameOwner.id !== monitor.id) {
|
|
2967
3031
|
return {
|
|
2968
3032
|
candidate,
|
|
@@ -5310,8 +5374,8 @@ class UptimeService {
|
|
|
5310
5374
|
const execute = () => this.submitProbeResultInTransaction(input);
|
|
5311
5375
|
return this.store.runInTransaction ? this.store.runInTransaction(execute) : execute();
|
|
5312
5376
|
}
|
|
5313
|
-
previewImport(request) {
|
|
5314
|
-
return previewImport(this.store, request);
|
|
5377
|
+
previewImport(request, options = {}) {
|
|
5378
|
+
return previewImport(this.store, request, options);
|
|
5315
5379
|
}
|
|
5316
5380
|
applyImport(request) {
|
|
5317
5381
|
return applyImport(this.store, request);
|
|
@@ -6355,7 +6419,7 @@ async function handleApiRoute(service, request, url, apiPath, options, hosted, a
|
|
|
6355
6419
|
return json(service.submitProbeResult(await jsonBody(request)), 201);
|
|
6356
6420
|
}
|
|
6357
6421
|
if (request.method === "POST" && apiPath === "/api/imports/preview") {
|
|
6358
|
-
return json(service.previewImport(await jsonBody(request)));
|
|
6422
|
+
return json(service.previewImport(await jsonBody(request), { workspaceId: actor?.workspaceId }));
|
|
6359
6423
|
}
|
|
6360
6424
|
if (request.method === "POST" && apiPath === "/api/imports/apply") {
|
|
6361
6425
|
if (hosted)
|
|
@@ -6535,7 +6599,7 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
6535
6599
|
const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
|
|
6536
6600
|
const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
|
|
6537
6601
|
const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
|
|
6538
|
-
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.
|
|
6602
|
+
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.11");
|
|
6539
6603
|
const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
|
|
6540
6604
|
const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
|
|
6541
6605
|
const cluster = `${prefix}-${stage}`;
|
package/dist/cloud-plan.js
CHANGED
|
@@ -21,7 +21,7 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
21
21
|
const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
|
|
22
22
|
const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
|
|
23
23
|
const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
|
|
24
|
-
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.
|
|
24
|
+
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.11");
|
|
25
25
|
const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
|
|
26
26
|
const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
|
|
27
27
|
const cluster = `${prefix}-${stage}`;
|
package/dist/imports.d.ts
CHANGED
|
@@ -71,7 +71,9 @@ export interface UptimeImportStore {
|
|
|
71
71
|
allowBrowserPage?: boolean;
|
|
72
72
|
}): Monitor;
|
|
73
73
|
deleteMonitor(idOrName: string): boolean;
|
|
74
|
-
getMonitor(idOrName: string
|
|
74
|
+
getMonitor(idOrName: string, options?: {
|
|
75
|
+
workspaceId?: string;
|
|
76
|
+
}): Monitor | null;
|
|
75
77
|
listResults(options?: ListResultsOptions): unknown[];
|
|
76
78
|
getProvenance(source: string, sourceId: string): MonitorProvenance | null;
|
|
77
79
|
upsertMonitorProvenance(input: UpsertMonitorProvenanceInput): MonitorProvenance;
|
|
@@ -84,7 +86,9 @@ export interface UptimeImportStore {
|
|
|
84
86
|
markImportBatchRolledBack(batchId: string): StoredImportBatch;
|
|
85
87
|
runInTransaction?<T>(fn: () => T): T;
|
|
86
88
|
}
|
|
87
|
-
export declare function previewImport(store: UptimeImportStore, request: ImportRequest
|
|
89
|
+
export declare function previewImport(store: UptimeImportStore, request: ImportRequest, options?: {
|
|
90
|
+
workspaceId?: string;
|
|
91
|
+
}): ImportPreview;
|
|
88
92
|
export declare function applyImport(store: UptimeImportStore, request: ImportRequest): ImportApplyResult;
|
|
89
93
|
export declare function rollbackImport(store: UptimeImportStore, batchId: string): ImportRollbackResult;
|
|
90
94
|
//# sourceMappingURL=imports.d.ts.map
|
package/dist/imports.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../src/imports.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../src/imports.ts"],"names":[],"mappings":"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"}
|
package/dist/imports.js
CHANGED
|
@@ -81,13 +81,74 @@ function isDeniedIpv4(ip) {
|
|
|
81
81
|
}
|
|
82
82
|
function isDeniedIpv6(ip) {
|
|
83
83
|
const normalized = ip.toLowerCase();
|
|
84
|
-
|
|
84
|
+
const mappedIpv4 = ipv4FromMappedIpv6(normalized);
|
|
85
|
+
if (mappedIpv4)
|
|
86
|
+
return isDeniedIpv4(mappedIpv4);
|
|
87
|
+
const words = parseIpv6Words(normalized);
|
|
88
|
+
return normalized === "::" || normalized === "::1" || words !== null && (words[0] & 65472) === 65152 || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("ff");
|
|
89
|
+
}
|
|
90
|
+
function ipv4FromMappedIpv6(ip) {
|
|
91
|
+
const words = parseIpv6Words(ip);
|
|
92
|
+
if (!words)
|
|
93
|
+
return null;
|
|
94
|
+
if (words[0] !== 0 || words[1] !== 0 || words[2] !== 0 || words[3] !== 0 || words[4] !== 0 || words[5] !== 65535) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return [
|
|
98
|
+
words[6] >> 8,
|
|
99
|
+
words[6] & 255,
|
|
100
|
+
words[7] >> 8,
|
|
101
|
+
words[7] & 255
|
|
102
|
+
].join(".");
|
|
103
|
+
}
|
|
104
|
+
function parseIpv6Words(value) {
|
|
105
|
+
let ip = value.toLowerCase();
|
|
106
|
+
const zoneIndex = ip.indexOf("%");
|
|
107
|
+
if (zoneIndex >= 0)
|
|
108
|
+
ip = ip.slice(0, zoneIndex);
|
|
109
|
+
if (ip.includes(".")) {
|
|
110
|
+
const lastColon = ip.lastIndexOf(":");
|
|
111
|
+
if (lastColon < 0)
|
|
112
|
+
return null;
|
|
113
|
+
const ipv4 = parseIpv4Words(ip.slice(lastColon + 1));
|
|
114
|
+
if (!ipv4)
|
|
115
|
+
return null;
|
|
116
|
+
ip = `${ip.slice(0, lastColon)}:${(ipv4[0] << 8 | ipv4[1]).toString(16)}:${(ipv4[2] << 8 | ipv4[3]).toString(16)}`;
|
|
117
|
+
}
|
|
118
|
+
const compressed = ip.split("::");
|
|
119
|
+
if (compressed.length > 2)
|
|
120
|
+
return null;
|
|
121
|
+
const left = parseIpv6Side(compressed[0]);
|
|
122
|
+
const right = compressed.length === 2 ? parseIpv6Side(compressed[1]) : [];
|
|
123
|
+
if (!left || !right)
|
|
124
|
+
return null;
|
|
125
|
+
if (compressed.length === 1)
|
|
126
|
+
return left.length === 8 ? left : null;
|
|
127
|
+
const missing = 8 - left.length - right.length;
|
|
128
|
+
if (missing < 1)
|
|
129
|
+
return null;
|
|
130
|
+
return [...left, ...Array(missing).fill(0), ...right];
|
|
131
|
+
}
|
|
132
|
+
function parseIpv6Side(value) {
|
|
133
|
+
if (!value)
|
|
134
|
+
return [];
|
|
135
|
+
const words = value.split(":");
|
|
136
|
+
if (words.some((word) => !/^[0-9a-f]{1,4}$/.test(word)))
|
|
137
|
+
return null;
|
|
138
|
+
return words.map((word) => Number.parseInt(word, 16));
|
|
139
|
+
}
|
|
140
|
+
function parseIpv4Words(value) {
|
|
141
|
+
const words = value.split(".").map((part) => Number(part));
|
|
142
|
+
if (words.length !== 4 || words.some((word) => !Number.isInteger(word) || word < 0 || word > 255)) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return words;
|
|
85
146
|
}
|
|
86
147
|
|
|
87
148
|
// src/imports.ts
|
|
88
|
-
function previewImport(store, request) {
|
|
149
|
+
function previewImport(store, request, options = {}) {
|
|
89
150
|
const source = normalizeSource(request.source);
|
|
90
|
-
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {})));
|
|
151
|
+
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {}, options)));
|
|
91
152
|
return {
|
|
92
153
|
source,
|
|
93
154
|
generatedAt: new Date().toISOString(),
|
|
@@ -161,7 +222,7 @@ function rollbackImport(store, batchId) {
|
|
|
161
222
|
items
|
|
162
223
|
};
|
|
163
224
|
}
|
|
164
|
-
function previewRecord(store, source, record, defaults) {
|
|
225
|
+
function previewRecord(store, source, record, defaults, options) {
|
|
165
226
|
const warnings = [];
|
|
166
227
|
let candidate;
|
|
167
228
|
try {
|
|
@@ -181,13 +242,16 @@ function previewRecord(store, source, record, defaults) {
|
|
|
181
242
|
reason: error instanceof Error ? error.message : String(error)
|
|
182
243
|
};
|
|
183
244
|
}
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
|
|
245
|
+
const monitorOptions = options.workspaceId ? { workspaceId: options.workspaceId } : undefined;
|
|
246
|
+
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId);
|
|
247
|
+
const provenanceMonitor = rawProvenance ? store.getMonitor(rawProvenance.monitorId, monitorOptions) : null;
|
|
248
|
+
const provenance = provenanceMonitor ? rawProvenance : null;
|
|
249
|
+
const monitor = provenanceMonitor ?? store.getMonitor(candidate.name, monitorOptions);
|
|
250
|
+
if (rawProvenance && !provenanceMonitor && !options.workspaceId) {
|
|
187
251
|
return { candidate, action: "create", monitor: null, provenance, warnings: ["source provenance points to a missing monitor"], reason: null };
|
|
188
252
|
}
|
|
189
253
|
if (provenance && monitor) {
|
|
190
|
-
const nameOwner = store.getMonitor(candidate.name);
|
|
254
|
+
const nameOwner = store.getMonitor(candidate.name, monitorOptions);
|
|
191
255
|
if (nameOwner && nameOwner.id !== monitor.id) {
|
|
192
256
|
return {
|
|
193
257
|
candidate,
|
package/dist/index.js
CHANGED
|
@@ -276,13 +276,74 @@ function isDeniedIpv4(ip) {
|
|
|
276
276
|
}
|
|
277
277
|
function isDeniedIpv6(ip) {
|
|
278
278
|
const normalized = ip.toLowerCase();
|
|
279
|
-
|
|
279
|
+
const mappedIpv4 = ipv4FromMappedIpv6(normalized);
|
|
280
|
+
if (mappedIpv4)
|
|
281
|
+
return isDeniedIpv4(mappedIpv4);
|
|
282
|
+
const words = parseIpv6Words(normalized);
|
|
283
|
+
return normalized === "::" || normalized === "::1" || words !== null && (words[0] & 65472) === 65152 || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("ff");
|
|
284
|
+
}
|
|
285
|
+
function ipv4FromMappedIpv6(ip) {
|
|
286
|
+
const words = parseIpv6Words(ip);
|
|
287
|
+
if (!words)
|
|
288
|
+
return null;
|
|
289
|
+
if (words[0] !== 0 || words[1] !== 0 || words[2] !== 0 || words[3] !== 0 || words[4] !== 0 || words[5] !== 65535) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
return [
|
|
293
|
+
words[6] >> 8,
|
|
294
|
+
words[6] & 255,
|
|
295
|
+
words[7] >> 8,
|
|
296
|
+
words[7] & 255
|
|
297
|
+
].join(".");
|
|
298
|
+
}
|
|
299
|
+
function parseIpv6Words(value) {
|
|
300
|
+
let ip = value.toLowerCase();
|
|
301
|
+
const zoneIndex = ip.indexOf("%");
|
|
302
|
+
if (zoneIndex >= 0)
|
|
303
|
+
ip = ip.slice(0, zoneIndex);
|
|
304
|
+
if (ip.includes(".")) {
|
|
305
|
+
const lastColon = ip.lastIndexOf(":");
|
|
306
|
+
if (lastColon < 0)
|
|
307
|
+
return null;
|
|
308
|
+
const ipv4 = parseIpv4Words(ip.slice(lastColon + 1));
|
|
309
|
+
if (!ipv4)
|
|
310
|
+
return null;
|
|
311
|
+
ip = `${ip.slice(0, lastColon)}:${(ipv4[0] << 8 | ipv4[1]).toString(16)}:${(ipv4[2] << 8 | ipv4[3]).toString(16)}`;
|
|
312
|
+
}
|
|
313
|
+
const compressed = ip.split("::");
|
|
314
|
+
if (compressed.length > 2)
|
|
315
|
+
return null;
|
|
316
|
+
const left = parseIpv6Side(compressed[0]);
|
|
317
|
+
const right = compressed.length === 2 ? parseIpv6Side(compressed[1]) : [];
|
|
318
|
+
if (!left || !right)
|
|
319
|
+
return null;
|
|
320
|
+
if (compressed.length === 1)
|
|
321
|
+
return left.length === 8 ? left : null;
|
|
322
|
+
const missing = 8 - left.length - right.length;
|
|
323
|
+
if (missing < 1)
|
|
324
|
+
return null;
|
|
325
|
+
return [...left, ...Array(missing).fill(0), ...right];
|
|
326
|
+
}
|
|
327
|
+
function parseIpv6Side(value) {
|
|
328
|
+
if (!value)
|
|
329
|
+
return [];
|
|
330
|
+
const words = value.split(":");
|
|
331
|
+
if (words.some((word) => !/^[0-9a-f]{1,4}$/.test(word)))
|
|
332
|
+
return null;
|
|
333
|
+
return words.map((word) => Number.parseInt(word, 16));
|
|
334
|
+
}
|
|
335
|
+
function parseIpv4Words(value) {
|
|
336
|
+
const words = value.split(".").map((part) => Number(part));
|
|
337
|
+
if (words.length !== 4 || words.some((word) => !Number.isInteger(word) || word < 0 || word > 255)) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
return words;
|
|
280
341
|
}
|
|
281
342
|
|
|
282
343
|
// src/imports.ts
|
|
283
|
-
function previewImport(store, request) {
|
|
344
|
+
function previewImport(store, request, options = {}) {
|
|
284
345
|
const source = normalizeSource(request.source);
|
|
285
|
-
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {})));
|
|
346
|
+
const items = dedupePreviewItems(request.records.map((record) => previewRecord(store, source, record, request.defaults ?? {}, options)));
|
|
286
347
|
return {
|
|
287
348
|
source,
|
|
288
349
|
generatedAt: new Date().toISOString(),
|
|
@@ -356,7 +417,7 @@ function rollbackImport(store, batchId) {
|
|
|
356
417
|
items
|
|
357
418
|
};
|
|
358
419
|
}
|
|
359
|
-
function previewRecord(store, source, record, defaults) {
|
|
420
|
+
function previewRecord(store, source, record, defaults, options) {
|
|
360
421
|
const warnings = [];
|
|
361
422
|
let candidate;
|
|
362
423
|
try {
|
|
@@ -376,13 +437,16 @@ function previewRecord(store, source, record, defaults) {
|
|
|
376
437
|
reason: error instanceof Error ? error.message : String(error)
|
|
377
438
|
};
|
|
378
439
|
}
|
|
379
|
-
const
|
|
380
|
-
const
|
|
381
|
-
|
|
440
|
+
const monitorOptions = options.workspaceId ? { workspaceId: options.workspaceId } : undefined;
|
|
441
|
+
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId);
|
|
442
|
+
const provenanceMonitor = rawProvenance ? store.getMonitor(rawProvenance.monitorId, monitorOptions) : null;
|
|
443
|
+
const provenance = provenanceMonitor ? rawProvenance : null;
|
|
444
|
+
const monitor = provenanceMonitor ?? store.getMonitor(candidate.name, monitorOptions);
|
|
445
|
+
if (rawProvenance && !provenanceMonitor && !options.workspaceId) {
|
|
382
446
|
return { candidate, action: "create", monitor: null, provenance, warnings: ["source provenance points to a missing monitor"], reason: null };
|
|
383
447
|
}
|
|
384
448
|
if (provenance && monitor) {
|
|
385
|
-
const nameOwner = store.getMonitor(candidate.name);
|
|
449
|
+
const nameOwner = store.getMonitor(candidate.name, monitorOptions);
|
|
386
450
|
if (nameOwner && nameOwner.id !== monitor.id) {
|
|
387
451
|
return {
|
|
388
452
|
candidate,
|
|
@@ -2729,8 +2793,8 @@ class UptimeService {
|
|
|
2729
2793
|
const execute = () => this.submitProbeResultInTransaction(input);
|
|
2730
2794
|
return this.store.runInTransaction ? this.store.runInTransaction(execute) : execute();
|
|
2731
2795
|
}
|
|
2732
|
-
previewImport(request) {
|
|
2733
|
-
return previewImport(this.store, request);
|
|
2796
|
+
previewImport(request, options = {}) {
|
|
2797
|
+
return previewImport(this.store, request, options);
|
|
2734
2798
|
}
|
|
2735
2799
|
applyImport(request) {
|
|
2736
2800
|
return applyImport(this.store, request);
|
|
@@ -3758,7 +3822,7 @@ async function handleApiRoute(service, request, url, apiPath, options, hosted, a
|
|
|
3758
3822
|
return json(service.submitProbeResult(await jsonBody(request)), 201);
|
|
3759
3823
|
}
|
|
3760
3824
|
if (request.method === "POST" && apiPath === "/api/imports/preview") {
|
|
3761
|
-
return json(service.previewImport(await jsonBody(request)));
|
|
3825
|
+
return json(service.previewImport(await jsonBody(request), { workspaceId: actor?.workspaceId }));
|
|
3762
3826
|
}
|
|
3763
3827
|
if (request.method === "POST" && apiPath === "/api/imports/apply") {
|
|
3764
3828
|
if (hosted)
|
|
@@ -3938,7 +4002,7 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
3938
4002
|
const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
|
|
3939
4003
|
const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
|
|
3940
4004
|
const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
|
|
3941
|
-
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.
|
|
4005
|
+
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.11");
|
|
3942
4006
|
const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
|
|
3943
4007
|
const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
|
|
3944
4008
|
const cluster = `${prefix}-${stage}`;
|