@hasna/uptime 0.1.6 → 0.1.7

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/.dockerignore CHANGED
@@ -2,7 +2,6 @@
2
2
  .gitignore
3
3
  .project.json
4
4
  node_modules
5
- dist
6
5
  coverage
7
6
  *.tgz
8
7
  *.log
package/CHANGELOG.md CHANGED
@@ -6,6 +6,25 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.7] - 2026-06-28
10
+
11
+ ### Added
12
+
13
+ - Explicit hosted EFS-backed SQLite runtime path with
14
+ `HASNA_UPTIME_HOSTED_SQLITE_DB` and `hosted-efs-sqlite` health metadata.
15
+ - AWS Terraform EFS file system, access point, ECS volume mount, and AWS Backup
16
+ plan for the hosted SQLite data store.
17
+ - `Dockerfile.package` plus AWS CodeBuild image-builder Terraform resources to
18
+ build the published npm package into ECR without relying on local Docker.
19
+
20
+ ### Changed
21
+
22
+ - Hosted AWS deployment artifacts no longer inject `HASNA_UPTIME_DATABASE_URL`;
23
+ the async Postgres adapter remains future work.
24
+ - The EFS-backed SQLite bridge is single-writer only: one web task maximum and
25
+ scheduler/public-probe/reporter services remain disabled until Postgres and
26
+ cloud leases exist.
27
+
9
28
  ## [0.1.6] - 2026-06-28
10
29
 
11
30
  ### Added
@@ -29,7 +48,7 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
29
48
 
30
49
  ### Added
31
50
 
32
- - Dry-run AWS deployment plan generator for the `hasna-xyz-infra` target,
51
+ - Dry-run AWS deployment plan generator for a reviewed AWS target,
33
52
  covering ECS/Fargate services, ECR image commands, ALB/RDS/S3/Secrets/Logs
34
53
  resources, rollback steps, and safety assertions.
35
54
  - Spark01 hosted-targeted private probe preflight config generator with JSON and
package/Dockerfile CHANGED
@@ -15,7 +15,8 @@ ENV NODE_ENV=production \
15
15
  HASNA_UPTIME_MODE=hosted
16
16
  WORKDIR /app
17
17
 
18
- RUN addgroup --system uptime && adduser --system --ingroup uptime uptime
18
+ RUN addgroup --system --gid 10001 uptime \
19
+ && adduser --system --uid 10001 --ingroup uptime uptime
19
20
 
20
21
  COPY --from=build /app/package.json ./package.json
21
22
  COPY --from=build /app/node_modules ./node_modules
@@ -0,0 +1,22 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ FROM oven/bun:1.3.13-slim AS runtime
4
+ ENV NODE_ENV=production \
5
+ HASNA_UPTIME_MODE=hosted
6
+ WORKDIR /app
7
+
8
+ RUN addgroup --system --gid 10001 uptime \
9
+ && adduser --system --uid 10001 --ingroup uptime uptime
10
+
11
+ COPY package.json ./package.json
12
+ COPY dist ./dist
13
+
14
+ RUN bun install --production
15
+
16
+ USER uptime
17
+ EXPOSE 3899
18
+
19
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
20
+ CMD bun -e "const r = await fetch('http://127.0.0.1:3899/health'); process.exit(r.ok ? 0 : 1)"
21
+
22
+ CMD ["bun", "dist/cli/index.js", "serve", "--mode", "hosted", "--host", "0.0.0.0", "--port", "3899"]
package/README.md CHANGED
@@ -48,7 +48,13 @@ in `docs/aws-deployment-runbook.md` is satisfied.
48
48
 
49
49
  Deployment review artifacts live in `Dockerfile` and `infra/aws`. The Terraform
50
50
  desired counts default to zero, and `uptime cloud plan --json` exposes the
51
- format/init/validate/plan commands with `applyAllowed: false`.
51
+ format/init/validate/plan commands with `applyAllowed: false`. Hosted AWS
52
+ runtime state currently uses explicit EFS-backed SQLite via
53
+ `HASNA_UPTIME_HOSTED_SQLITE_DB=/data/uptime/uptime.db` for one protected web
54
+ task maximum; do not set `HASNA_UPTIME_DATABASE_URL` until the async Postgres
55
+ adapter is implemented.
56
+ `Dockerfile.package` is used by the Terraform CodeBuild image builder to build
57
+ the published npm package into ECR from inside AWS.
52
58
 
53
59
  Private/local probes can submit signed results from another machine:
54
60
 
package/dist/api.js CHANGED
@@ -820,10 +820,12 @@ function ensureUptimeHome() {
820
820
  }
821
821
 
822
822
  // src/store.ts
823
- import { copyFileSync, existsSync, mkdirSync as mkdirSync2, statSync } from "fs";
823
+ import { copyFileSync, existsSync, mkdirSync as mkdirSync2, statfsSync, statSync } from "fs";
824
824
  import { dirname, join as join2 } from "path";
825
825
  import { randomUUID as randomUUID2 } from "crypto";
826
826
  import { Database } from "bun:sqlite";
