@hasna/uptime 0.1.22 → 0.1.23
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 +12 -0
- package/dist/api.d.ts +1 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +160 -23
- package/dist/checks.d.ts +4 -0
- package/dist/checks.d.ts.map +1 -1
- package/dist/checks.js +26 -3
- package/dist/cli/index.js +161 -24
- package/dist/cloud-plan.js +1 -1
- package/dist/imports.d.ts +5 -1
- package/dist/imports.d.ts.map +1 -1
- package/dist/imports.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +162 -24
- package/dist/mcp/index.js +114 -18
- package/dist/service.d.ts +4 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +114 -18
- package/dist/store.d.ts +6 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +79 -12
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/aws-deployment-runbook.md +3 -2
- package/docs/aws-runtime-security.md +2 -1
- package/docs/cloud-source-of-truth.md +3 -3
- package/docs/deployment-metadata.example.json +1 -1
- package/docs/operational-tracking.md +2 -2
- package/infra/aws/terraform.tfvars.example +1 -1
- package/infra/aws/variables.tf +1 -1
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -14532,8 +14532,9 @@ async function runMonitorCheck(monitor, options = {}) {
|
|
|
14532
14532
|
}
|
|
14533
14533
|
if (monitor.kind === "browser_page")
|
|
14534
14534
|
return runBrowserPageCheck(monitor, { fetch: options.fetch, runner: options.browserPage });
|
|
14535
|
-
if (monitor.kind === "tcp")
|
|
14536
|
-
return runTcpCheck(monitor);
|
|
14535
|
+
if (monitor.kind === "tcp") {
|
|
14536
|
+
return options.hostedTargetPolicy ? runHostedTcpCheck(monitor, { resolveHost: options.resolveHost }) : runTcpCheck(monitor);
|
|
14537
|
+
}
|
|
14537
14538
|
return { status: "down", latencyMs: null, error: `unsupported monitor kind: ${monitor.kind ?? "unknown"}` };
|
|
14538
14539
|
}
|
|
14539
14540
|
async function runHttpCheck(monitor, fetchImpl = fetch) {
|
|
@@ -14645,9 +14646,30 @@ async function runHostedHttpCheck(monitor, options = {}) {
|
|
|
14645
14646
|
async function runTcpCheck(monitor) {
|
|
14646
14647
|
if (!monitor.host || !monitor.port)
|
|
14647
14648
|
return { status: "down", latencyMs: null, error: "missing host or port" };
|
|
14649
|
+
return runTcpSocket(monitor.host, monitor.port, monitor.timeoutMs);
|
|
14650
|
+
}
|
|
14651
|
+
async function runHostedTcpCheck(monitor, options = {}) {
|
|
14652
|
+
if (!monitor.host || !monitor.port)
|
|
14653
|
+
return { status: "down", latencyMs: null, error: "missing host or port" };
|
|
14654
|
+
const resolver = options.resolveHost ?? resolveHostedHost;
|
|
14655
|
+
try {
|
|
14656
|
+
const addresses = normalizeResolvedAddresses(await resolver(normalizeHostedHost(monitor.host)));
|
|
14657
|
+
assertHostedResolvedAddressesAllowed(monitor.host, addresses, "TCP resolved address");
|
|
14658
|
+
const address = addresses[0];
|
|
14659
|
+
return runTcpSocket(address.address, monitor.port, monitor.timeoutMs, address.family);
|
|
14660
|
+
} catch (error51) {
|
|
14661
|
+
return {
|
|
14662
|
+
status: "down",
|
|
14663
|
+
latencyMs: null,
|
|
14664
|
+
statusCode: null,
|
|
14665
|
+
error: error51 instanceof Error ? error51.message : String(error51)
|
|
14666
|
+
};
|
|
14667
|
+
}
|
|
14668
|
+
}
|
|
14669
|
+
async function runTcpSocket(host, port, timeoutMs, family) {
|
|
14648
14670
|
const started = performance.now();
|
|
14649
14671
|
return new Promise((resolve) => {
|
|
14650
|
-
const socket = net2.createConnection({ host
|
|
14672
|
+
const socket = net2.createConnection({ host, port, timeout: timeoutMs, family });
|
|
14651
14673
|
let settled = false;
|
|
14652
14674
|
const finish = (result) => {
|
|
14653
14675
|
if (settled)
|
|
@@ -15063,7 +15085,7 @@ function previewRecord(store, source, record2, defaults, options) {
|
|
|
15063
15085
|
};
|
|
15064
15086
|
}
|
|
15065
15087
|
const monitorOptions = options.workspaceId ? { workspaceId: options.workspaceId } : undefined;
|
|
15066
|
-
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId);
|
|
15088
|
+
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId, monitorOptions);
|
|
15067
15089
|
const provenanceMonitor = rawProvenance ? store.getMonitor(rawProvenance.monitorId, monitorOptions) : null;
|
|
15068
15090
|
const provenance = provenanceMonitor ? rawProvenance : null;
|
|
15069
15091
|
const monitor = provenanceMonitor ?? store.getMonitor(candidate.name, monitorOptions);
|
|
@@ -15526,7 +15548,7 @@ var REQUIRED_TABLES = [
|
|
|
15526
15548
|
];
|
|
15527
15549
|
var PROBE_TABLES = new Set(["probe_identities", "probe_check_jobs", "probe_submissions"]);
|
|
15528
15550
|
var REPORT_AUDIT_TABLES = new Set(["report_schedules", "report_runs", "audit_events"]);
|
|
15529
|
-
var CURRENT_SCHEMA_VERSION = "
|
|
15551
|
+
var CURRENT_SCHEMA_VERSION = "5";
|
|
15530
15552
|
|
|
15531
15553
|
class StaleCheckResultError extends Error {
|
|
15532
15554
|
constructor(message) {
|
|
@@ -15639,15 +15661,17 @@ class UptimeStore {
|
|
|
15639
15661
|
`);
|
|
15640
15662
|
this.db.run(`
|
|
15641
15663
|
CREATE TABLE IF NOT EXISTS monitor_provenance (
|
|
15664
|
+
workspace_id TEXT NOT NULL DEFAULT 'local',
|
|
15642
15665
|
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
|
15643
15666
|
source TEXT NOT NULL,
|
|
15644
15667
|
source_id TEXT NOT NULL,
|
|
15645
15668
|
source_label TEXT,
|
|
15646
15669
|
imported_at TEXT NOT NULL,
|
|
15647
15670
|
snapshot_json TEXT NOT NULL,
|
|
15648
|
-
PRIMARY KEY (source, source_id)
|
|
15671
|
+
PRIMARY KEY (workspace_id, source, source_id)
|
|
15649
15672
|
)
|
|
15650
15673
|
`);
|
|
15674
|
+
this.ensureMonitorProvenanceWorkspaceScoped();
|
|
15651
15675
|
this.db.run(`
|
|
15652
15676
|
CREATE TABLE IF NOT EXISTS import_batches (
|
|
15653
15677
|
id TEXT PRIMARY KEY,
|
|
@@ -15739,6 +15763,7 @@ class UptimeStore {
|
|
|
15739
15763
|
this.db.run(`
|
|
15740
15764
|
CREATE TABLE IF NOT EXISTS audit_events (
|
|
15741
15765
|
id TEXT PRIMARY KEY,
|
|
15766
|
+
workspace_id TEXT,
|
|
15742
15767
|
action TEXT NOT NULL,
|
|
15743
15768
|
resource_type TEXT,
|
|
15744
15769
|
resource_id TEXT,
|
|
@@ -15748,6 +15773,7 @@ class UptimeStore {
|
|
|
15748
15773
|
created_at TEXT NOT NULL
|
|
15749
15774
|
)
|
|
15750
15775
|
`);
|
|
15776
|
+
this.ensureColumn("audit_events", "workspace_id", "TEXT");
|
|
15751
15777
|
this.db.run(`
|
|
15752
15778
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
15753
15779
|
key TEXT PRIMARY KEY,
|
|
@@ -15761,6 +15787,7 @@ class UptimeStore {
|
|
|
15761
15787
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_incidents_monitor_status ON incidents(monitor_id, status)");
|
|
15762
15788
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_check_leases_until ON check_leases(leased_until)");
|
|
15763
15789
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_monitor_provenance_monitor ON monitor_provenance(monitor_id)");
|
|
15790
|
+
this.db.run("CREATE INDEX IF NOT EXISTS idx_monitor_provenance_workspace_source ON monitor_provenance(workspace_id, source, source_id)");
|
|
15764
15791
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_probe_jobs_status_due ON probe_check_jobs(status, due_at)");
|
|
15765
15792
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_probe_jobs_probe_status ON probe_check_jobs(claimed_by_probe_id, status)");
|
|
15766
15793
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_probe_submissions_probe_time ON probe_submissions(probe_id, submitted_at DESC)");
|
|
@@ -15769,6 +15796,7 @@ class UptimeStore {
|
|
|
15769
15796
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_report_schedules_due ON report_schedules(enabled, next_run_at)");
|
|
15770
15797
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_report_runs_schedule_time ON report_runs(schedule_id, started_at DESC)");
|
|
15771
15798
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_audit_events_resource_time ON audit_events(resource_type, resource_id, created_at DESC)");
|
|
15799
|
+
this.db.run("CREATE INDEX IF NOT EXISTS idx_audit_events_workspace_time ON audit_events(workspace_id, created_at DESC)");
|
|
15772
15800
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_audit_events_time ON audit_events(created_at DESC)");
|
|
15773
15801
|
}
|
|
15774
15802
|
backup(destinationPath) {
|
|
@@ -15818,6 +15846,9 @@ class UptimeStore {
|
|
|
15818
15846
|
const normalized = normalizeCreateMonitor(input, options.allowBrowserPage === true);
|
|
15819
15847
|
if (this.mode === "hosted")
|
|
15820
15848
|
assertHostedTargetAllowed(normalized);
|
|
15849
|
+
if (this.mode === "hosted" && normalized.kind === "browser_page" && normalized.enabled !== false) {
|
|
15850
|
+
throw new Error("hosted browser_page monitors must remain disabled until browser evidence workers are configured");
|
|
15851
|
+
}
|
|
15821
15852
|
const now = new Date().toISOString();
|
|
15822
15853
|
const workspaceId = normalizeWorkspaceId(options.workspaceId ?? input.workspaceId ?? "local");
|
|
15823
15854
|
const monitor = {
|
|
@@ -15882,6 +15913,9 @@ class UptimeStore {
|
|
|
15882
15913
|
const next = normalizeUpdateMonitor(current, input, updatedAt, options.allowBrowserPage === true);
|
|
15883
15914
|
if (this.mode === "hosted")
|
|
15884
15915
|
assertHostedTargetAllowed(next);
|
|
15916
|
+
if (this.mode === "hosted" && next.kind === "browser_page" && next.enabled) {
|
|
15917
|
+
throw new Error("hosted browser_page monitors must remain disabled until browser evidence workers are configured");
|
|
15918
|
+
}
|
|
15885
15919
|
this.db.query(`UPDATE monitors SET
|
|
15886
15920
|
name = ?, kind = ?, url = ?, host = ?, port = ?, method = ?,
|
|
15887
15921
|
expected_status = ?, interval_seconds = ?, timeout_ms = ?,
|
|
@@ -16178,8 +16212,10 @@ class UptimeStore {
|
|
|
16178
16212
|
const action = normalizeAuditText(input.action, "Audit action", 160);
|
|
16179
16213
|
const createdAt = input.createdAt ?? new Date().toISOString();
|
|
16180
16214
|
assertIsoTimestamp(createdAt, "Audit event createdAt");
|
|
16215
|
+
const workspaceId = input.workspaceId == null ? null : normalizeWorkspaceId(input.workspaceId);
|
|
16181
16216
|
const event = {
|
|
16182
16217
|
id: newId("aud"),
|
|
16218
|
+
workspaceId,
|
|
16183
16219
|
action,
|
|
16184
16220
|
resourceType: normalizeNullableAuditText(input.resourceType, "Audit resourceType", 80),
|
|
16185
16221
|
resourceId: normalizeNullableAuditText(input.resourceId, "Audit resourceId", 160),
|
|
@@ -16189,13 +16225,17 @@ class UptimeStore {
|
|
|
16189
16225
|
createdAt
|
|
16190
16226
|
};
|
|
16191
16227
|
this.db.query(`INSERT INTO audit_events (
|
|
16192
|
-
id, action, resource_type, resource_id, message, metadata_json, actor, created_at
|
|
16193
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(event.id, event.action, event.resourceType, event.resourceId, event.message, JSON.stringify(event.metadata), event.actor, event.createdAt);
|
|
16228
|
+
id, workspace_id, action, resource_type, resource_id, message, metadata_json, actor, created_at
|
|
16229
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(event.id, event.workspaceId, event.action, event.resourceType, event.resourceId, event.message, JSON.stringify(event.metadata), event.actor, event.createdAt);
|
|
16194
16230
|
return event;
|
|
16195
16231
|
}
|
|
16196
16232
|
listAuditEvents(options = {}) {
|
|
16197
16233
|
const clauses = [];
|
|
16198
16234
|
const args = [];
|
|
16235
|
+
if (options.workspaceId) {
|
|
16236
|
+
clauses.push("workspace_id = ?");
|
|
16237
|
+
args.push(normalizeWorkspaceId(options.workspaceId));
|
|
16238
|
+
}
|
|
16199
16239
|
if (options.resourceType) {
|
|
16200
16240
|
clauses.push("resource_type = ?");
|
|
16201
16241
|
args.push(options.resourceType);
|
|
@@ -16287,21 +16327,24 @@ class UptimeStore {
|
|
|
16287
16327
|
const rows = this.db.query(`SELECT check_results.* FROM check_results JOIN monitors ON monitors.id = check_results.monitor_id ${where} ORDER BY checked_at DESC LIMIT ?`).all(...args);
|
|
16288
16328
|
return rows.map(checkResultFromRow);
|
|
16289
16329
|
}
|
|
16290
|
-
getProvenance(source, sourceId) {
|
|
16291
|
-
const
|
|
16330
|
+
getProvenance(source, sourceId, options = {}) {
|
|
16331
|
+
const workspaceId = options.workspaceId ? normalizeWorkspaceId(options.workspaceId) : undefined;
|
|
16332
|
+
const row = workspaceId ? this.db.query("SELECT * FROM monitor_provenance WHERE workspace_id = ? AND source = ? AND source_id = ?").get(workspaceId, source, sourceId) : this.db.query("SELECT * FROM monitor_provenance WHERE source = ? AND source_id = ? ORDER BY imported_at DESC LIMIT 1").get(source, sourceId);
|
|
16292
16333
|
return row ? provenanceFromRow(row) : null;
|
|
16293
16334
|
}
|
|
16294
16335
|
upsertMonitorProvenance(input) {
|
|
16295
16336
|
const importedAt = new Date().toISOString();
|
|
16337
|
+
const monitor = this.getMonitor(input.monitorId);
|
|
16338
|
+
const workspaceId = normalizeWorkspaceId(input.workspaceId ?? monitor?.workspaceId ?? "local");
|
|
16296
16339
|
this.db.query(`INSERT INTO monitor_provenance (
|
|
16297
|
-
monitor_id, source, source_id, source_label, imported_at, snapshot_json
|
|
16298
|
-
) VALUES (?, ?, ?, ?, ?, ?)
|
|
16299
|
-
ON CONFLICT(source, source_id) DO UPDATE SET
|
|
16340
|
+
workspace_id, monitor_id, source, source_id, source_label, imported_at, snapshot_json
|
|
16341
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
16342
|
+
ON CONFLICT(workspace_id, source, source_id) DO UPDATE SET
|
|
16300
16343
|
monitor_id = excluded.monitor_id,
|
|
16301
16344
|
source_label = excluded.source_label,
|
|
16302
16345
|
imported_at = excluded.imported_at,
|
|
16303
|
-
snapshot_json = excluded.snapshot_json`).run(input.monitorId, input.source, input.sourceId, input.sourceLabel ?? null, importedAt, JSON.stringify(input.snapshot));
|
|
16304
|
-
return this.getProvenance(input.source, input.sourceId);
|
|
16346
|
+
snapshot_json = excluded.snapshot_json`).run(workspaceId, input.monitorId, input.source, input.sourceId, input.sourceLabel ?? null, importedAt, JSON.stringify(input.snapshot));
|
|
16347
|
+
return this.getProvenance(input.source, input.sourceId, { workspaceId });
|
|
16305
16348
|
}
|
|
16306
16349
|
saveImportBatch(input) {
|
|
16307
16350
|
const createdAt = new Date().toISOString();
|
|
@@ -16484,6 +16527,49 @@ class UptimeStore {
|
|
|
16484
16527
|
this.db.run("PRAGMA foreign_keys = ON");
|
|
16485
16528
|
}
|
|
16486
16529
|
}
|
|
16530
|
+
ensureMonitorProvenanceWorkspaceScoped() {
|
|
16531
|
+
const row = this.db.query("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'monitor_provenance'").get();
|
|
16532
|
+
const columns = this.db.query("PRAGMA table_info(monitor_provenance)").all();
|
|
16533
|
+
const hasWorkspaceId = columns.some((column) => column.name === "workspace_id");
|
|
16534
|
+
const hasWorkspacePrimaryKey = Boolean(row?.sql?.includes("PRIMARY KEY (workspace_id, source, source_id)"));
|
|
16535
|
+
if (hasWorkspaceId && hasWorkspacePrimaryKey)
|
|
16536
|
+
return;
|
|
16537
|
+
this.db.run("PRAGMA foreign_keys = OFF");
|
|
16538
|
+
this.db.run("PRAGMA legacy_alter_table = ON");
|
|
16539
|
+
try {
|
|
16540
|
+
const migrate = this.db.transaction(() => {
|
|
16541
|
+
this.db.run("ALTER TABLE monitor_provenance RENAME TO monitor_provenance_old_workspace");
|
|
16542
|
+
this.db.run(`
|
|
16543
|
+
CREATE TABLE monitor_provenance (
|
|
16544
|
+
workspace_id TEXT NOT NULL DEFAULT 'local',
|
|
16545
|
+
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
|
16546
|
+
source TEXT NOT NULL,
|
|
16547
|
+
source_id TEXT NOT NULL,
|
|
16548
|
+
source_label TEXT,
|
|
16549
|
+
imported_at TEXT NOT NULL,
|
|
16550
|
+
snapshot_json TEXT NOT NULL,
|
|
16551
|
+
PRIMARY KEY (workspace_id, source, source_id)
|
|
16552
|
+
)
|
|
16553
|
+
`);
|
|
16554
|
+
const workspaceSelect = hasWorkspaceId ? "COALESCE(old.workspace_id, monitors.workspace_id, 'local')" : "COALESCE(monitors.workspace_id, 'local')";
|
|
16555
|
+
this.db.run(`
|
|
16556
|
+
INSERT OR REPLACE INTO monitor_provenance (
|
|
16557
|
+
workspace_id, monitor_id, source, source_id, source_label, imported_at, snapshot_json
|
|
16558
|
+
)
|
|
16559
|
+
SELECT
|
|
16560
|
+
${workspaceSelect}, old.monitor_id, old.source, old.source_id, old.source_label,
|
|
16561
|
+
old.imported_at, old.snapshot_json
|
|
16562
|
+
FROM monitor_provenance_old_workspace old
|
|
16563
|
+
LEFT JOIN monitors ON monitors.id = old.monitor_id
|
|
16564
|
+
`);
|
|
16565
|
+
this.db.run("DROP TABLE monitor_provenance_old_workspace");
|
|
16566
|
+
});
|
|
16567
|
+
migrate();
|
|
16568
|
+
} finally {
|
|
16569
|
+
this.db.run("PRAGMA legacy_alter_table = OFF");
|
|
16570
|
+
this.db.run("PRAGMA foreign_keys = ON");
|
|
16571
|
+
}
|
|
16572
|
+
}
|
|
16487
16573
|
vacuumInto(backupPath) {
|
|
16488
16574
|
const quoted = backupPath.replace(/'/g, "''");
|
|
16489
16575
|
this.db.run(`VACUUM INTO '${quoted}'`);
|
|
@@ -16513,10 +16599,11 @@ function verifyBackupFile(backupPath) {
|
|
|
16513
16599
|
const missingTables = REQUIRED_TABLES.filter((table) => !tableExists(db, table));
|
|
16514
16600
|
const schemaVersion = missingTables.includes("schema_migrations") ? null : db.query("SELECT value FROM schema_migrations WHERE key = 'schema_version'").get()?.value ?? null;
|
|
16515
16601
|
const currentOk = missingTables.length === 0 && schemaVersion === CURRENT_SCHEMA_VERSION;
|
|
16602
|
+
const restorableV4 = schemaVersion === "4" && missingTables.length === 0;
|
|
16516
16603
|
const restorableV1 = schemaVersion === "1" && missingTables.every((table) => PROBE_TABLES.has(table) || REPORT_AUDIT_TABLES.has(table));
|
|
16517
16604
|
const restorableV2 = schemaVersion === "2" && missingTables.every((table) => REPORT_AUDIT_TABLES.has(table));
|
|
16518
16605
|
return {
|
|
16519
|
-
ok: integrity === "ok" && (currentOk || restorableV1 || restorableV2),
|
|
16606
|
+
ok: integrity === "ok" && (currentOk || restorableV4 || restorableV1 || restorableV2),
|
|
16520
16607
|
backupPath,
|
|
16521
16608
|
integrity,
|
|
16522
16609
|
schemaVersion,
|
|
@@ -16901,6 +16988,7 @@ function checkResultFromRow(row) {
|
|
|
16901
16988
|
}
|
|
16902
16989
|
function provenanceFromRow(row) {
|
|
16903
16990
|
return {
|
|
16991
|
+
workspaceId: row.workspace_id,
|
|
16904
16992
|
monitorId: row.monitor_id,
|
|
16905
16993
|
source: row.source,
|
|
16906
16994
|
sourceId: row.source_id,
|
|
@@ -16988,6 +17076,7 @@ function reportRunFromRow(row) {
|
|
|
16988
17076
|
function auditEventFromRow(row) {
|
|
16989
17077
|
return {
|
|
16990
17078
|
id: row.id,
|
|
17079
|
+
workspaceId: row.workspace_id,
|
|
16991
17080
|
action: row.action,
|
|
16992
17081
|
resourceType: row.resource_type,
|
|
16993
17082
|
resourceId: row.resource_id,
|
|
@@ -17489,10 +17578,10 @@ class UptimeService {
|
|
|
17489
17578
|
return this.reportStore().listReportRuns(options);
|
|
17490
17579
|
}
|
|
17491
17580
|
listAuditEvents(options = {}) {
|
|
17492
|
-
return this.
|
|
17581
|
+
return this.auditStore().listAuditEvents(options);
|
|
17493
17582
|
}
|
|
17494
17583
|
recordAuditEvent(input) {
|
|
17495
|
-
return this.
|
|
17584
|
+
return this.auditStore().recordAuditEvent(input);
|
|
17496
17585
|
}
|
|
17497
17586
|
async runReportSchedule(idOrName, options = {}) {
|
|
17498
17587
|
const store = this.reportStore();
|
|
@@ -17699,6 +17788,13 @@ class UptimeService {
|
|
|
17699
17788
|
}
|
|
17700
17789
|
return store;
|
|
17701
17790
|
}
|
|
17791
|
+
auditStore() {
|
|
17792
|
+
const store = this.store;
|
|
17793
|
+
if (typeof store.recordAuditEvent !== "function" || typeof store.listAuditEvents !== "function") {
|
|
17794
|
+
throw new Error("audit logging requires an audit-capable store");
|
|
17795
|
+
}
|
|
17796
|
+
return store;
|
|
17797
|
+
}
|
|
17702
17798
|
audit(action, resourceType, resourceId, message, metadata) {
|
|
17703
17799
|
this.reportStore().recordAuditEvent({
|
|
17704
17800
|
action,
|
package/dist/service.d.ts
CHANGED
|
@@ -48,7 +48,9 @@ export interface UptimeStoreLike {
|
|
|
48
48
|
checkedAt?: string;
|
|
49
49
|
expectedMonitorRevision?: number;
|
|
50
50
|
}): CheckResult;
|
|
51
|
-
getProvenance(source: string, sourceId: string
|
|
51
|
+
getProvenance(source: string, sourceId: string, options?: {
|
|
52
|
+
workspaceId?: string;
|
|
53
|
+
}): MonitorProvenance | null;
|
|
52
54
|
upsertMonitorProvenance(input: UpsertMonitorProvenanceInput): MonitorProvenance;
|
|
53
55
|
saveImportBatch(input: SaveImportBatchInput): StoredImportBatch;
|
|
54
56
|
getImportBatch(batchId: string): StoredImportBatch | null;
|
|
@@ -207,6 +209,7 @@ export declare class UptimeService {
|
|
|
207
209
|
private isDue;
|
|
208
210
|
private probeStore;
|
|
209
211
|
private reportStore;
|
|
212
|
+
private auditStore;
|
|
210
213
|
private audit;
|
|
211
214
|
private submitProbeResultInTransaction;
|
|
212
215
|
}
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8C,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAErK,OAAO,EAAsC,KAAK,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,KAAK,iBAAiB,EAAE,KAAK,4BAA4B,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClP,OAAO,EAAuC,KAAK,wBAAwB,EAAE,KAAK,uBAAuB,EAAE,KAAK,YAAY,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC7K,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAElB,WAAW,EACX,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,oBAAoB,EACpB,0BAA0B,EAC1B,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,EACd,MAAM,YAAY,CAAC;AAKpB,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAC9D,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;IAChF,KAAK,IAAI,IAAI,CAAC;IACd,aAAa,CAAC,KAAK,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IACpH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,0BAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IAC5I,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IAC7E,YAAY,CAAC,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,EAAE,CAAC;IACvF,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,GAAG,IAAI,CAAC;IACjF,cAAc,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAChD,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,EAAE,CAAC;IACzD,aAAa,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,QAAQ,EAAE,CAAC;IAC9H,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC;IAC3D,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAC/C,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACpD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5E,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW,CAAC;IACxI,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,iBAAiB,GAAG,IAAI,CAAC;IAC9G,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,CAAC;IAChF,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,iBAAiB,CAAC;IAChE,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAAC;IAC1D,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAAC;IAC9D,mBAAmB,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,aAAa,CAAC;IACpI,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,aAAa,EAAE,CAAC;IAC/E,gBAAgB,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;IAC1D,mBAAmB,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC;IACnG,kBAAkB,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,mBAAmB,CAAC,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC;IACxG,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;IACpD,kBAAkB,CAAC,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC;IACnG,qBAAqB,CAAC,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,CAAC;IACpJ,kBAAkB,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAAC;IACnF,qBAAqB,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,IAAI,GAAG,aAAa,CAAC,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,sBAAsB,CAAC;IACrI,oBAAoB,CAAC,CAAC,KAAK,EAAE,yBAAyB,GAAG,cAAc,CAAC;IACxE,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,cAAc,EAAE,CAAC;IAChF,sBAAsB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;IAC3D,iBAAiB,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IAC5D,oBAAoB,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,yBAAyB,GAAG,cAAc,CAAC;IAC1F,oBAAoB,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,eAAe,CAAC,CAAC,KAAK,EAAE;QACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;QAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;QACpC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KAC7C,GAAG,SAAS,CAAC;IACd,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,SAAS,EAAE,CAAC;IAC9D,gBAAgB,CAAC,CAAC,KAAK,EAAE,qBAAqB,GAAG,UAAU,CAAC;IAC5D,eAAe,CAAC,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,UAAU,EAAE,CAAC;IACjE,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CACtC;AAqCD,qBAAa,aAAa;IACxB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoD;IAChF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwD;IACnF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAqB;gBAEjD,OAAO,GAAE,oBAAyB;IAK9C,KAAK,IAAI,IAAI;IAIb,aAAa,CAAC,KAAK,EAAE,kBAAkB,EAAE,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO;IAIzF,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO;IAI3G,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO;IAIhF,YAAY,CAAC,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,EAAE;IAI1F,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,GAAG,IAAI;IAIpF,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,EAAE;IAI5D,aAAa,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,QAAQ,EAAE;IAIjI,OAAO,CAAC,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,aAAa;IAI9D,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB;IAmBvD,UAAU,CAAC,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,aAAa,EAAE;IAIxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAIhD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa;IAIzF,mBAAmB,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa;IAItG,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAIlD,kBAAkB,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa;IAIjG,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,GAAG;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,sBAAsB,CAAA;KAAE;IAKzG,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,aAAa;IAI5F,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,iBAAiB;IAItD,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB;IAIrD,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,YAAY;IAI9C,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB;IAInD,WAAW,CAAC,OAAO,GAAE,wBAAwB,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,YAAY;IAKtF,UAAU,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAOxF,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,cAAc;IAYtE,mBAAmB,CAAC,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,cAAc,EAAE;IAIlF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAI1D,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,yBAAyB,GAAG,cAAc;IAYxF,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAY/C,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,SAAS,EAAE;IAIhE,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,UAAU,EAAE;IAInE,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,UAAU;IAIpD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;KAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAkDnG,qBAAqB,CAAC,GAAG,GAAE,IAAiB,EAAE,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;KAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAU/G,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAoCpD,QAAQ,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAUxC,cAAc,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,OAAO,KAAK,CAAA;KAAO,GAAG,eAAe;IAgB5F,YAAY,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAiBlE,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,UAAU;IA0BlB,OAAO,CAAC,WAAW;IAyBnB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,KAAK;IAWb,OAAO,CAAC,8BAA8B;CAiEvC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CAEpF;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B"}
|
package/dist/service.js
CHANGED
|
@@ -236,8 +236,9 @@ async function runMonitorCheck(monitor, options = {}) {
|
|
|
236
236
|
}
|
|
237
237
|
if (monitor.kind === "browser_page")
|
|
238
238
|
return runBrowserPageCheck(monitor, { fetch: options.fetch, runner: options.browserPage });
|
|
239
|
-
if (monitor.kind === "tcp")
|
|
240
|
-
return runTcpCheck(monitor);
|
|
239
|
+
if (monitor.kind === "tcp") {
|
|
240
|
+
return options.hostedTargetPolicy ? runHostedTcpCheck(monitor, { resolveHost: options.resolveHost }) : runTcpCheck(monitor);
|
|
241
|
+
}
|
|
241
242
|
return { status: "down", latencyMs: null, error: `unsupported monitor kind: ${monitor.kind ?? "unknown"}` };
|
|
242
243
|
}
|
|
243
244
|
async function runHttpCheck(monitor, fetchImpl = fetch) {
|
|
@@ -349,9 +350,30 @@ async function runHostedHttpCheck(monitor, options = {}) {
|
|
|
349
350
|
async function runTcpCheck(monitor) {
|
|
350
351
|
if (!monitor.host || !monitor.port)
|
|
351
352
|
return { status: "down", latencyMs: null, error: "missing host or port" };
|
|
353
|
+
return runTcpSocket(monitor.host, monitor.port, monitor.timeoutMs);
|
|
354
|
+
}
|
|
355
|
+
async function runHostedTcpCheck(monitor, options = {}) {
|
|
356
|
+
if (!monitor.host || !monitor.port)
|
|
357
|
+
return { status: "down", latencyMs: null, error: "missing host or port" };
|
|
358
|
+
const resolver = options.resolveHost ?? resolveHostedHost;
|
|
359
|
+
try {
|
|
360
|
+
const addresses = normalizeResolvedAddresses(await resolver(normalizeHostedHost(monitor.host)));
|
|
361
|
+
assertHostedResolvedAddressesAllowed(monitor.host, addresses, "TCP resolved address");
|
|
362
|
+
const address = addresses[0];
|
|
363
|
+
return runTcpSocket(address.address, monitor.port, monitor.timeoutMs, address.family);
|
|
364
|
+
} catch (error) {
|
|
365
|
+
return {
|
|
366
|
+
status: "down",
|
|
367
|
+
latencyMs: null,
|
|
368
|
+
statusCode: null,
|
|
369
|
+
error: error instanceof Error ? error.message : String(error)
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
async function runTcpSocket(host, port, timeoutMs, family) {
|
|
352
374
|
const started = performance.now();
|
|
353
375
|
return new Promise((resolve) => {
|
|
354
|
-
const socket = net2.createConnection({ host
|
|
376
|
+
const socket = net2.createConnection({ host, port, timeout: timeoutMs, family });
|
|
355
377
|
let settled = false;
|
|
356
378
|
const finish = (result) => {
|
|
357
379
|
if (settled)
|
|
@@ -767,7 +789,7 @@ function previewRecord(store, source, record, defaults, options) {
|
|
|
767
789
|
};
|
|
768
790
|
}
|
|
769
791
|
const monitorOptions = options.workspaceId ? { workspaceId: options.workspaceId } : undefined;
|
|
770
|
-
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId);
|
|
792
|
+
const rawProvenance = store.getProvenance(candidate.source, candidate.sourceId, monitorOptions);
|
|
771
793
|
const provenanceMonitor = rawProvenance ? store.getMonitor(rawProvenance.monitorId, monitorOptions) : null;
|
|
772
794
|
const provenance = provenanceMonitor ? rawProvenance : null;
|
|
773
795
|
const monitor = provenanceMonitor ?? store.getMonitor(candidate.name, monitorOptions);
|
|
@@ -1237,7 +1259,7 @@ var REQUIRED_TABLES = [
|
|
|
1237
1259
|
];
|
|
1238
1260
|
var PROBE_TABLES = new Set(["probe_identities", "probe_check_jobs", "probe_submissions"]);
|
|
1239
1261
|
var REPORT_AUDIT_TABLES = new Set(["report_schedules", "report_runs", "audit_events"]);
|
|
1240
|
-
var CURRENT_SCHEMA_VERSION = "
|
|
1262
|
+
var CURRENT_SCHEMA_VERSION = "5";
|
|
1241
1263
|
|
|
1242
1264
|
class StaleCheckResultError extends Error {
|
|
1243
1265
|
constructor(message) {
|
|
@@ -1350,15 +1372,17 @@ class UptimeStore {
|
|
|
1350
1372
|
`);
|
|
1351
1373
|
this.db.run(`
|
|
1352
1374
|
CREATE TABLE IF NOT EXISTS monitor_provenance (
|
|
1375
|
+
workspace_id TEXT NOT NULL DEFAULT 'local',
|
|
1353
1376
|
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
|
1354
1377
|
source TEXT NOT NULL,
|
|
1355
1378
|
source_id TEXT NOT NULL,
|
|
1356
1379
|
source_label TEXT,
|
|
1357
1380
|
imported_at TEXT NOT NULL,
|
|
1358
1381
|
snapshot_json TEXT NOT NULL,
|
|
1359
|
-
PRIMARY KEY (source, source_id)
|
|
1382
|
+
PRIMARY KEY (workspace_id, source, source_id)
|
|
1360
1383
|
)
|
|
1361
1384
|
`);
|
|
1385
|
+
this.ensureMonitorProvenanceWorkspaceScoped();
|
|
1362
1386
|
this.db.run(`
|
|
1363
1387
|
CREATE TABLE IF NOT EXISTS import_batches (
|
|
1364
1388
|
id TEXT PRIMARY KEY,
|
|
@@ -1450,6 +1474,7 @@ class UptimeStore {
|
|
|
1450
1474
|
this.db.run(`
|
|
1451
1475
|
CREATE TABLE IF NOT EXISTS audit_events (
|
|
1452
1476
|
id TEXT PRIMARY KEY,
|
|
1477
|
+
workspace_id TEXT,
|
|
1453
1478
|
action TEXT NOT NULL,
|
|
1454
1479
|
resource_type TEXT,
|
|
1455
1480
|
resource_id TEXT,
|
|
@@ -1459,6 +1484,7 @@ class UptimeStore {
|
|
|
1459
1484
|
created_at TEXT NOT NULL
|
|
1460
1485
|
)
|
|
1461
1486
|
`);
|
|
1487
|
+
this.ensureColumn("audit_events", "workspace_id", "TEXT");
|
|
1462
1488
|
this.db.run(`
|
|
1463
1489
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
1464
1490
|
key TEXT PRIMARY KEY,
|
|
@@ -1472,6 +1498,7 @@ class UptimeStore {
|
|
|
1472
1498
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_incidents_monitor_status ON incidents(monitor_id, status)");
|
|
1473
1499
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_check_leases_until ON check_leases(leased_until)");
|
|
1474
1500
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_monitor_provenance_monitor ON monitor_provenance(monitor_id)");
|
|
1501
|
+
this.db.run("CREATE INDEX IF NOT EXISTS idx_monitor_provenance_workspace_source ON monitor_provenance(workspace_id, source, source_id)");
|
|
1475
1502
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_probe_jobs_status_due ON probe_check_jobs(status, due_at)");
|
|
1476
1503
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_probe_jobs_probe_status ON probe_check_jobs(claimed_by_probe_id, status)");
|
|
1477
1504
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_probe_submissions_probe_time ON probe_submissions(probe_id, submitted_at DESC)");
|
|
@@ -1480,6 +1507,7 @@ class UptimeStore {
|
|
|
1480
1507
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_report_schedules_due ON report_schedules(enabled, next_run_at)");
|
|
1481
1508
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_report_runs_schedule_time ON report_runs(schedule_id, started_at DESC)");
|
|
1482
1509
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_audit_events_resource_time ON audit_events(resource_type, resource_id, created_at DESC)");
|
|
1510
|
+
this.db.run("CREATE INDEX IF NOT EXISTS idx_audit_events_workspace_time ON audit_events(workspace_id, created_at DESC)");
|
|
1483
1511
|
this.db.run("CREATE INDEX IF NOT EXISTS idx_audit_events_time ON audit_events(created_at DESC)");
|
|
1484
1512
|
}
|
|
1485
1513
|
backup(destinationPath) {
|
|
@@ -1529,6 +1557,9 @@ class UptimeStore {
|
|
|
1529
1557
|
const normalized = normalizeCreateMonitor(input, options.allowBrowserPage === true);
|
|
1530
1558
|
if (this.mode === "hosted")
|
|
1531
1559
|
assertHostedTargetAllowed(normalized);
|
|
1560
|
+
if (this.mode === "hosted" && normalized.kind === "browser_page" && normalized.enabled !== false) {
|
|
1561
|
+
throw new Error("hosted browser_page monitors must remain disabled until browser evidence workers are configured");
|
|
1562
|
+
}
|
|
1532
1563
|
const now = new Date().toISOString();
|
|
1533
1564
|
const workspaceId = normalizeWorkspaceId(options.workspaceId ?? input.workspaceId ?? "local");
|
|
1534
1565
|
const monitor = {
|
|
@@ -1593,6 +1624,9 @@ class UptimeStore {
|
|
|
1593
1624
|
const next = normalizeUpdateMonitor(current, input, updatedAt, options.allowBrowserPage === true);
|
|
1594
1625
|
if (this.mode === "hosted")
|
|
1595
1626
|
assertHostedTargetAllowed(next);
|
|
1627
|
+
if (this.mode === "hosted" && next.kind === "browser_page" && next.enabled) {
|
|
1628
|
+
throw new Error("hosted browser_page monitors must remain disabled until browser evidence workers are configured");
|
|
1629
|
+
}
|
|
1596
1630
|
this.db.query(`UPDATE monitors SET
|
|
1597
1631
|
name = ?, kind = ?, url = ?, host = ?, port = ?, method = ?,
|
|
1598
1632
|
expected_status = ?, interval_seconds = ?, timeout_ms = ?,
|
|
@@ -1889,8 +1923,10 @@ class UptimeStore {
|
|
|
1889
1923
|
const action = normalizeAuditText(input.action, "Audit action", 160);
|
|
1890
1924
|
const createdAt = input.createdAt ?? new Date().toISOString();
|
|
1891
1925
|
assertIsoTimestamp(createdAt, "Audit event createdAt");
|
|
1926
|
+
const workspaceId = input.workspaceId == null ? null : normalizeWorkspaceId(input.workspaceId);
|
|
1892
1927
|
const event = {
|
|
1893
1928
|
id: newId("aud"),
|
|
1929
|
+
workspaceId,
|
|
1894
1930
|
action,
|
|
1895
1931
|
resourceType: normalizeNullableAuditText(input.resourceType, "Audit resourceType", 80),
|
|
1896
1932
|
resourceId: normalizeNullableAuditText(input.resourceId, "Audit resourceId", 160),
|
|
@@ -1900,13 +1936,17 @@ class UptimeStore {
|
|
|
1900
1936
|
createdAt
|
|
1901
1937
|
};
|
|
1902
1938
|
this.db.query(`INSERT INTO audit_events (
|
|
1903
|
-
id, action, resource_type, resource_id, message, metadata_json, actor, created_at
|
|
1904
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(event.id, event.action, event.resourceType, event.resourceId, event.message, JSON.stringify(event.metadata), event.actor, event.createdAt);
|
|
1939
|
+
id, workspace_id, action, resource_type, resource_id, message, metadata_json, actor, created_at
|
|
1940
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(event.id, event.workspaceId, event.action, event.resourceType, event.resourceId, event.message, JSON.stringify(event.metadata), event.actor, event.createdAt);
|
|
1905
1941
|
return event;
|
|
1906
1942
|
}
|
|
1907
1943
|
listAuditEvents(options = {}) {
|
|
1908
1944
|
const clauses = [];
|
|
1909
1945
|
const args = [];
|
|
1946
|
+
if (options.workspaceId) {
|
|
1947
|
+
clauses.push("workspace_id = ?");
|
|
1948
|
+
args.push(normalizeWorkspaceId(options.workspaceId));
|
|
1949
|
+
}
|
|
1910
1950
|
if (options.resourceType) {
|
|
1911
1951
|
clauses.push("resource_type = ?");
|
|
1912
1952
|
args.push(options.resourceType);
|
|
@@ -1998,21 +2038,24 @@ class UptimeStore {
|
|
|
1998
2038
|
const rows = this.db.query(`SELECT check_results.* FROM check_results JOIN monitors ON monitors.id = check_results.monitor_id ${where} ORDER BY checked_at DESC LIMIT ?`).all(...args);
|
|
1999
2039
|
return rows.map(checkResultFromRow);
|
|
2000
2040
|
}
|
|
2001
|
-
getProvenance(source, sourceId) {
|
|
2002
|
-
const
|
|
2041
|
+
getProvenance(source, sourceId, options = {}) {
|
|
2042
|
+
const workspaceId = options.workspaceId ? normalizeWorkspaceId(options.workspaceId) : undefined;
|
|
2043
|
+
const row = workspaceId ? this.db.query("SELECT * FROM monitor_provenance WHERE workspace_id = ? AND source = ? AND source_id = ?").get(workspaceId, source, sourceId) : this.db.query("SELECT * FROM monitor_provenance WHERE source = ? AND source_id = ? ORDER BY imported_at DESC LIMIT 1").get(source, sourceId);
|
|
2003
2044
|
return row ? provenanceFromRow(row) : null;
|
|
2004
2045
|
}
|
|
2005
2046
|
upsertMonitorProvenance(input) {
|
|
2006
2047
|
const importedAt = new Date().toISOString();
|
|
2048
|
+
const monitor = this.getMonitor(input.monitorId);
|
|
2049
|
+
const workspaceId = normalizeWorkspaceId(input.workspaceId ?? monitor?.workspaceId ?? "local");
|
|
2007
2050
|
this.db.query(`INSERT INTO monitor_provenance (
|
|
2008
|
-
monitor_id, source, source_id, source_label, imported_at, snapshot_json
|
|
2009
|
-
) VALUES (?, ?, ?, ?, ?, ?)
|
|
2010
|
-
ON CONFLICT(source, source_id) DO UPDATE SET
|
|
2051
|
+
workspace_id, monitor_id, source, source_id, source_label, imported_at, snapshot_json
|
|
2052
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
2053
|
+
ON CONFLICT(workspace_id, source, source_id) DO UPDATE SET
|
|
2011
2054
|
monitor_id = excluded.monitor_id,
|
|
2012
2055
|
source_label = excluded.source_label,
|
|
2013
2056
|
imported_at = excluded.imported_at,
|
|
2014
|
-
snapshot_json = excluded.snapshot_json`).run(input.monitorId, input.source, input.sourceId, input.sourceLabel ?? null, importedAt, JSON.stringify(input.snapshot));
|
|
2015
|
-
return this.getProvenance(input.source, input.sourceId);
|
|
2057
|
+
snapshot_json = excluded.snapshot_json`).run(workspaceId, input.monitorId, input.source, input.sourceId, input.sourceLabel ?? null, importedAt, JSON.stringify(input.snapshot));
|
|
2058
|
+
return this.getProvenance(input.source, input.sourceId, { workspaceId });
|
|
2016
2059
|
}
|
|
2017
2060
|
saveImportBatch(input) {
|
|
2018
2061
|
const createdAt = new Date().toISOString();
|
|
@@ -2195,6 +2238,49 @@ class UptimeStore {
|
|
|
2195
2238
|
this.db.run("PRAGMA foreign_keys = ON");
|
|
2196
2239
|
}
|
|
2197
2240
|
}
|
|
2241
|
+
ensureMonitorProvenanceWorkspaceScoped() {
|
|
2242
|
+
const row = this.db.query("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'monitor_provenance'").get();
|
|
2243
|
+
const columns = this.db.query("PRAGMA table_info(monitor_provenance)").all();
|
|
2244
|
+
const hasWorkspaceId = columns.some((column) => column.name === "workspace_id");
|
|
2245
|
+
const hasWorkspacePrimaryKey = Boolean(row?.sql?.includes("PRIMARY KEY (workspace_id, source, source_id)"));
|
|
2246
|
+
if (hasWorkspaceId && hasWorkspacePrimaryKey)
|
|
2247
|
+
return;
|
|
2248
|
+
this.db.run("PRAGMA foreign_keys = OFF");
|
|
2249
|
+
this.db.run("PRAGMA legacy_alter_table = ON");
|
|
2250
|
+
try {
|
|
2251
|
+
const migrate = this.db.transaction(() => {
|
|
2252
|
+
this.db.run("ALTER TABLE monitor_provenance RENAME TO monitor_provenance_old_workspace");
|
|
2253
|
+
this.db.run(`
|
|
2254
|
+
CREATE TABLE monitor_provenance (
|
|
2255
|
+
workspace_id TEXT NOT NULL DEFAULT 'local',
|
|
2256
|
+
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
|
2257
|
+
source TEXT NOT NULL,
|
|
2258
|
+
source_id TEXT NOT NULL,
|
|
2259
|
+
source_label TEXT,
|
|
2260
|
+
imported_at TEXT NOT NULL,
|
|
2261
|
+
snapshot_json TEXT NOT NULL,
|
|
2262
|
+
PRIMARY KEY (workspace_id, source, source_id)
|
|
2263
|
+
)
|
|
2264
|
+
`);
|
|
2265
|
+
const workspaceSelect = hasWorkspaceId ? "COALESCE(old.workspace_id, monitors.workspace_id, 'local')" : "COALESCE(monitors.workspace_id, 'local')";
|
|
2266
|
+
this.db.run(`
|
|
2267
|
+
INSERT OR REPLACE INTO monitor_provenance (
|
|
2268
|
+
workspace_id, monitor_id, source, source_id, source_label, imported_at, snapshot_json
|
|
2269
|
+
)
|
|
2270
|
+
SELECT
|
|
2271
|
+
${workspaceSelect}, old.monitor_id, old.source, old.source_id, old.source_label,
|
|
2272
|
+
old.imported_at, old.snapshot_json
|
|
2273
|
+
FROM monitor_provenance_old_workspace old
|
|
2274
|
+
LEFT JOIN monitors ON monitors.id = old.monitor_id
|
|
2275
|
+
`);
|
|
2276
|
+
this.db.run("DROP TABLE monitor_provenance_old_workspace");
|
|
2277
|
+
});
|
|
2278
|
+
migrate();
|
|
2279
|
+
} finally {
|
|
2280
|
+
this.db.run("PRAGMA legacy_alter_table = OFF");
|
|
2281
|
+
this.db.run("PRAGMA foreign_keys = ON");
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2198
2284
|
vacuumInto(backupPath) {
|
|
2199
2285
|
const quoted = backupPath.replace(/'/g, "''");
|
|
2200
2286
|
this.db.run(`VACUUM INTO '${quoted}'`);
|
|
@@ -2224,10 +2310,11 @@ function verifyBackupFile(backupPath) {
|
|
|
2224
2310
|
const missingTables = REQUIRED_TABLES.filter((table) => !tableExists(db, table));
|
|
2225
2311
|
const schemaVersion = missingTables.includes("schema_migrations") ? null : db.query("SELECT value FROM schema_migrations WHERE key = 'schema_version'").get()?.value ?? null;
|
|
2226
2312
|
const currentOk = missingTables.length === 0 && schemaVersion === CURRENT_SCHEMA_VERSION;
|
|
2313
|
+
const restorableV4 = schemaVersion === "4" && missingTables.length === 0;
|
|
2227
2314
|
const restorableV1 = schemaVersion === "1" && missingTables.every((table) => PROBE_TABLES.has(table) || REPORT_AUDIT_TABLES.has(table));
|
|
2228
2315
|
const restorableV2 = schemaVersion === "2" && missingTables.every((table) => REPORT_AUDIT_TABLES.has(table));
|
|
2229
2316
|
return {
|
|
2230
|
-
ok: integrity === "ok" && (currentOk || restorableV1 || restorableV2),
|
|
2317
|
+
ok: integrity === "ok" && (currentOk || restorableV4 || restorableV1 || restorableV2),
|
|
2231
2318
|
backupPath,
|
|
2232
2319
|
integrity,
|
|
2233
2320
|
schemaVersion,
|
|
@@ -2612,6 +2699,7 @@ function checkResultFromRow(row) {
|
|
|
2612
2699
|
}
|
|
2613
2700
|
function provenanceFromRow(row) {
|
|
2614
2701
|
return {
|
|
2702
|
+
workspaceId: row.workspace_id,
|
|
2615
2703
|
monitorId: row.monitor_id,
|
|
2616
2704
|
source: row.source,
|
|
2617
2705
|
sourceId: row.source_id,
|
|
@@ -2699,6 +2787,7 @@ function reportRunFromRow(row) {
|
|
|
2699
2787
|
function auditEventFromRow(row) {
|
|
2700
2788
|
return {
|
|
2701
2789
|
id: row.id,
|
|
2790
|
+
workspaceId: row.workspace_id,
|
|
2702
2791
|
action: row.action,
|
|
2703
2792
|
resourceType: row.resource_type,
|
|
2704
2793
|
resourceId: row.resource_id,
|
|
@@ -3201,10 +3290,10 @@ class UptimeService {
|
|
|
3201
3290
|
return this.reportStore().listReportRuns(options);
|
|
3202
3291
|
}
|
|
3203
3292
|
listAuditEvents(options = {}) {
|
|
3204
|
-
return this.
|
|
3293
|
+
return this.auditStore().listAuditEvents(options);
|
|
3205
3294
|
}
|
|
3206
3295
|
recordAuditEvent(input) {
|
|
3207
|
-
return this.
|
|
3296
|
+
return this.auditStore().recordAuditEvent(input);
|
|
3208
3297
|
}
|
|
3209
3298
|
async runReportSchedule(idOrName, options = {}) {
|
|
3210
3299
|
const store = this.reportStore();
|
|
@@ -3411,6 +3500,13 @@ class UptimeService {
|
|
|
3411
3500
|
}
|
|
3412
3501
|
return store;
|
|
3413
3502
|
}
|
|
3503
|
+
auditStore() {
|
|
3504
|
+
const store = this.store;
|
|
3505
|
+
if (typeof store.recordAuditEvent !== "function" || typeof store.listAuditEvents !== "function") {
|
|
3506
|
+
throw new Error("audit logging requires an audit-capable store");
|
|
3507
|
+
}
|
|
3508
|
+
return store;
|
|
3509
|
+
}
|
|
3414
3510
|
audit(action, resourceType, resourceId, message, metadata) {
|
|
3415
3511
|
this.reportStore().recordAuditEvent({
|
|
3416
3512
|
action,
|