@hasna/uptime 0.1.11 → 0.1.12
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 +20 -0
- package/dist/api.js +474 -138
- package/dist/checks.d.ts +37 -5
- package/dist/checks.d.ts.map +1 -1
- package/dist/checks.js +471 -4
- package/dist/cli/index.js +473 -140
- package/dist/cloud-plan.js +2 -2
- package/dist/imports.js +100 -17
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +480 -140
- package/dist/mcp/index.js +471 -138
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +474 -138
- package/dist/store.js +100 -17
- package/dist/target-policy.d.ts +7 -0
- package/dist/target-policy.d.ts.map +1 -1
- package/dist/types.d.ts +26 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/aws-deployment-runbook.md +5 -5
- package/infra/aws/README.md +3 -2
- package/infra/aws/terraform.tfvars.example +1 -1
- package/infra/aws/variables.tf +1 -1
- package/package.json +1 -1
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.12");
|
|
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}`;
|
|
@@ -163,7 +163,7 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
163
163
|
"The infrastructure owner repository was not found in this workspace.",
|
|
164
164
|
"The EFS SQLite bridge is single-writer only: web target desired count is 1 and scheduler/public-probe/reporter targets remain 0 until Postgres and cloud leases exist.",
|
|
165
165
|
"Hosted production auth/RBAC must replace broad static hosted-token operation before exposure.",
|
|
166
|
-
"Public probe execution still needs
|
|
166
|
+
"Public probe execution still needs cloud check-job leases wired to runHostedHttpCheck and live policy-decision log evidence.",
|
|
167
167
|
"Private probe enrollment, claim, submit, heartbeat, revocation, and rotation are not cloud-backed yet."
|
|
168
168
|
],
|
|
169
169
|
requiredEvidence: [
|
package/dist/imports.js
CHANGED
|
@@ -14,6 +14,40 @@ var MAX_RESULT_LIMIT = 1000;
|
|
|
14
14
|
// src/target-policy.ts
|
|
15
15
|
import net from "net";
|
|
16
16
|
var SECRET_PARAM_PATTERN = /(token|secret|password|passwd|api[_-]?key|access[_-]?token|auth|credential|session)/i;
|
|
17
|
+
var DENIED_IPV4_CIDRS = [
|
|
18
|
+
["0.0.0.0", 8],
|
|
19
|
+
["10.0.0.0", 8],
|
|
20
|
+
["100.64.0.0", 10],
|
|
21
|
+
["127.0.0.0", 8],
|
|
22
|
+
["169.254.0.0", 16],
|
|
23
|
+
["172.16.0.0", 12],
|
|
24
|
+
["192.0.0.0", 24],
|
|
25
|
+
["192.0.2.0", 24],
|
|
26
|
+
["192.88.99.0", 24],
|
|
27
|
+
["192.168.0.0", 16],
|
|
28
|
+
["198.18.0.0", 15],
|
|
29
|
+
["198.51.100.0", 24],
|
|
30
|
+
["203.0.113.0", 24],
|
|
31
|
+
["224.0.0.0", 4],
|
|
32
|
+
["240.0.0.0", 4]
|
|
33
|
+
];
|
|
34
|
+
var DENIED_IPV6_CIDRS = [
|
|
35
|
+
["::", 128],
|
|
36
|
+
["::1", 128],
|
|
37
|
+
["64:ff9b::", 96],
|
|
38
|
+
["64:ff9b:1::", 48],
|
|
39
|
+
["100::", 64],
|
|
40
|
+
["100:0:0:1::", 64],
|
|
41
|
+
["2001::", 23],
|
|
42
|
+
["2001:db8::", 32],
|
|
43
|
+
["2002::", 16],
|
|
44
|
+
["2620:4f:8000::", 48],
|
|
45
|
+
["3fff::", 20],
|
|
46
|
+
["5f00::", 16],
|
|
47
|
+
["fc00::", 7],
|
|
48
|
+
["fe80::", 10],
|
|
49
|
+
["ff00::", 8]
|
|
50
|
+
];
|
|
17
51
|
function assertHostedTargetAllowed(target) {
|
|
18
52
|
if (target.kind === "http" || target.kind === "browser_page") {
|
|
19
53
|
if (!target.url)
|
|
@@ -51,7 +85,7 @@ function assertHostedHttpUrlAllowed(value) {
|
|
|
51
85
|
assertHostedHostAllowed(parsed.hostname, "HTTP host");
|
|
52
86
|
}
|
|
53
87
|
function assertHostedHostAllowed(hostname, label = "host") {
|
|
54
|
-
const host =
|
|
88
|
+
const host = normalizeHostedHost(hostname);
|
|
55
89
|
if (!host)
|
|
56
90
|
throw new Error(`${label} is required`);
|
|
57
91
|
if (host === "localhost" || host.endsWith(".localhost")) {
|
|
@@ -68,39 +102,88 @@ function assertHostedHostAllowed(hostname, label = "host") {
|
|
|
68
102
|
throw new Error(`${label} is not allowed in hosted mode: private or reserved IPv6`);
|
|
69
103
|
}
|
|
70
104
|
}
|
|
71
|
-
function
|
|
105
|
+
function assertHostedResolvedAddressesAllowed(hostname, addresses, label = "resolved address") {
|
|
106
|
+
if (addresses.length === 0) {
|
|
107
|
+
throw new Error(`${label} is not allowed in hosted mode: DNS returned no addresses for ${normalizeHostedHost(hostname) || "host"}`);
|
|
108
|
+
}
|
|
109
|
+
for (const entry of addresses) {
|
|
110
|
+
assertHostedAddressAllowed(entry.address, label);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function assertHostedAddressAllowed(address, label = "resolved address") {
|
|
114
|
+
const host = normalizeHostedHost(address);
|
|
115
|
+
const ipVersion = net.isIP(host);
|
|
116
|
+
if (ipVersion === 4 && isDeniedIpv4(host)) {
|
|
117
|
+
throw new Error(`${label} is not allowed in hosted mode: private or reserved IPv4`);
|
|
118
|
+
}
|
|
119
|
+
if (ipVersion === 6 && isDeniedIpv6(host)) {
|
|
120
|
+
throw new Error(`${label} is not allowed in hosted mode: private or reserved IPv6`);
|
|
121
|
+
}
|
|
122
|
+
if (ipVersion === 0) {
|
|
123
|
+
throw new Error(`${label} is not allowed in hosted mode: DNS returned a non-IP address`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function normalizeHostedHost(hostname) {
|
|
72
127
|
return hostname.trim().toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
|
|
73
128
|
}
|
|
74
129
|
function isDeniedIpv4(ip) {
|
|
75
|
-
const parts = ip
|
|
76
|
-
if (parts
|
|
130
|
+
const parts = parseIpv4Words(ip);
|
|
131
|
+
if (!parts)
|
|
77
132
|
return true;
|
|
78
|
-
|
|
79
|
-
const [a, b] = parts;
|
|
80
|
-
return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a >= 224;
|
|
133
|
+
return DENIED_IPV4_CIDRS.some(([base, prefix]) => ipv4MatchesCidr(parts, parseIpv4Words(base), prefix));
|
|
81
134
|
}
|
|
82
135
|
function isDeniedIpv6(ip) {
|
|
83
136
|
const normalized = ip.toLowerCase();
|
|
84
|
-
const
|
|
137
|
+
const words = parseIpv6Words(normalized);
|
|
138
|
+
if (!words)
|
|
139
|
+
return true;
|
|
140
|
+
const mappedIpv4 = ipv4FromMappedIpv6Words(words);
|
|
85
141
|
if (mappedIpv4)
|
|
86
142
|
return isDeniedIpv4(mappedIpv4);
|
|
87
|
-
|
|
88
|
-
return normalized === "::" || normalized === "::1" || words !== null && (words[0] & 65472) === 65152 || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("ff");
|
|
143
|
+
return isIpv4CompatibleIpv6(words) || DENIED_IPV6_CIDRS.some(([base, prefix]) => ipv6MatchesCidr(words, parseIpv6Words(base), prefix));
|
|
89
144
|
}
|
|
90
|
-
function
|
|
91
|
-
const words = parseIpv6Words(ip);
|
|
145
|
+
function isIpv4CompatibleIpv6(words) {
|
|
92
146
|
if (!words)
|
|
93
|
-
return
|
|
147
|
+
return false;
|
|
148
|
+
if (!words.slice(0, 6).every((word) => word === 0))
|
|
149
|
+
return false;
|
|
150
|
+
if (words[6] === 0 && (words[7] === 0 || words[7] === 1))
|
|
151
|
+
return false;
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
function ipv4FromMappedIpv6Words(words) {
|
|
94
155
|
if (words[0] !== 0 || words[1] !== 0 || words[2] !== 0 || words[3] !== 0 || words[4] !== 0 || words[5] !== 65535) {
|
|
95
156
|
return null;
|
|
96
157
|
}
|
|
158
|
+
return ipv4FromWords(words[6], words[7]);
|
|
159
|
+
}
|
|
160
|
+
function ipv4FromWords(high, low) {
|
|
97
161
|
return [
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
162
|
+
high >> 8,
|
|
163
|
+
high & 255,
|
|
164
|
+
low >> 8,
|
|
165
|
+
low & 255
|
|
102
166
|
].join(".");
|
|
103
167
|
}
|
|
168
|
+
function ipv4MatchesCidr(parts, base, prefix) {
|
|
169
|
+
const mask = prefix === 0 ? 0 : 4294967295 << 32 - prefix >>> 0;
|
|
170
|
+
return (ipv4ToNumber(parts) & mask) >>> 0 === (ipv4ToNumber(base) & mask) >>> 0;
|
|
171
|
+
}
|
|
172
|
+
function ipv4ToNumber(parts) {
|
|
173
|
+
return (parts[0] << 24 >>> 0 | parts[1] << 16 | parts[2] << 8 | parts[3]) >>> 0;
|
|
174
|
+
}
|
|
175
|
+
function ipv6MatchesCidr(words, base, prefix) {
|
|
176
|
+
const fullWords = Math.floor(prefix / 16);
|
|
177
|
+
for (let index = 0;index < fullWords; index += 1) {
|
|
178
|
+
if (words[index] !== base[index])
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const remainingBits = prefix % 16;
|
|
182
|
+
if (remainingBits === 0)
|
|
183
|
+
return true;
|
|
184
|
+
const mask = 65535 << 16 - remainingBits & 65535;
|
|
185
|
+
return (words[fullWords] & mask) === (base[fullWords] & mask);
|
|
186
|
+
}
|
|
104
187
|
function parseIpv6Words(value) {
|
|
105
188
|
let ip = value.toLowerCase();
|
|
106
189
|
const zoneIndex = ip.indexOf("%");
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createUptimeClient, UptimeService } from "./service.js";
|
|
2
2
|
export { UptimeStore } from "./store.js";
|
|
3
|
-
export { runBrowserPageCheck, runMonitorCheck, runHttpCheck, runTcpCheck } from "./checks.js";
|
|
3
|
+
export { isBrowserPageEvidence, isHttpTargetPolicyEvidence, normalizeHttpTargetPolicyEvidence, runBrowserPageCheck, runHostedHttpCheck, runMonitorCheck, runHttpCheck, runTcpCheck, } from "./checks.js";
|
|
4
4
|
export { createApiHandler, serveUptime } from "./api.js";
|
|
5
5
|
export { applyImport, previewImport, rollbackImport } from "./imports.js";
|
|
6
6
|
export { buildUptimeReport, sendUptimeReport } from "./report.js";
|
|
@@ -8,9 +8,9 @@ export { generateProbeKeyPair, probePublicKeyFingerprint, probeResultSigningPayl
|
|
|
8
8
|
export { buildAwsDeploymentPlan, buildPrivateProbeCloudConfig, renderPrivateProbeEnv } from "./cloud-plan.js";
|
|
9
9
|
export { uptimeHome, uptimeDbPath, uptimeHostedFallbackDbPath, ensureUptimeHome } from "./paths.js";
|
|
10
10
|
export type { UptimeBackup, UptimeBackupCheck, UptimeRuntimeMode, UptimeStoreOptions, MonitorProvenance, SaveImportBatchInput, StoredImportBatch, UpsertMonitorProvenanceInput, } from "./store.js";
|
|
11
|
-
export type { BrowserPageRunner, BrowserPageRunnerResult, FetchLike, } from "./checks.js";
|
|
11
|
+
export type { BrowserPageRunner, BrowserPageRunnerResult, FetchLike, HostedDnsResolver, HostedHttpCheckOptions, HostedHttpRequestContext, HostedHttpRequestLike, HostedHttpResponse, MonitorCheckOptions, } from "./checks.js";
|
|
12
12
|
export type { ImportAction, ImportApplyItem, ImportApplyResult, ImportCandidate, ImportPreview, ImportPreviewItem, ImportRequest, ImportRollbackItem, ImportRollbackResult, ImportSource, } from "./imports.js";
|
|
13
|
-
export type { BrowserFailedRequest, BrowserPageEvidence, AuditEvent, CheckAttemptResult, CheckEvidence, CheckResult, CheckStatus, CreateMonitorKind, CreateMonitorInput, CreateReportScheduleInput, ImportedMonitorInput, ImportedUpdateMonitorInput, EvidenceArtifact, Incident, IncidentStatus, ListAuditEventsOptions, ListReportRunsOptions, ListResultsOptions, Monitor, MonitorKind, MonitorStatus, MonitorSummary, ProbeCheckJob, ProbeCheckJobStatus, ProbeIdentity, ProbeResultSubmission, ProbeSubmissionReceipt, RecordAuditEventInput, ReportDeliveryChannel, ReportDeliveryRecord, ReportEmailChannelConfig, ReportLogsChannelConfig, ReportRun, ReportRunStatus, ReportSchedule, ReportScheduleChannels, ReportScheduleStatus, ReportSmsChannelConfig, SchedulerHandle, UpdateMonitorInput, UpdateReportScheduleInput, UptimeSummary, } from "./types.js";
|
|
13
|
+
export type { BrowserFailedRequest, BrowserPageEvidence, AuditEvent, CheckAttemptResult, CheckEvidence, CheckResult, CheckStatus, CreateMonitorKind, CreateMonitorInput, CreateReportScheduleInput, ImportedMonitorInput, ImportedUpdateMonitorInput, EvidenceArtifact, HttpTargetPolicyDecision, HttpTargetPolicyEvidence, Incident, IncidentStatus, ListAuditEventsOptions, ListReportRunsOptions, ListResultsOptions, Monitor, MonitorKind, MonitorStatus, MonitorSummary, ProbeCheckJob, ProbeCheckJobStatus, ProbeIdentity, ProbeResultSubmission, ProbeSubmissionReceipt, RecordAuditEventInput, ReportDeliveryChannel, ReportDeliveryRecord, ReportEmailChannelConfig, ReportLogsChannelConfig, ReportRun, ReportRunStatus, ReportSchedule, ReportScheduleChannels, ReportScheduleStatus, ReportSmsChannelConfig, SchedulerHandle, UpdateMonitorInput, UpdateReportScheduleInput, UptimeSummary, } from "./types.js";
|
|
14
14
|
export type { ProbeKeyPair, ProbeSigningInput } from "./probes.js";
|
|
15
15
|
export type { AwsDeploymentPlan, AwsDeploymentPlanOptions, AwsServicePlan, PrivateProbeCloudConfig, PrivateProbeCloudConfigOptions, } from "./cloud-plan.js";
|
|
16
16
|
export type { BuildUptimeReportOptions, SendUptimeReportOptions, UptimeEmailReportTarget, UptimeLogsReportTarget, UptimeReport, UptimeReportDelivery, UptimeSmsReportTarget, } from "./report.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,iCAAiC,EACjC,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACtJ,OAAO,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACpG,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,GAC7B,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,iBAAiB,EACjB,uBAAuB,EACvB,SAAS,EACT,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,gBAAgB,EAChB,wBAAwB,EACxB,wBAAwB,EACxB,QAAQ,EACR,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,aAAa,EACb,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,SAAS,EACT,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,EACd,uBAAuB,EACvB,8BAA8B,GAC/B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
|