827
+ var DEFAULT_HOSTED_SQLITE_DB_PATH = "/data/uptime/uptime.db";
828
+ var NFS_SUPER_MAGIC = 26985;
827
829
  var SECRET_URL_PARAM_PATTERN = /(token|secret|password|passwd|api[_-]?key|access[_-]?token|auth|credential|session)/i;
828
830
  var REQUIRED_TABLES = [
829
831
  "schema_migrations",
@@ -860,18 +862,39 @@ class UptimeStore {
860
862
  this.mode = resolveRuntimeMode(options.mode ?? "local");
861
863
  const cloudDatabaseUrl = options.cloudDatabaseUrl ?? process.env.HASNA_UPTIME_DATABASE_URL;
862
864
  if (this.mode === "hosted" && cloudDatabaseUrl) {
863
- throw new Error("hosted cloud database adapter is not implemented yet");
865
+ throw new Error("hosted Postgres adapter is not implemented yet; use HASNA_UPTIME_HOSTED_SQLITE_DB on cloud-mounted storage for the current hosted deployment path");
864
866
  }
865
- if (this.mode === "hosted" && !allowHostedLocalStore(options.allowHostedLocalStore)) {
866
- throw new Error("hosted mode requires a cloud data layer; set HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE=1 only for explicit local fallback testing");
867
+ const hostedSqliteDbPath = options.hostedSqliteDbPath ?? process.env.HASNA_UPTIME_HOSTED_SQLITE_DB;
868
+ if (this.mode === "hosted" && hostedSqliteDbPath) {
869
+ if (hostedSqliteDbPath === ":memory:" || !hostedSqliteDbPath.startsWith("/")) {
870
+ throw new Error("HASNA_UPTIME_HOSTED_SQLITE_DB must be an absolute path on mounted cloud storage");
871
+ }
872
+ const approvedHostedPath = hostedSqliteDbPath === DEFAULT_HOSTED_SQLITE_DB_PATH;
873
+ if (!approvedHostedPath && !allowHostedLocalStore(options.allowHostedLocalStore)) {
874
+ throw new Error(`HASNA_UPTIME_HOSTED_SQLITE_DB must be ${DEFAULT_HOSTED_SQLITE_DB_PATH}; set HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE=1 only for explicit local fallback testing`);
875
+ }
876
+ const verifiedCloudMount = approvedHostedPath && isNfsMount(dirname(hostedSqliteDbPath));
877
+ if (approvedHostedPath && !verifiedCloudMount && !allowHostedLocalStore(options.allowHostedLocalStore)) {
878
+ throw new Error(`${DEFAULT_HOSTED_SQLITE_DB_PATH} must be on a mounted EFS/NFS filesystem; refusing to create hosted task-local SQLite`);
879
+ }
880
+ this.dataMode = verifiedCloudMount ? "hosted-efs-sqlite" : "hosted-local-sqlite";
881
+ this.dbPath = hostedSqliteDbPath;
882
+ } else if (this.mode === "hosted") {
883
+ if (!allowHostedLocalStore(options.allowHostedLocalStore)) {
884
+ throw new Error("hosted mode requires HASNA_UPTIME_HOSTED_SQLITE_DB on mounted cloud storage; set HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE=1 only for explicit local fallback testing");
885
+ }
886
+ this.dataMode = "hosted-local-sqlite";
887
+ this.dbPath = options.dbPath ?? uptimeHostedFallbackDbPath();
888
+ } else {
889
+ this.dataMode = "local-sqlite";
890
+ this.dbPath = options.dbPath ?? uptimeDbPath();
867
891
  }
868
- this.dataMode = this.mode === "hosted" ? "hosted-local-sqlite" : "local-sqlite";
869
- this.dbPath = options.dbPath ?? (this.mode === "hosted" ? uptimeHostedFallbackDbPath() : uptimeDbPath());
870
- if (this.dbPath !== ":memory:") {
892
+ if (this.dbPath !== ":memory:" && this.dataMode !== "hosted-efs-sqlite") {
871
893
  mkdirSync2(dirname(this.dbPath), { recursive: true });
872
894
  }
873
895
  this.db = new Database(this.dbPath, { create: true });
874
- this.db.run("PRAGMA journal_mode = WAL");
896
+ this.db.run(this.dataMode === "hosted-efs-sqlite" ? "PRAGMA journal_mode = DELETE" : "PRAGMA journal_mode = WAL");
897
+ this.db.run("PRAGMA busy_timeout = 5000");
875
898
  this.db.run("PRAGMA foreign_keys = ON");
876
899
  this.migrate();
877
900
  }
@@ -1751,6 +1774,13 @@ function resolveRuntimeMode(mode) {
1751
1774
  function allowHostedLocalStore(value) {
1752
1775
  return value === true || process.env.HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE === "1";
1753
1776
  }
1777
+ function isNfsMount(path) {
1778
+ try {
1779
+ return statfsSync(path).type === NFS_SUPER_MAGIC;
1780
+ } catch {
1781
+ return false;
1782
+ }
1783
+ }
1754
1784
  function verifyBackupFile(backupPath) {
1755
1785
  const db = new Database(backupPath, { readonly: true });
1756
1786
  try {
package/dist/cli/index.js CHANGED
@@ -3381,7 +3381,7 @@ function stableJson(value) {
3381
3381
  }
3382
3382
 
3383
3383
  // src/store.ts
3384
- import { copyFileSync, existsSync, mkdirSync as mkdirSync2, statSync } from "fs";
3384
+ import { copyFileSync, existsSync, mkdirSync as mkdirSync2, statfsSync, statSync } from "fs";
3385
3385
  import { dirname, join as join2 } from "path";
3386
3386
  import { randomUUID as randomUUID2 } from "crypto";
3387
3387
  import { Database } from "bun:sqlite";
@@ -3406,6 +3406,8 @@ function ensureUptimeHome() {
3406
3406
  }
3407
3407
 
3408
3408
  // src/store.ts
3409
+ var DEFAULT_HOSTED_SQLITE_DB_PATH = "/data/uptime/uptime.db";
3410
+ var NFS_SUPER_MAGIC = 26985;
3409
3411
  var SECRET_URL_PARAM_PATTERN = /(token|secret|password|passwd|api[_-]?key|access[_-]?token|auth|credential|session)/i;
3410
3412
  var REQUIRED_TABLES = [
3411
3413
  "schema_migrations",
@@ -3442,18 +3444,39 @@ class UptimeStore {
3442
3444
  this.mode = resolveRuntimeMode(options.mode ?? "local");
3443
3445
  const cloudDatabaseUrl = options.cloudDatabaseUrl ?? process.env.HASNA_UPTIME_DATABASE_URL;
3444
3446
  if (this.mode === "hosted" && cloudDatabaseUrl) {
3445
- throw new Error("hosted cloud database adapter is not implemented yet");
3447
+ throw new Error("hosted Postgres adapter is not implemented yet; use HASNA_UPTIME_HOSTED_SQLITE_DB on cloud-mounted storage for the current hosted deployment path");
3446
3448
  }
3447
- if (this.mode === "hosted" && !allowHostedLocalStore(options.allowHostedLocalStore)) {
3448
- throw new Error("hosted mode requires a cloud data layer; set HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE=1 only for explicit local fallback testing");
3449
+ const hostedSqliteDbPath = options.hostedSqliteDbPath ?? process.env.HASNA_UPTIME_HOSTED_SQLITE_DB;
3450
+ if (this.mode === "hosted" && hostedSqliteDbPath) {
3451
+ if (hostedSqliteDbPath === ":memory:" || !hostedSqliteDbPath.startsWith("/")) {
3452
+ throw new Error("HASNA_UPTIME_HOSTED_SQLITE_DB must be an absolute path on mounted cloud storage");
3453
+ }
3454
+ const approvedHostedPath = hostedSqliteDbPath === DEFAULT_HOSTED_SQLITE_DB_PATH;
3455
+ if (!approvedHostedPath && !allowHostedLocalStore(options.allowHostedLocalStore)) {
3456
+ throw new Error(`HASNA_UPTIME_HOSTED_SQLITE_DB must be ${DEFAULT_HOSTED_SQLITE_DB_PATH}; set HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE=1 only for explicit local fallback testing`);
3457
+ }
3458
+ const verifiedCloudMount = approvedHostedPath && isNfsMount(dirname(hostedSqliteDbPath));
3459
+ if (approvedHostedPath && !verifiedCloudMount && !allowHostedLocalStore(options.allowHostedLocalStore)) {
3460
+ throw new Error(`${DEFAULT_HOSTED_SQLITE_DB_PATH} must be on a mounted EFS/NFS filesystem; refusing to create hosted task-local SQLite`);
3461
+ }
3462
+ this.dataMode = verifiedCloudMount ? "hosted-efs-sqlite" : "hosted-local-sqlite";
3463
+ this.dbPath = hostedSqliteDbPath;
3464
+ } else if (this.mode === "hosted") {
3465
+ if (!allowHostedLocalStore(options.allowHostedLocalStore)) {
3466
+ throw new Error("hosted mode requires HASNA_UPTIME_HOSTED_SQLITE_DB on mounted cloud storage; set HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE=1 only for explicit local fallback testing");
3467
+ }
3468
+ this.dataMode = "hosted-local-sqlite";
3469
+ this.dbPath = options.dbPath ?? uptimeHostedFallbackDbPath();
3470
+ } else {
3471
+ this.dataMode = "local-sqlite";
3472
+ this.dbPath = options.dbPath ?? uptimeDbPath();
3449
3473
  }
3450
- this.dataMode = this.mode === "hosted" ? "hosted-local-sqlite" : "local-sqlite";
3451
- this.dbPath = options.dbPath ?? (this.mode === "hosted" ? uptimeHostedFallbackDbPath() : uptimeDbPath());
3452
- if (this.dbPath !== ":memory:") {
3474
+ if (this.dbPath !== ":memory:" && this.dataMode !== "hosted-efs-sqlite") {
3453
3475
  mkdirSync2(dirname(this.dbPath), { recursive: true });
3454
3476
  }
3455
3477
  this.db = new Database(this.dbPath, { create: true });
3456
- this.db.run("PRAGMA journal_mode = WAL");
3478
+ this.db.run(this.dataMode === "hosted-efs-sqlite" ? "PRAGMA journal_mode = DELETE" : "PRAGMA journal_mode = WAL");
3479
+ this.db.run("PRAGMA busy_timeout = 5000");
3457
3480
  this.db.run("PRAGMA foreign_keys = ON");
3458
3481
  this.migrate();
3459
3482
  }
@@ -4333,6 +4356,13 @@ function resolveRuntimeMode(mode) {
4333
4356
  function allowHostedLocalStore(value) {
4334
4357
  return value === true || process.env.HASNA_UPTIME_ALLOW_HOSTED_LOCAL_STORE === "1";
4335
4358
  }
4359
+ function isNfsMount(path) {
4360
+ try {
4361
+ return statfsSync(path).type === NFS_SUPER_MAGIC;
4362
+ } catch {
4363
+ return false;
4364
+ }
4365
+ }
4336
4366
  function verifyBackupFile(backupPath) {
4337
4367
  const db = new Database(backupPath, { readonly: true });
4338
4368
  try {
@@ -6388,14 +6418,14 @@ class ApiError extends Error {
6388
6418
  }
6389
6419
 
6390
6420
  // src/cloud-plan.ts
6391
- var DEFAULT_ACCOUNT = "hasna-xyz-infra";
6421
+ var DEFAULT_ACCOUNT = "aws-profile";
6392
6422
  var DEFAULT_REGION = "us-east-1";
6393
6423
  var DEFAULT_STAGE = "prod";
6394
6424
  var DEFAULT_PREFIX = "open-uptime";
6395
- var DEFAULT_HOSTNAME = "uptime.hasna.xyz";
6396
- var DEFAULT_WORKSPACE_ID = "wks_2tyysw05cwap";
6397
- var DEFAULT_VPC_ID = "vpc-04c7f7abc1d3c3f56";
6398
- var DEFAULT_RDS = "hasna-xyz-infra-apps-prod-postgres";
6425
+ var DEFAULT_HOSTNAME = "uptime.example.com";
6426
+ var DEFAULT_WORKSPACE_ID = "workspace-id";
6427
+ var DEFAULT_VPC_ID = "vpc-xxxxxxxx";
6428
+ var DEFAULT_HOSTED_SQLITE_DB = "/data/uptime/uptime.db";
6399
6429
  function buildAwsDeploymentPlan(options = {}) {
6400
6430
  const region = clean(options.region, DEFAULT_REGION);
6401
6431
  const stage = clean(options.stage, DEFAULT_STAGE);
@@ -6403,37 +6433,39 @@ function buildAwsDeploymentPlan(options = {}) {
6403
6433
  const accountName = clean(options.accountName, DEFAULT_ACCOUNT);
6404
6434
  const hostname = clean(options.hostname, DEFAULT_HOSTNAME);
6405
6435
  const workspaceId = clean(options.workspaceId, DEFAULT_WORKSPACE_ID);
6406
- const ecrRepository = clean(options.ecrRepository, `hasna/opensource/${prefix}`);
6436
+ const ecrRepository = clean(options.ecrRepository, prefix);
6407
6437
  const imageRepositoryUri = `<account-id>.dkr.ecr.${region}.amazonaws.com/${ecrRepository}`;
6408
6438
  const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
6409
6439
  const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
6440
+ const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
6441
+ const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.7");
6410
6442
  const cluster = `${prefix}-${stage}`;
6411
6443
  const secrets = {
6412
- database: clean(options.databaseSecretName, `hasna/xyz/opensource/uptime/${stage}/rds`),
6413
- appEnv: clean(options.appEnvSecretName, `hasna/xyz/opensource/uptime/${stage}/app/env`),
6414
- hostedToken: clean(options.hostedTokenSecretName, `hasna/xyz/opensource/uptime/${stage}/hosted-token`),
6415
- publicProbe: clean(options.publicProbeSecretName, `hasna/xyz/opensource/uptime/${stage}/probe/public`),
6416
- privateProbe: clean(options.privateProbeSecretName, `hasna/xyz/opensource/uptime/${stage}/probe/private`),
6417
- reporting: clean(options.reportingSecretName, `hasna/xyz/opensource/uptime/${stage}/reporting`)
6444
+ appEnv: clean(options.appEnvSecretName, `open-uptime/${stage}/app/env`),
6445
+ hostedToken: clean(options.hostedTokenSecretName, `open-uptime/${stage}/hosted-token`),
6446
+ publicProbe: clean(options.publicProbeSecretName, `open-uptime/${stage}/probe/public`),
6447
+ privateProbe: clean(options.privateProbeSecretName, `open-uptime/${stage}/probe/private`),
6448
+ reporting: clean(options.reportingSecretName, `open-uptime/${stage}/reporting`)
6418
6449
  };
6419
6450
  const services = [
6420
- servicePlan(prefix, stage, "web", 2, image, workspaceId, secrets, {
6451
+ servicePlan(prefix, stage, "web", 1, image, workspaceId, secrets, {
6421
6452
  HASNA_UPTIME_MODE: "hosted",
6453
+ HASNA_UPTIME_HOSTED_SQLITE_DB: hostedSqliteDbPath,
6422
6454
  HASNA_UPTIME_WORKSPACE_ID: workspaceId,
6423
6455
  HASNA_UPTIME_HOSTNAME: hostname
6424
6456
  }),
6425
- servicePlan(prefix, stage, "scheduler", 1, image, workspaceId, secrets, {
6457
+ servicePlan(prefix, stage, "scheduler", 0, image, workspaceId, secrets, {
6426
6458
  HASNA_UPTIME_MODE: "hosted",
6427
6459
  HASNA_UPTIME_WORKSPACE_ID: workspaceId,
6428
6460
  HASNA_UPTIME_COMPONENT: "scheduler"
6429
6461
  }),
6430
- servicePlan(prefix, stage, "public-probe", 1, image, workspaceId, secrets, {
6462
+ servicePlan(prefix, stage, "public-probe", 0, image, workspaceId, secrets, {
6431
6463
  HASNA_UPTIME_MODE: "hosted",
6432
6464
  HASNA_UPTIME_WORKSPACE_ID: workspaceId,
6433
6465
  HASNA_UPTIME_COMPONENT: "public-probe",
6434
6466
  HASNA_UPTIME_PROBE_LOCATION: region
6435
6467
  }),
6436
- servicePlan(prefix, stage, "reporter", 1, image, workspaceId, secrets, {
6468
+ servicePlan(prefix, stage, "reporter", 0, image, workspaceId, secrets, {
6437
6469
  HASNA_UPTIME_MODE: "hosted",
6438
6470
  HASNA_UPTIME_WORKSPACE_ID: workspaceId,
6439
6471
  HASNA_UPTIME_COMPONENT: "reporter"
@@ -6446,7 +6478,7 @@ function buildAwsDeploymentPlan(options = {}) {
6446
6478
  ];
6447
6479
  return {
6448
6480
  kind: "open-uptime.aws-deployment-plan",
6449
- version: 1,
6481
+ version: 2,
6450
6482
  generatedAt: new Date().toISOString(),
6451
6483
  status: "blocked",
6452
6484
  canApply: false,
@@ -6459,10 +6491,13 @@ function buildAwsDeploymentPlan(options = {}) {
6459
6491
  mode: "hosted",
6460
6492
  resources: {
6461
6493
  ecrRepository,
6494
+ imageBuilder: `${prefix}-${stage}-image-builder`,
6462
6495
  ecsCluster: cluster,
6463
6496
  services,
6464
6497
  vpcId: clean(options.vpcId, DEFAULT_VPC_ID),
6465
- rdsInstanceId: clean(options.rdsInstanceId, DEFAULT_RDS),
6498
+ efsFileSystem: `${prefix}-${stage}-data`,
6499
+ efsAccessPoint: `${prefix}-${stage}-uptime`,
6500
+ hostedSqliteDbPath,
6466
6501
  evidenceBucket,
6467
6502
  loadBalancer: `${prefix}-${stage}-alb`,
6468
6503
  targetGroups: [`${prefix}-${stage}-web-tg`],
@@ -6472,7 +6507,8 @@ function buildAwsDeploymentPlan(options = {}) {
6472
6507
  `${prefix}-${stage}-scheduler-sg`,
6473
6508
  `${prefix}-${stage}-public-probe-sg`,
6474
6509
  `${prefix}-${stage}-reporter-sg`,
6475
- `${prefix}-${stage}-migration-sg`
6510
+ `${prefix}-${stage}-migration-sg`,
6511
+ `${prefix}-${stage}-efs-sg`
6476
6512
  ],
6477
6513
  secrets,
6478
6514
  logGroups: services.map((service) => service.logGroup),
@@ -6484,10 +6520,10 @@ function buildAwsDeploymentPlan(options = {}) {
6484
6520
  image: {
6485
6521
  repository: ecrRepository,
6486
6522
  uri: image,
6487
- dockerfile: "Dockerfile",
6488
- buildCommand: `docker build --pull -t ${imageRepositoryUri}:<git-sha> .`,
6523
+ dockerfile: "Dockerfile.package",
6524
+ buildCommand: `BLOCKED: after infra approval, AWS CodeBuild builds Dockerfile.package from @hasna/uptime@${runtimePackageVersion} into ${imageRepositoryUri}`,
6489
6525
  pushCommands: [
6490
- "BLOCKED: push only from approved CI/CD after the ECR repository and image digest policy exist",
6526
+ `BLOCKED: start ${prefix}-${stage}-image-builder only through the approved deploy pipeline after @hasna/uptime@${runtimePackageVersion} is published`,
6491
6527
  "BLOCKED: deploy services by immutable image digest, not by mutable tags"
6492
6528
  ]
6493
6529
  },
@@ -6502,19 +6538,22 @@ function buildAwsDeploymentPlan(options = {}) {
6502
6538
  runbook: {
6503
6539
  preflight: [
6504
6540
  `aws sts get-caller-identity --profile ${accountName}`,
6505
- `aws rds describe-db-instances --db-instance-identifier ${clean(options.rdsInstanceId, DEFAULT_RDS)} --region ${region}`,
6506
6541
  `aws ec2 describe-vpcs --vpc-ids ${clean(options.vpcId, DEFAULT_VPC_ID)} --region ${region}`,
6542
+ `aws efs describe-file-systems --region ${region}`,
6507
6543
  "Confirm the infra repository and Terraform/CloudFormation owner before live mutation."
6508
6544
  ],
6509
6545
  provision: [
6510
6546
  `Infra PR must declare or update ECR repository ${ecrRepository}.`,
6547
+ `Infra PR must declare CodeBuild image builder ${prefix}-${stage}-image-builder for @hasna/uptime@${runtimePackageVersion}.`,
6511
6548
  `Infra PR must declare hardened S3 evidence bucket ${evidenceBucket} with KMS, versioning, lifecycle, and public access block.`,
6549
+ `Infra PR must declare encrypted EFS ${prefix}-${stage}-data with access point, mount targets, and AWS Backup plan.`,
6512
6550
  `Infra PR must declare ECS/Fargate cluster ${cluster}, ALB, target groups, security groups, IAM roles, CloudWatch log groups, and Secrets Manager refs.`,
6513
6551
  "Only apply the infra plan from the approved infrastructure repository after review evidence is attached."
6514
6552
  ],
6515
6553
  deploy: [
6516
6554
  "Build and publish the image only after the Dockerfile/container target is reviewed.",
6517
- "Run the migration task with the migrator role before web/scheduler/probe services.",
6555
+ `Start the AWS image builder for @hasna/uptime@${runtimePackageVersion} and record the pushed image digest.`,
6556
+ "For the EFS SQLite bridge, do not run migration, scheduler, public-probe, or reporter tasks; keep them at desired count 0 until Postgres and cloud leases exist.",
6518
6557
  `Register task definitions for ${services.map((service) => service.name).join(", ")} using valueFrom secrets.`,
6519
6558
  `Update ECS services in cluster ${cluster} one component at a time through the approved deploy pipeline.`,
6520
6559
  `Create Route53/edge record for ${hostname} only after ALB health checks pass and auth denial smokes succeed.`
@@ -6523,7 +6562,7 @@ function buildAwsDeploymentPlan(options = {}) {
6523
6562
  "Keep previous task definition ARNs before each service update.",
6524
6563
  "Rollback through the approved deploy pipeline to the previously recorded task definition ARNs.",
6525
6564
  "Disable scheduler/reporter services before data rollback.",
6526
- "Restore RDS snapshot only after explicit operator approval and audit record."
6565
+ "Restore EFS backup recovery point only after explicit operator approval and audit record."
6527
6566
  ],
6528
6567
  spark01: [
6529
6568
  "Create a private probe identity with a caller-managed public key.",
@@ -6532,18 +6571,19 @@ function buildAwsDeploymentPlan(options = {}) {
6532
6571
  ]
6533
6572
  },
6534
6573
  blockers: [
6535
- "The hasna-xyz-infra infrastructure owner repository was not found in this workspace.",
6536
- "Hosted Postgres storage adapter and migrations are not implemented.",
6574
+ "The infrastructure owner repository was not found in this workspace.",
6575
+ "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.",
6537
6576
  "Hosted production auth/RBAC must replace broad static hosted-token operation before exposure.",
6538
6577
  "Public probe execution still needs DNS, redirect, and rebinding SSRF enforcement plus cloud check-job leases.",
6539
6578
  "Spark01 hosted probe enrollment, claim, submit, heartbeat, revocation, and rotation are not cloud-backed yet."
6540
6579
  ],
6541
6580
  requiredEvidence: [
6542
6581
  "Infrastructure PR/synth/plan from the approved infra repository.",
6543
- "Container build smoke and immutable image digest.",
6582
+ "CodeBuild image-builder run, container smoke, and immutable image digest.",
6544
6583
  "ECS task definitions using secrets.valueFrom only.",
6545
6584
  "ALB/TLS/DNS/auth denial smokes and web alarm checks.",
6546
- "RDS TLS, backups/PITR, scoped roles, and migration dry-run evidence.",
6585
+ "Single-writer ECS evidence: one web task maximum and no scheduler/public-probe/reporter EFS mounts.",
6586
+ "EFS encryption, access point, mount-target, AWS Backup, and restore-drill evidence.",
6547
6587
  "S3 bucket KMS, versioning, lifecycle, and public-access-block evidence.",
6548
6588
  "Spark01 private-probe registration, key-file mode, heartbeat, and revocation evidence."
6549
6589
  ],
@@ -6553,7 +6593,9 @@ function buildAwsDeploymentPlan(options = {}) {
6553
6593
  hostedLocalSqliteAllowed: false,
6554
6594
  notes: [
6555
6595
  "This plan generator does not call AWS.",
6556
- "Hosted runtime must use Postgres; SQLite remains local/dev fallback only.",
6596
+ "Blocked plan output intentionally avoids copy-pastable AWS mutation commands.",
6597
+ "Hosted runtime uses explicit EFS-backed SQLite at HASNA_UPTIME_HOSTED_SQLITE_DB until the async Postgres adapter exists.",
6598
+ "Do not set HASNA_UPTIME_DATABASE_URL for hosted tasks until the Postgres adapter is implemented.",
6557
6599
  "Secrets are represented as secret names/refs and must be injected with valueFrom.",
6558
6600
  "Actual deploy belongs in the deploy_release_operate_final goal node after infra review."
6559
6601
  ]
@@ -6645,7 +6687,7 @@ function servicePlan(prefix, stage, role, desiredCount, image, workspaceId, secr
6645
6687
  HASNA_UPTIME_IMAGE: image,
6646
6688
  ...environment
6647
6689
  },
6648
- secrets: role === "web" ? { HASNA_UPTIME_DATABASE_URL: secrets.database, APP_ENV: secrets.appEnv, HASNA_UPTIME_HOSTED_TOKEN: secrets.hostedToken } : role === "public-probe" ? { PROBE_CONFIG: secrets.publicProbe } : role === "reporter" ? { HASNA_UPTIME_DATABASE_URL: secrets.database, REPORTING_CONFIG: secrets.reporting } : { HASNA_UPTIME_DATABASE_URL: secrets.database, APP_ENV: secrets.appEnv }
6690
+ secrets: role === "web" ? { APP_ENV: secrets.appEnv, HASNA_UPTIME_HOSTED_TOKEN: secrets.hostedToken } : role === "public-probe" ? { PROBE_CONFIG: secrets.publicProbe } : role === "reporter" ? { REPORTING_CONFIG: secrets.reporting } : { APP_ENV: secrets.appEnv }
6649
6691
  };
6650
6692
  }
6651
6693
  function clean(value, fallback) {
@@ -6966,7 +7008,7 @@ program2.command("audit").description("List local audit events").option("--resou
6966
7008
  }
6967
7009
  });
6968
7010
  var cloud = program2.command("cloud").description("Generate dry-run cloud deployment and Spark01 configuration artifacts");
6969
- cloud.command("plan").description("Generate a dry-run AWS deployment plan for hasna-xyz-infra").option("--account <name>", "AWS account/profile label", "hasna-xyz-infra").option("--region <region>", "AWS region", "us-east-1").option("--stage <stage>", "deployment stage", "prod").option("--hostname <hostname>", "hosted Open Uptime hostname", "uptime.hasna.xyz").option("--workspace-id <id>", "workspace id", "wks_2tyysw05cwap").option("--vpc-id <id>", "target VPC id").option("--rds-instance-id <id>", "existing RDS instance id").option("--ecr-repository <name>", "ECR repository name").option("--image <uri>", "container image URI").option("--evidence-bucket <name>", "S3 evidence bucket name").option("-j, --json", "print JSON").action((opts) => {
7011
+ 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").option("--evidence-bucket <name>", "S3 evidence bucket name").option("-j, --json", "print JSON").action((opts) => {
6970
7012
  try {
6971
7013
  const plan = buildAwsDeploymentPlan({
6972
7014
  accountName: opts.account,
@@ -6975,9 +7017,12 @@ cloud.command("plan").description("Generate a dry-run AWS deployment plan for ha
6975
7017
  hostname: opts.hostname,
6976
7018
  workspaceId: opts.workspaceId,
6977
7019
  vpcId: opts.vpcId,
7020
+ hostedSqliteDbPath: opts.hostedSqliteDb,
6978
7021
  rdsInstanceId: opts.rdsInstanceId,
7022
+ databaseSecretName: opts.databaseSecretName,
6979
7023
  ecrRepository: opts.ecrRepository,
6980
7024
  image: opts.image,
7025
+ runtimePackageVersion: opts.runtimePackageVersion,
6981
7026
  evidenceBucket: opts.evidenceBucket
6982
7027
  });
6983
7028
  print(plan, renderCloudPlan(plan), opts);
@@ -6985,7 +7030,7 @@ cloud.command("plan").description("Generate a dry-run AWS deployment plan for ha
6985
7030
  fail(error);
6986
7031
  }
6987
7032
  });
6988
- cloud.command("spark01-config").description("Generate Spark01 hosted-targeted private probe preflight configuration").option("--api-url <url>", "hosted Open Uptime API URL", "https://uptime.hasna.xyz/api/v1").option("--workspace-id <id>", "workspace id", "wks_2tyysw05cwap").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) => {
7033
+ 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) => {
6989
7034
  try {
6990
7035
  const config = buildSpark01CloudConfig({
6991
7036
  apiUrl: opts.apiUrl,
@@ -7185,7 +7230,7 @@ program2.command("restore <backup-path>").description("Restore a verified local
7185
7230
  fail(error);
7186
7231
  }
7187
7232
  });
7188
- program2.command("serve").description("Serve the local API and dashboard").option("--host <host>", "host to bind", "127.0.0.1").option("--port <port>", "port", parseInteger, 3899).option("--check", "run the scheduler while serving").addOption(new Option("--mode <mode>", "runtime mode").choices(["local", "hosted"]).default("local")).option("--api-token <token>", "token required for non-loopback mutation hosts").option("--hosted-token <token>", "scoped hosted-mode token").option("--allow-hosted-local-store", "allow hosted mode to use local SQLite as an explicit fallback").option("--allow-unsafe-remote-mutations", "allow state-changing requests from non-loopback hosts without a token").option("-j, --json", "print JSON").action((opts) => {
7233
+ program2.command("serve").description("Serve the local API and dashboard").option("--host <host>", "host to bind", "127.0.0.1").option("--port <port>", "port", parseInteger, 3899).option("--check", "run the scheduler while serving").addOption(new Option("--mode <mode>", "runtime mode").choices(["local", "hosted"]).default("local")).option("--api-token <token>", "token required for non-loopback mutation hosts").option("--hosted-token <token>", "scoped hosted-mode token").option("--hosted-sqlite-db <path>", "absolute SQLite database path on hosted cloud-mounted storage").option("--allow-hosted-local-store", "allow hosted mode to use local SQLite as an explicit fallback").option("--allow-unsafe-remote-mutations", "allow state-changing requests from non-loopback hosts without a token").option("-j, --json", "print JSON").action((opts) => {
7189
7234
  try {
7190
7235
  const { server } = serveUptime({
7191
7236
  host: opts.host,
@@ -7194,6 +7239,7 @@ program2.command("serve").description("Serve the local API and dashboard").optio
7194
7239
  mode: opts.mode,
7195
7240
  apiToken: opts.apiToken,
7196
7241
  hostedToken: opts.hostedToken,
7242
+ hostedSqliteDbPath: opts.hostedSqliteDb,
7197
7243
  allowHostedLocalStore: opts.allowHostedLocalStore,
7198
7244
  allowUnsafeRemoteMutations: opts.allowUnsafeRemoteMutations
7199
7245
  });
@@ -7364,10 +7410,12 @@ function renderCloudPlan(plan) {
7364
7410
  `host: ${plan.hostname}`,
7365
7411
  `cluster: ${plan.resources.ecsCluster}`,
7366
7412
  `image: ${plan.image.uri}`,
7413
+ `image builder: ${plan.resources.imageBuilder}`,
7367
7414
  `dockerfile: ${plan.image.dockerfile}`,
7368
7415
  `infra: ${plan.infra.path}`,
7369
7416
  `vpc: ${plan.resources.vpcId}`,
7370
- `rds: ${plan.resources.rdsInstanceId}`,
7417
+ `efs: ${plan.resources.efsFileSystem}`,
7418
+ `hosted sqlite: ${plan.resources.hostedSqliteDbPath}`,
7371
7419
  `services: ${plan.resources.services.map((service2) => `${service2.name}:${service2.desiredCount}/${service2.targetDesiredCount}`).join(", ")}`,
7372
7420
  `evidence bucket: ${plan.resources.evidenceBucket}`,
7373
7421
  `blockers: ${plan.blockers.length}`,
@@ -6,12 +6,16 @@ export interface AwsDeploymentPlanOptions {
6
6
  hostname?: string;
7
7
  workspaceId?: string;
8
8
  vpcId?: string;
9
- rdsInstanceId?: string;
10
9
  ecrRepository?: string;
11
10
  image?: string;
12
11
  evidenceBucket?: string;
13
- hostedTokenSecretName?: string;
12
+ hostedSqliteDbPath?: string;
13
+ runtimePackageVersion?: string;
14
+ /** @deprecated Postgres is target-state only until the async adapter is implemented. */
15
+ rdsInstanceId?: string;
16
+ /** @deprecated Postgres is target-state only until the async adapter is implemented. */
14
17
  databaseSecretName?: string;
18
+ hostedTokenSecretName?: string;
15
19
  appEnvSecretName?: string;
16
20
  publicProbeSecretName?: string;
17
21
  privateProbeSecretName?: string;
@@ -19,7 +23,7 @@ export interface AwsDeploymentPlanOptions {
19
23
  }
20
24
  export interface AwsDeploymentPlan {
21
25
  kind: "open-uptime.aws-deployment-plan";
22
- version: 1;
26
+ version: 2;
23
27
  generatedAt: string;
24
28
  status: "blocked";
25
29
  canApply: false;
@@ -32,10 +36,13 @@ export interface AwsDeploymentPlan {
32
36
  mode: "hosted";
33
37
  resources: {
34
38
  ecrRepository: string;
39
+ imageBuilder: string;
35
40
  ecsCluster: string;
36
41
  services: AwsServicePlan[];
37
42
  vpcId: string;
38
- rdsInstanceId: string;
43
+ efsFileSystem: string;
44
+ efsAccessPoint: string;
45
+ hostedSqliteDbPath: string;
39
46
  evidenceBucket: string;
40
47
  loadBalancer: string;
41
48
  targetGroups: string[];
@@ -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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"}