@hasna/uptime 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -3426,7 +3426,7 @@ var REQUIRED_TABLES = [
3426
3426
  ];
3427
3427
  var PROBE_TABLES = new Set(["probe_identities", "probe_check_jobs", "probe_submissions"]);
3428
3428
  var REPORT_AUDIT_TABLES = new Set(["report_schedules", "report_runs", "audit_events"]);
3429
- var CURRENT_SCHEMA_VERSION = "3";
3429
+ var CURRENT_SCHEMA_VERSION = "4";
3430
3430
 
3431
3431
  class StaleCheckResultError extends Error {
3432
3432
  constructor(message) {
@@ -3487,7 +3487,8 @@ class UptimeStore {
3487
3487
  this.db.run(`
3488
3488
  CREATE TABLE IF NOT EXISTS monitors (
3489
3489
  id TEXT PRIMARY KEY,
3490
- name TEXT NOT NULL UNIQUE,
3490
+ workspace_id TEXT NOT NULL DEFAULT 'local',
3491
+ name TEXT NOT NULL,
3491
3492
  kind TEXT NOT NULL CHECK (kind IN ('http', 'tcp', 'browser_page')),
3492
3493
  url TEXT,
3493
3494
  host TEXT,
@@ -3502,9 +3503,11 @@ class UptimeStore {
3502
3503
  last_checked_at TEXT,
3503
3504
  revision INTEGER NOT NULL DEFAULT 1,
3504
3505
  created_at TEXT NOT NULL,
3505
- updated_at TEXT NOT NULL
3506
+ updated_at TEXT NOT NULL,
3507
+ UNIQUE (workspace_id, name)
3506
3508
  )
3507
3509
  `);
3510
+ this.ensureColumn("monitors", "workspace_id", "TEXT NOT NULL DEFAULT 'local'");
3508
3511
  this.ensureColumn("monitors", "revision", "INTEGER NOT NULL DEFAULT 1");
3509
3512
  this.ensureMonitorKindAllowsBrowserPage();
3510
3513
  this.db.run(`
@@ -3654,6 +3657,7 @@ class UptimeStore {
3654
3657
  `);
3655
3658
  this.db.query("INSERT OR REPLACE INTO schema_migrations (key, value, updated_at) VALUES ('schema_version', ?, ?)").run(CURRENT_SCHEMA_VERSION, new Date().toISOString());
3656
3659
  this.db.run("CREATE INDEX IF NOT EXISTS idx_results_monitor_time ON check_results(monitor_id, checked_at DESC)");
3660
+ this.db.run("CREATE INDEX IF NOT EXISTS idx_monitors_workspace_enabled_name ON monitors(workspace_id, enabled, name)");
3657
3661
  this.db.run("CREATE INDEX IF NOT EXISTS idx_incidents_monitor_status ON incidents(monitor_id, status)");
3658
3662
  this.db.run("CREATE INDEX IF NOT EXISTS idx_check_leases_until ON check_leases(leased_until)");
3659
3663
  this.db.run("CREATE INDEX IF NOT EXISTS idx_monitor_provenance_monitor ON monitor_provenance(monitor_id)");
@@ -3715,8 +3719,10 @@ class UptimeStore {
3715
3719
  if (this.mode === "hosted")
3716
3720
  assertHostedTargetAllowed(normalized);
3717
3721
  const now = new Date().toISOString();
3722
+ const workspaceId = normalizeWorkspaceId(options.workspaceId ?? input.workspaceId ?? "local");
3718
3723
  const monitor = {
3719
3724
  id: newId("mon"),
3725
+ workspaceId,
3720
3726
  name: normalized.name,
3721
3727
  kind: normalized.kind,
3722
3728
  url: normalized.url ?? null,
@@ -3735,22 +3741,33 @@ class UptimeStore {
3735
3741
  updatedAt: now
3736
3742
  };
3737
3743
  this.db.query(`INSERT INTO monitors (
3738
- id, name, kind, url, host, port, method, expected_status,
3744
+ id, workspace_id, name, kind, url, host, port, method, expected_status,
3739
3745
  interval_seconds, timeout_ms, retry_count, enabled, status,
3740
3746
  last_checked_at, revision, created_at, updated_at
3741
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(monitor.id, monitor.name, monitor.kind, monitor.url, monitor.host, monitor.port, monitor.method, monitor.expectedStatus, monitor.intervalSeconds, monitor.timeoutMs, monitor.retryCount, monitor.enabled ? 1 : 0, monitor.status, monitor.lastCheckedAt, monitor.revision, monitor.createdAt, monitor.updatedAt);
3747
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(monitor.id, monitor.workspaceId, monitor.name, monitor.kind, monitor.url, monitor.host, monitor.port, monitor.method, monitor.expectedStatus, monitor.intervalSeconds, monitor.timeoutMs, monitor.retryCount, monitor.enabled ? 1 : 0, monitor.status, monitor.lastCheckedAt, monitor.revision, monitor.createdAt, monitor.updatedAt);
3742
3748
  return monitor;
3743
3749
  }
3744
3750
  listMonitors(options = {}) {
3745
- const rows = options.includeDisabled ? this.db.query("SELECT * FROM monitors ORDER BY name ASC").all() : this.db.query("SELECT * FROM monitors WHERE enabled = 1 ORDER BY name ASC").all();
3751
+ const workspaceId = options.workspaceId ? normalizeWorkspaceId(options.workspaceId) : undefined;
3752
+ const clauses = [];
3753
+ const args = [];
3754
+ if (workspaceId) {
3755
+ clauses.push("workspace_id = ?");
3756
+ args.push(workspaceId);
3757
+ }
3758
+ if (!options.includeDisabled)
3759
+ clauses.push("enabled = 1");
3760
+ const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
3761
+ const rows = this.db.query(`SELECT * FROM monitors ${where} ORDER BY name ASC`).all(...args);
3746
3762
  return rows.map(monitorFromRow);
3747
3763
  }
3748
- getMonitor(idOrName) {
3749
- const row = this.db.query("SELECT * FROM monitors WHERE id = ? OR name = ?").get(idOrName, idOrName);
3764
+ getMonitor(idOrName, options = {}) {
3765
+ const workspaceId = options.workspaceId ? normalizeWorkspaceId(options.workspaceId) : undefined;
3766
+ const row = this.db.query(`SELECT * FROM monitors WHERE (id = ? OR name = ?)${workspaceId ? " AND workspace_id = ?" : ""}`).get(...workspaceId ? [idOrName, idOrName, workspaceId] : [idOrName, idOrName]);
3750
3767
  return row ? monitorFromRow(row) : null;
3751
3768
  }
3752
3769
  updateMonitor(idOrName, input, options = {}) {
3753
- const current = this.getMonitor(idOrName);
3770
+ const current = this.getMonitor(idOrName, { workspaceId: options.workspaceId });
3754
3771
  if (!current)
3755
3772
  throw new Error(`Monitor not found: ${idOrName}`);
3756
3773
  if (this.mode === "hosted") {
@@ -3774,10 +3791,10 @@ class UptimeStore {
3774
3791
  if (definitionChanged(current, next)) {
3775
3792
  this.closeOpenIncident(current.id, updatedAt);
3776
3793
  }
3777
- return this.getMonitor(current.id);
3794
+ return this.getMonitor(current.id, { workspaceId: options.workspaceId });
3778
3795
  }
3779
- deleteMonitor(idOrName) {
3780
- const current = this.getMonitor(idOrName);
3796
+ deleteMonitor(idOrName, options = {}) {
3797
+ const current = this.getMonitor(idOrName, { workspaceId: options.workspaceId });
3781
3798
  if (!current)
3782
3799
  return false;
3783
3800
  this.db.query("DELETE FROM monitors WHERE id = ?").run(current.id);
@@ -4154,7 +4171,20 @@ class UptimeStore {
4154
4171
  }
4155
4172
  listResults(options = {}) {
4156
4173
  const limit = clampLimit(options.limit ?? 50);
4157
- const rows = options.monitorId ? this.db.query("SELECT * FROM check_results WHERE monitor_id = ? ORDER BY checked_at DESC LIMIT ?").all(options.monitorId, limit) : this.db.query("SELECT * FROM check_results ORDER BY checked_at DESC LIMIT ?").all(limit);
4174
+ const workspaceId = options.workspaceId ? normalizeWorkspaceId(options.workspaceId) : undefined;
4175
+ const clauses = [];
4176
+ const args = [];
4177
+ if (options.monitorId) {
4178
+ clauses.push("check_results.monitor_id = ?");
4179
+ args.push(options.monitorId);
4180
+ }
4181
+ if (workspaceId) {
4182
+ clauses.push("monitors.workspace_id = ?");
4183
+ args.push(workspaceId);
4184
+ }
4185
+ const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
4186
+ args.push(limit);
4187
+ 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);
4158
4188
  return rows.map(checkResultFromRow);
4159
4189
  }
4160
4190
  getProvenance(source, sourceId) {
@@ -4197,24 +4227,28 @@ class UptimeStore {
4197
4227
  const clauses = [];
4198
4228
  const args = [];
4199
4229
  if (options.status) {
4200
- clauses.push("status = ?");
4230
+ clauses.push("incidents.status = ?");
4201
4231
  args.push(options.status);
4202
4232
  }
4203
4233
  if (options.monitorId) {
4204
- clauses.push("monitor_id = ?");
4234
+ clauses.push("incidents.monitor_id = ?");
4205
4235
  args.push(options.monitorId);
4206
4236
  }
4237
+ if (options.workspaceId) {
4238
+ clauses.push("monitors.workspace_id = ?");
4239
+ args.push(normalizeWorkspaceId(options.workspaceId));
4240
+ }
4207
4241
  const where = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
4208
4242
  args.push(clampLimit(options.limit ?? 50));
4209
- const rows = this.db.query(`SELECT * FROM incidents ${where} ORDER BY opened_at DESC LIMIT ?`).all(...args);
4243
+ const rows = this.db.query(`SELECT incidents.* FROM incidents JOIN monitors ON monitors.id = incidents.monitor_id ${where} ORDER BY opened_at DESC LIMIT ?`).all(...args);
4210
4244
  return rows.map(incidentFromRow);
4211
4245
  }
4212
4246
  getOpenIncident(monitorId) {
4213
4247
  const row = this.db.query("SELECT * FROM incidents WHERE monitor_id = ? AND status = 'open' ORDER BY opened_at DESC LIMIT 1").get(monitorId);
4214
4248
  return row ? incidentFromRow(row) : null;
4215
4249
  }
4216
- summary() {
4217
- const monitors = this.listMonitors({ includeDisabled: true });
4250
+ summary(options = {}) {
4251
+ const monitors = this.listMonitors({ includeDisabled: true, workspaceId: options.workspaceId });
4218
4252
  const summaries = monitors.map((monitor) => this.monitorSummary(monitor));
4219
4253
  return {
4220
4254
  generatedAt: new Date().toISOString(),
@@ -4226,11 +4260,15 @@ class UptimeStore {
4226
4260
  down: monitors.filter((m) => m.status === "down").length,
4227
4261
  paused: monitors.filter((m) => !m.enabled || m.status === "paused").length,
4228
4262
  unknown: monitors.filter((m) => m.status === "unknown").length,
4229
- openIncidents: this.countOpenIncidents()
4263
+ openIncidents: this.countOpenIncidents(options.workspaceId)
4230
4264
  }
4231
4265
  };
4232
4266
  }
4233
- countOpenIncidents() {
4267
+ countOpenIncidents(workspaceId) {
4268
+ if (workspaceId) {
4269
+ const row2 = this.db.query("SELECT COUNT(*) AS count FROM incidents JOIN monitors ON monitors.id = incidents.monitor_id WHERE incidents.status = 'open' AND monitors.workspace_id = ?").get(normalizeWorkspaceId(workspaceId));
4270
+ return Number(row2?.count ?? 0);
4271
+ }
4234
4272
  const row = this.db.query("SELECT COUNT(*) AS count FROM incidents WHERE status = 'open'").get();
4235
4273
  return Number(row?.count ?? 0);
4236
4274
  }
@@ -4294,7 +4332,9 @@ class UptimeStore {
4294
4332
  }
4295
4333
  ensureMonitorKindAllowsBrowserPage() {
4296
4334
  const row = this.db.query("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'monitors'").get();
4297
- if (!row?.sql || row.sql.includes("browser_page"))
4335
+ const needsBrowserPage = !row?.sql?.includes("browser_page");
4336
+ const needsWorkspaceUnique = Boolean(row?.sql?.includes("name TEXT NOT NULL UNIQUE"));
4337
+ if (!row?.sql || !needsBrowserPage && !needsWorkspaceUnique)
4298
4338
  return;
4299
4339
  this.db.run("PRAGMA foreign_keys = OFF");
4300
4340
  this.db.run("PRAGMA legacy_alter_table = ON");
@@ -4304,7 +4344,8 @@ class UptimeStore {
4304
4344
  this.db.run(`
4305
4345
  CREATE TABLE monitors (
4306
4346
  id TEXT PRIMARY KEY,
4307
- name TEXT NOT NULL UNIQUE,
4347
+ workspace_id TEXT NOT NULL DEFAULT 'local',
4348
+ name TEXT NOT NULL,
4308
4349
  kind TEXT NOT NULL CHECK (kind IN ('http', 'tcp', 'browser_page')),
4309
4350
  url TEXT,
4310
4351
  host TEXT,
@@ -4319,17 +4360,18 @@ class UptimeStore {
4319
4360
  last_checked_at TEXT,
4320
4361
  revision INTEGER NOT NULL DEFAULT 1,
4321
4362
  created_at TEXT NOT NULL,
4322
- updated_at TEXT NOT NULL
4363
+ updated_at TEXT NOT NULL,
4364
+ UNIQUE (workspace_id, name)
4323
4365
  )
4324
4366
  `);
4325
4367
  this.db.run(`
4326
4368
  INSERT INTO monitors (
4327
- id, name, kind, url, host, port, method, expected_status,
4369
+ id, workspace_id, name, kind, url, host, port, method, expected_status,
4328
4370
  interval_seconds, timeout_ms, retry_count, enabled, status,
4329
4371
  last_checked_at, revision, created_at, updated_at
4330
4372
  )
4331
4373
  SELECT
4332
- id, name, kind, url, host, port, method, expected_status,
4374
+ id, workspace_id, name, kind, url, host, port, method, expected_status,
4333
4375
  interval_seconds, timeout_ms, retry_count, enabled, status,
4334
4376
  last_checked_at, revision, created_at, updated_at
4335
4377
  FROM monitors_old_kind
@@ -4529,6 +4571,16 @@ function rejectControlCharacters2(value, label) {
4529
4571
  throw new Error(`${label} must not contain control characters`);
4530
4572
  }
4531
4573
  }
4574
+ function normalizeWorkspaceId(value) {
4575
+ const normalized = value.trim();
4576
+ if (!normalized)
4577
+ throw new Error("Workspace id is required");
4578
+ rejectControlCharacters2(normalized, "Workspace id");
4579
+ if (!/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/.test(normalized)) {
4580
+ throw new Error("Workspace id contains unsupported characters");
4581
+ }
4582
+ return normalized;
4583
+ }
4532
4584
  function normalizeScheduleSlot(value) {
4533
4585
  const slot = value.trim();
4534
4586
  if (!slot)
@@ -4715,6 +4767,7 @@ function assertIsoTimestamp(value, label) {
4715
4767
  function monitorFromRow(row) {
4716
4768
  return {
4717
4769
  id: row.id,
4770
+ workspaceId: row.workspace_id ?? "local",
4718
4771
  name: row.name,
4719
4772
  kind: row.kind,
4720
4773
  url: row.url,
@@ -5195,20 +5248,20 @@ class UptimeService {
5195
5248
  close() {
5196
5249
  this.store.close();
5197
5250
  }
5198
- createMonitor(input) {
5199
- return this.store.createMonitor(input);
5251
+ createMonitor(input, options = {}) {
5252
+ return this.store.createMonitor(input, options);
5200
5253
  }
5201
- updateMonitor(idOrName, input) {
5202
- return this.store.updateMonitor(idOrName, input);
5254
+ updateMonitor(idOrName, input, options = {}) {
5255
+ return this.store.updateMonitor(idOrName, input, options);
5203
5256
  }
5204
- deleteMonitor(idOrName) {
5205
- return this.store.deleteMonitor(idOrName);
5257
+ deleteMonitor(idOrName, options = {}) {
5258
+ return this.store.deleteMonitor(idOrName, options);
5206
5259
  }
5207
5260
  listMonitors(options = {}) {
5208
5261
  return this.store.listMonitors(options);
5209
5262
  }
5210
- getMonitor(idOrName) {
5211
- return this.store.getMonitor(idOrName);
5263
+ getMonitor(idOrName, options = {}) {
5264
+ return this.store.getMonitor(idOrName, options);
5212
5265
  }
5213
5266
  listResults(options = {}) {
5214
5267
  return this.store.listResults(options);
@@ -5216,8 +5269,8 @@ class UptimeService {
5216
5269
  listIncidents(options = {}) {
5217
5270
  return this.store.listIncidents(options);
5218
5271
  }
5219
- summary() {
5220
- return this.store.summary();
5272
+ summary(options = {}) {
5273
+ return this.store.summary(options);
5221
5274
  }
5222
5275
  createProbe(input) {
5223
5276
  const store = this.probeStore();
@@ -5273,7 +5326,8 @@ class UptimeService {
5273
5326
  return this.store.verifyBackup(backupPath);
5274
5327
  }
5275
5328
  buildReport(options = {}) {
5276
- return buildUptimeReport(this.summary(), options);
5329
+ const { workspaceId, ...reportOptions } = options;
5330
+ return buildUptimeReport(this.summary({ workspaceId }), reportOptions);
5277
5331
  }
5278
5332
  async sendReport(options = {}) {
5279
5333
  if (this.store.mode === "hosted" && (options.email || options.sms || options.logs)) {
@@ -5597,6 +5651,7 @@ class UptimeService {
5597
5651
  throw new Error("Probe job fencing token is invalid");
5598
5652
  if (!job.leaseExpiresAt || job.leaseExpiresAt <= new Date().toISOString())
5599
5653
  throw new Error("Probe job lease expired");
5654
+ const evidence = input.evidence ? normalizeBrowserEvidence(monitor.url ?? monitor.host ?? "https://example.invalid", input.evidence) : null;
5600
5655
  const result = this.store.recordCheckResult({
5601
5656
  monitorId: monitor.id,
5602
5657
  checkedAt: input.checkedAt,
@@ -5604,7 +5659,7 @@ class UptimeService {
5604
5659
  latencyMs: input.latencyMs,
5605
5660
  statusCode: input.statusCode ?? null,
5606
5661
  error: input.error ?? null,
5607
- evidence: input.evidence ?? null,
5662
+ evidence,
5608
5663
  attemptCount: input.attemptCount ?? 1,
5609
5664
  expectedMonitorRevision: input.monitorRevision
5610
5665
  });
@@ -6165,11 +6220,11 @@ async function handleHostedRequest(service, request, url, options) {
6165
6220
  }
6166
6221
  const apiPath = `/api${url.pathname.slice("/api/v1".length)}`;
6167
6222
  const scope = hostedScopeFor(request.method, apiPath);
6168
- requireHostedActor(request, url, options, scope);
6223
+ const actor = requireHostedActor(request, url, options, scope);
6169
6224
  if (["POST", "PATCH", "DELETE"].includes(request.method)) {
6170
6225
  validateHostedMutationOrigin(request, url, options);
6171
6226
  }
6172
- return handleApiRoute(service, request, url, apiPath, options, true);
6227
+ return handleApiRoute(service, request, url, apiPath, options, true, actor);
6173
6228
  }
6174
6229
  function validateHostedMutationOrigin(request, url, options) {
6175
6230
  const rawOrigin = request.headers.get("origin");
@@ -6184,12 +6239,12 @@ function validateHostedMutationOrigin(request, url, options) {
6184
6239
  throw new ApiError("cross-origin mutation rejected", 403);
6185
6240
  }
6186
6241
  }
6187
- async function handleApiRoute(service, request, url, apiPath, options, hosted) {
6242
+ async function handleApiRoute(service, request, url, apiPath, options, hosted, actor) {
6188
6243
  if (request.method === "GET" && apiPath === "/api/summary") {
6189
- return json(service.summary());
6244
+ return json(service.summary({ workspaceId: actor?.workspaceId }));
6190
6245
  }
6191
6246
  if (request.method === "GET" && apiPath === "/api/report") {
6192
- return json(service.buildReport());
6247
+ return json(service.buildReport({ workspaceId: actor?.workspaceId }));
6193
6248
  }
6194
6249
  if (request.method === "POST" && apiPath === "/api/report") {
6195
6250
  if (hosted)
@@ -6246,22 +6301,24 @@ async function handleApiRoute(service, request, url, apiPath, options, hosted) {
6246
6301
  }));
6247
6302
  }
6248
6303
  if (request.method === "GET" && apiPath === "/api/monitors") {
6249
- return json(service.listMonitors({ includeDisabled: url.searchParams.get("includeDisabled") === "true" }));
6304
+ return json(service.listMonitors({ includeDisabled: url.searchParams.get("includeDisabled") === "true", workspaceId: actor?.workspaceId }));
6250
6305
  }
6251
6306
  if (request.method === "POST" && apiPath === "/api/monitors") {
6252
- return json(service.createMonitor(await jsonBody(request)), 201);
6307
+ return json(service.createMonitor(await jsonBody(request), { workspaceId: actor?.workspaceId }), 201);
6253
6308
  }
6254
6309
  if (request.method === "GET" && apiPath === "/api/incidents") {
6255
6310
  const status = url.searchParams.get("status");
6256
6311
  return json(service.listIncidents({
6257
6312
  status: status === "open" || status === "closed" ? status : undefined,
6258
6313
  monitorId: url.searchParams.get("monitorId") ?? undefined,
6314
+ workspaceId: actor?.workspaceId,
6259
6315
  limit: numericParam(url, "limit", 50)
6260
6316
  }));
6261
6317
  }
6262
6318
  if (request.method === "GET" && apiPath === "/api/results") {
6263
6319
  return json(service.listResults({
6264
6320
  monitorId: url.searchParams.get("monitorId") ?? undefined,
6321
+ workspaceId: actor?.workspaceId,
6265
6322
  limit: numericParam(url, "limit", 50)
6266
6323
  }));
6267
6324
  }
@@ -6320,14 +6377,14 @@ async function handleApiRoute(service, request, url, apiPath, options, hosted) {
6320
6377
  if (monitorMatch) {
6321
6378
  const id = decodeURIComponent(monitorMatch[1]);
6322
6379
  if (request.method === "GET" && !monitorMatch[2]) {
6323
- const monitor = service.getMonitor(id);
6380
+ const monitor = service.getMonitor(id, { workspaceId: actor?.workspaceId });
6324
6381
  return monitor ? json(monitor) : json({ error: "not found" }, 404);
6325
6382
  }
6326
6383
  if (request.method === "PATCH" && !monitorMatch[2]) {
6327
- return json(service.updateMonitor(id, await jsonBody(request)));
6384
+ return json(service.updateMonitor(id, await jsonBody(request), { workspaceId: actor?.workspaceId }));
6328
6385
  }
6329
6386
  if (request.method === "DELETE" && !monitorMatch[2]) {
6330
- return json({ deleted: service.deleteMonitor(id) });
6387
+ return json({ deleted: service.deleteMonitor(id, { workspaceId: actor?.workspaceId }) });
6331
6388
  }
6332
6389
  if (request.method === "POST" && monitorMatch[2] === "check") {
6333
6390
  if (hosted)
@@ -6478,7 +6535,7 @@ function buildAwsDeploymentPlan(options = {}) {
6478
6535
  const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
6479
6536
  const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
6480
6537
  const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
6481
- const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.8");
6538
+ const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.10");
6482
6539
  const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
6483
6540
  const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
6484
6541
  const cluster = `${prefix}-${stage}`;
@@ -6610,9 +6667,9 @@ function buildAwsDeploymentPlan(options = {}) {
6610
6667
  "Disable scheduler/reporter services before data rollback.",
6611
6668
  "Restore EFS backup recovery point only after explicit operator approval and audit record."
6612
6669
  ],
6613
- spark01: [
6670
+ privateProbe: [
6614
6671
  "Create a private probe identity with a caller-managed public key.",
6615
- "Install @hasna/uptime on Spark01 and write the generated env file with mode 0600.",
6672
+ "Install @hasna/uptime on the private probe operator machine and write the generated env file with mode 0600.",
6616
6673
  "Run the private probe against the hosted /api/v1 probe endpoint once it exists."
6617
6674
  ]
6618
6675
  },
@@ -6621,7 +6678,7 @@ function buildAwsDeploymentPlan(options = {}) {
6621
6678
  "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.",
6622
6679
  "Hosted production auth/RBAC must replace broad static hosted-token operation before exposure.",
6623
6680
  "Public probe execution still needs DNS, redirect, and rebinding SSRF enforcement plus cloud check-job leases.",
6624
- "Spark01 hosted probe enrollment, claim, submit, heartbeat, revocation, and rotation are not cloud-backed yet."
6681
+ "Private probe enrollment, claim, submit, heartbeat, revocation, and rotation are not cloud-backed yet."
6625
6682
  ],
6626
6683
  requiredEvidence: [
6627
6684
  "Infrastructure PR/synth/plan from the approved infra repository.",
@@ -6631,7 +6688,7 @@ function buildAwsDeploymentPlan(options = {}) {
6631
6688
  "Single-writer ECS evidence: one web task maximum and no scheduler/public-probe/reporter EFS mounts.",
6632
6689
  "EFS encryption, access point, mount-target, AWS Backup, and restore-drill evidence.",
6633
6690
  "S3 bucket KMS, versioning, lifecycle, and public-access-block evidence.",
6634
- "Spark01 private-probe registration, key-file mode, heartbeat, and revocation evidence."
6691
+ "Private-probe registration, key-file mode, heartbeat, and revocation evidence."
6635
6692
  ],
6636
6693
  safety: {
6637
6694
  liveAwsMutation: false,
@@ -6649,16 +6706,16 @@ function buildAwsDeploymentPlan(options = {}) {
6649
6706
  }
6650
6707
  };
6651
6708
  }
6652
- function buildSpark01CloudConfig(options = {}) {
6709
+ function buildPrivateProbeCloudConfig(options = {}) {
6653
6710
  const apiUrl = clean(options.apiUrl, `https://${DEFAULT_HOSTNAME}/api/v1`);
6654
6711
  const workspaceId = clean(options.workspaceId, DEFAULT_WORKSPACE_ID);
6655
- const machineId = clean(options.machineId, "spark01");
6656
- const privateKeyFile = clean(options.probePrivateKeyFile, "~/.hasna/uptime/probes/spark01.key.pem");
6712
+ const machineId = clean(options.machineId, "private-probe-01");
6713
+ const privateKeyFile = clean(options.probePrivateKeyFile, "~/.hasna/uptime/probes/private-probe-01.key.pem");
6657
6714
  const probeId = options.probeId?.trim();
6658
6715
  const blockers = [
6659
6716
  ...probeId ? [] : ["Cloud-registered private probe id is required before writing a sourceable env file."],
6660
6717
  "Hosted probe claim and submit routes still fail closed until cloud check_jobs and workspace stores are implemented.",
6661
- "Spark01 enrollment, heartbeat, revocation, rotation, and bounded offline lease handling are not implemented yet."
6718
+ "Private probe enrollment, heartbeat, revocation, rotation, and bounded offline lease handling are not implemented yet."
6662
6719
  ];
6663
6720
  const env3 = {
6664
6721
  HASNA_UPTIME_MODE: "hosted",
@@ -6672,7 +6729,7 @@ function buildSpark01CloudConfig(options = {}) {
6672
6729
  if (probeId)
6673
6730
  env3.HASNA_UPTIME_PRIVATE_PROBE_ID = probeId;
6674
6731
  return {
6675
- kind: "open-uptime.spark01-cloud-config",
6732
+ kind: "open-uptime.private-probe-cloud-config",
6676
6733
  version: 1,
6677
6734
  generatedAt: new Date().toISOString(),
6678
6735
  status: "blocked",
@@ -6684,7 +6741,7 @@ function buildSpark01CloudConfig(options = {}) {
6684
6741
  {
6685
6742
  path: privateKeyFile,
6686
6743
  mode: "0600",
6687
- purpose: "Ed25519 private key generated on Spark01; never paste into cloud config."
6744
+ purpose: "Ed25519 private key generated on the private probe machine; never paste into cloud config."
6688
6745
  },
6689
6746
  {
6690
6747
  path: "~/.hasna/uptime/cloud.env",
@@ -6694,7 +6751,7 @@ function buildSpark01CloudConfig(options = {}) {
6694
6751
  ],
6695
6752
  commands: [
6696
6753
  "bun install -g @hasna/uptime@latest",
6697
- "Generate the Spark01 private key locally and register only its public key with the hosted control plane once registration exists.",
6754
+ "Generate the private probe key locally and register only its public key with the hosted control plane once registration exists.",
6698
6755
  "Write ~/.hasna/uptime/cloud.env from this plan, then source it for the private probe service.",
6699
6756
  "Start the private probe worker only after hosted /api/v1 probe claim/submit routes are backed by cloud jobs."
6700
6757
  ],
@@ -6703,18 +6760,18 @@ function buildSpark01CloudConfig(options = {}) {
6703
6760
  privateKeyInline: false,
6704
6761
  tokenInline: false,
6705
6762
  notes: [
6706
- "This config is hosted-targeted preflight: Spark01 must not start until cloud probe routes are backed by hosted state.",
6763
+ "This config is hosted-targeted preflight: the private probe must not start until cloud probe routes are backed by hosted state.",
6707
6764
  "The private key file path is referenced, not embedded.",
6708
6765
  "Hosted token or probe auth material must come from the machine secret store, not this generated config."
6709
6766
  ]
6710
6767
  }
6711
6768
  };
6712
6769
  }
6713
- function renderSpark01Env(config) {
6770
+ function renderPrivateProbeEnv(config) {
6714
6771
  const required = ["HASNA_UPTIME_PRIVATE_PROBE_ID"];
6715
6772
  const missing = required.filter((key) => !config.env[key]);
6716
6773
  if (missing.length > 0) {
6717
- throw new Error(`Spark01 env output requires ${missing.join(", ")}`);
6774
+ throw new Error(`private probe env output requires ${missing.join(", ")}`);
6718
6775
  }
6719
6776
  return Object.entries(config.env).map(([key, value]) => `${key}=${shellEscape(value)}`).join(`
6720
6777
  `);
@@ -7054,7 +7111,7 @@ program2.command("audit").description("List local audit events").option("--resou
7054
7111
  fail(error);
7055
7112
  }
7056
7113
  });
7057
- var cloud = program2.command("cloud").description("Generate dry-run cloud deployment and Spark01 configuration artifacts");
7114
+ var cloud = program2.command("cloud").description("Generate dry-run cloud deployment and private-probe configuration artifacts");
7058
7115
  cloud.command("plan").description("Generate a dry-run AWS deployment plan").option("--account <name>", "AWS account/profile label", "aws-profile").option("--region <region>", "AWS region", "us-east-1").option("--stage <stage>", "deployment stage", "prod").option("--hostname <hostname>", "hosted Open Uptime hostname", "uptime.example.com").option("--workspace-id <id>", "workspace id", "workspace-id").option("--vpc-id <id>", "target VPC id").option("--hosted-sqlite-db <path>", "hosted SQLite path on the EFS mount").option("--rds-instance-id <id>", "deprecated; ignored until the hosted Postgres adapter exists").option("--database-secret-name <name>", "deprecated; ignored until the hosted Postgres adapter exists").option("--ecr-repository <name>", "ECR repository name").option("--image <uri>", "container image URI").option("--runtime-package-version <version>", "published @hasna/uptime version for the AWS image builder").addOption(new Option("--protected-access-mode <mode>", "protected web access mode").choices(["cloudfront_default_domain", "alb_https_cert"]).default("cloudfront_default_domain")).option("--evidence-bucket <name>", "S3 evidence bucket name").option("-j, --json", "print JSON").action((opts) => {
7059
7116
  try {
7060
7117
  const plan = buildAwsDeploymentPlan({
@@ -7078,9 +7135,9 @@ cloud.command("plan").description("Generate a dry-run AWS deployment plan").opti
7078
7135
  fail(error);
7079
7136
  }
7080
7137
  });
7081
- cloud.command("spark01-config").description("Generate Spark01 hosted-targeted private probe preflight configuration").option("--api-url <url>", "hosted Open Uptime API URL", "https://uptime.example.com/api/v1").option("--workspace-id <id>", "workspace id", "workspace-id").option("--probe-id <id>", "cloud registered private probe id").option("--private-key-file <path>", "Spark01 private probe key file", "~/.hasna/uptime/probes/spark01.key.pem").option("--machine-id <id>", "machine id", "spark01").option("--log-level <level>", "probe log level", "info").option("--env", "print shell env file instead of summary text").option("-j, --json", "print JSON").action((opts) => {
7138
+ cloud.command("private-probe-config").description("Generate hosted-targeted private probe preflight configuration").option("--api-url <url>", "hosted Open Uptime API URL", "https://uptime.example.com/api/v1").option("--workspace-id <id>", "workspace id", "workspace-id").option("--probe-id <id>", "cloud registered private probe id").option("--private-key-file <path>", "private probe key file", "~/.hasna/uptime/probes/private-probe-01.key.pem").option("--machine-id <id>", "machine id", "private-probe-01").option("--log-level <level>", "probe log level", "info").option("--env", "print shell env file instead of summary text").option("-j, --json", "print JSON").action((opts) => {
7082
7139
  try {
7083
- const config = buildSpark01CloudConfig({
7140
+ const config = buildPrivateProbeCloudConfig({
7084
7141
  apiUrl: opts.apiUrl,
7085
7142
  workspaceId: opts.workspaceId,
7086
7143
  probeId: opts.probeId,
@@ -7089,10 +7146,10 @@ cloud.command("spark01-config").description("Generate Spark01 hosted-targeted pr
7089
7146
  logLevel: opts.logLevel
7090
7147
  });
7091
7148
  if (opts.env && !wantsJson(opts)) {
7092
- console.log(renderSpark01Env(config));
7149
+ console.log(renderPrivateProbeEnv(config));
7093
7150
  return;
7094
7151
  }
7095
- print(config, renderSpark01Config(config), opts);
7152
+ print(config, renderPrivateProbeConfig(config), opts);
7096
7153
  } catch (error) {
7097
7154
  fail(error);
7098
7155
  }
@@ -7472,7 +7529,7 @@ function renderCloudPlan(plan) {
7472
7529
  ].join(`
7473
7530
  `);
7474
7531
  }
7475
- function renderSpark01Config(config) {
7532
+ function renderPrivateProbeConfig(config) {
7476
7533
  return [
7477
7534
  `${config.machineId} ${config.mode} config`,
7478
7535
  `status: ${config.status}`,
@@ -75,7 +75,7 @@ export interface AwsDeploymentPlan {
75
75
  provision: string[];
76
76
  deploy: string[];
77
77
  rollback: string[];
78
- spark01: string[];
78
+ privateProbe: string[];
79
79
  };
80
80
  blockers: string[];
81
81
  requiredEvidence: string[];
@@ -98,7 +98,7 @@ export interface AwsServicePlan {
98
98
  environment: Record<string, string>;
99
99
  secrets: Record<string, string>;
100
100
  }
101
- export interface Spark01CloudConfigOptions {
101
+ export interface PrivateProbeCloudConfigOptions {
102
102
  apiUrl?: string;
103
103
  workspaceId?: string;
104
104
  probeId?: string;
@@ -106,8 +106,8 @@ export interface Spark01CloudConfigOptions {
106
106
  machineId?: string;
107
107
  logLevel?: string;
108
108
  }
109
- export interface Spark01CloudConfig {
110
- kind: "open-uptime.spark01-cloud-config";
109
+ export interface PrivateProbeCloudConfig {
110
+ kind: "open-uptime.private-probe-cloud-config";
111
111
  version: 1;
112
112
  generatedAt: string;
113
113
  status: "blocked";
@@ -129,6 +129,6 @@ export interface Spark01CloudConfig {
129
129
  };
130
130
  }
131
131
  export declare function buildAwsDeploymentPlan(options?: AwsDeploymentPlanOptions): AwsDeploymentPlan;
132
- export declare function buildSpark01CloudConfig(options?: Spark01CloudConfigOptions): Spark01CloudConfig;
133
- export declare function renderSpark01Env(config: Spark01CloudConfig): string;
132
+ export declare function buildPrivateProbeCloudConfig(options?: PrivateProbeCloudConfigOptions): PrivateProbeCloudConfig;
133
+ export declare function renderPrivateProbeEnv(config: PrivateProbeCloudConfig): string;
134
134
  //# sourceMappingURL=cloud-plan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-plan.d.ts","sourceRoot":"","sources":["../src/cloud-plan.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cloud-plan.d.ts","sourceRoot":"","sources":["../src/cloud-plan.ts"],"names":[],"mappings":"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"}