@hasna/uptime 0.1.17 → 0.1.18

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 CHANGED
@@ -6,6 +6,16 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.18] - 2026-06-28
10
+
11
+ ### Changed
12
+
13
+ - Added explicit ECS container health checks to the AWS Terraform module task
14
+ definitions. The web task checks `/health`, while disabled non-web roles use
15
+ a hosted-environment sanity check until their worker entrypoints are enabled.
16
+ - Updated cloud planning and AWS deployment docs to keep the zero-count
17
+ deployment status clear while the private root is repinned and verified.
18
+
9
19
  ## [0.1.17] - 2026-06-28
10
20
 
11
21
  ### Fixed
package/dist/cli/index.js CHANGED
@@ -6943,7 +6943,7 @@ function buildAwsDeploymentPlan(options = {}) {
6943
6943
  const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
6944
6944
  const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
6945
6945
  const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
6946
- const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.17");
6946
+ const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.18");
6947
6947
  const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
6948
6948
  const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
6949
6949
  const cluster = `${prefix}-${stage}`;
@@ -7194,7 +7194,7 @@ function servicePlan(prefix, stage, role, desiredCount, image, workspaceId, secr
7194
7194
  taskRole: `${name}-task-role`,
7195
7195
  executionRole: `${prefix}-${stage}-execution-role`,
7196
7196
  logGroup: `/ecs/${name}`,
7197
- healthCommand: role === "web" ? "GET /health" : undefined,
7197
+ healthCommand: role === "web" ? "GET /health" : "hosted environment sanity check",
7198
7198
  environment: {
7199
7199
  HASNA_UPTIME_IMAGE: image,
7200
7200
  ...environment
@@ -21,7 +21,7 @@ function buildAwsDeploymentPlan(options = {}) {
21
21
  const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
22
22
  const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
23
23
  const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
24
- const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.17");
24
+ const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.18");
25
25
  const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
26
26
  const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
27
27
  const cluster = `${prefix}-${stage}`;
@@ -272,7 +272,7 @@ function servicePlan(prefix, stage, role, desiredCount, image, workspaceId, secr
272
272
  taskRole: `${name}-task-role`,
273
273
  executionRole: `${prefix}-${stage}-execution-role`,
274
274
  logGroup: `/ecs/${name}`,
275
- healthCommand: role === "web" ? "GET /health" : undefined,
275
+ healthCommand: role === "web" ? "GET /health" : "hosted environment sanity check",
276
276
  environment: {
277
277
  HASNA_UPTIME_IMAGE: image,
278
278
  ...environment
package/dist/index.js CHANGED
@@ -4349,7 +4349,7 @@ function buildAwsDeploymentPlan(options = {}) {
4349
4349
  const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
4350
4350
  const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
4351
4351
  const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
4352
- const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.17");
4352
+ const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.18");
4353
4353
  const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
4354
4354
  const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
4355
4355
  const cluster = `${prefix}-${stage}`;
@@ -4600,7 +4600,7 @@ function servicePlan(prefix, stage, role, desiredCount, image, workspaceId, secr
4600
4600
  taskRole: `${name}-task-role`,
4601
4601
  executionRole: `${prefix}-${stage}-execution-role`,
4602
4602
  logGroup: `/ecs/${name}`,
4603
- healthCommand: role === "web" ? "GET /health" : undefined,
4603
+ healthCommand: role === "web" ? "GET /health" : "hosted environment sanity check",
4604
4604
  environment: {
4605
4605
  HASNA_UPTIME_IMAGE: image,
4606
4606
  ...environment
@@ -71,6 +71,12 @@ Keep this disabled when private endpoints are the approved egress path. Runtime
71
71
  scale-up still requires ECS task evidence for image pull, secret injection, log
72
72
  delivery, S3 access, and EFS mount behavior.
73
73
 
74
+ Every ECS task definition includes an explicit container health check. The web
75
+ task checks `GET /health` through Bun's built-in `fetch`; disabled non-web roles
76
+ currently run a hosted-environment sanity check so scheduler, public-probe,
77
+ reporter, and migration tasks do not start from empty ECS health semantics when
78
+ their long-running workers are later enabled.
79
+
74
80
  Interface endpoint private DNS is VPC-wide. In shared VPCs, either keep endpoint
75
81
  creation in the approved networking root, or pass
76
82
  `additional_vpc_endpoint_source_security_group_ids` for every workload that must
package/infra/aws/main.tf CHANGED
@@ -79,6 +79,43 @@ locals {
79
79
  : ["arn:${data.aws_partition.current.partition}:ssm:${var.region}:${data.aws_caller_identity.current.account_id}:parameter/${local.prefix}/no-ssm-refs-configured"]
80
80
  )
81
81
  service_log_group_arns = [for group in aws_cloudwatch_log_group.service : "${group.arn}:*"]
82
+ service_health_checks = {
83
+ web = {
84
+ command = ["CMD-SHELL", "bun -e \"const r = await fetch('http://127.0.0.1:${local.container_port}/health'); process.exit(r.ok ? 0 : 1)\""]
85
+ interval = 30
86
+ timeout = 5
87
+ retries = 3
88
+ startPeriod = 30
89
+ }
90
+ scheduler = {
91
+ command = ["CMD-SHELL", "bun -e \"process.exit(process.env.HASNA_UPTIME_MODE === 'hosted' && process.env.HASNA_UPTIME_COMPONENT === 'scheduler' ? 0 : 1)\""]
92
+ interval = 30
93
+ timeout = 5
94
+ retries = 3
95
+ startPeriod = 30
96
+ }
97
+ "public-probe" = {
98
+ command = ["CMD-SHELL", "bun -e \"process.exit(process.env.HASNA_UPTIME_MODE === 'hosted' && process.env.HASNA_UPTIME_COMPONENT === 'public-probe' ? 0 : 1)\""]
99
+ interval = 30
100
+ timeout = 5
101
+ retries = 3
102
+ startPeriod = 30
103
+ }
104
+ reporter = {
105
+ command = ["CMD-SHELL", "bun -e \"process.exit(process.env.HASNA_UPTIME_MODE === 'hosted' && process.env.HASNA_UPTIME_COMPONENT === 'reporter' ? 0 : 1)\""]
106
+ interval = 30
107
+ timeout = 5
108
+ retries = 3
109
+ startPeriod = 30
110
+ }
111
+ migration = {
112
+ command = ["CMD-SHELL", "bun -e \"process.exit(process.env.HASNA_UPTIME_MODE === 'hosted' && process.env.HASNA_UPTIME_COMPONENT === 'migration' ? 0 : 1)\""]
113
+ interval = 30
114
+ timeout = 5
115
+ retries = 3
116
+ startPeriod = 30
117
+ }
118
+ }
82
119
  }
83
120
 
84
121
  data "aws_vpc" "target" {
@@ -1090,6 +1127,7 @@ resource "aws_ecs_task_definition" "service" {
1090
1127
  readOnly = false
1091
1128
  }
1092
1129
  ] : []
1130
+ healthCheck = local.service_health_checks[each.key]
1093
1131
  secrets = [
1094
1132
  for name, value_from in each.value.secrets : {
1095
1133
  name = name
@@ -16,7 +16,7 @@ alb_ingress_cidr_blocks = []
16
16
  private_subnet_ids = ["subnet-replace-private-a", "subnet-replace-private-b"]
17
17
  private_route_table_ids = ["rtb-replace-private"]
18
18
  container_image = "123456789012.dkr.ecr.us-east-1.amazonaws.com/open-uptime@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
19
- runtime_package_version = "0.1.17"
19
+ runtime_package_version = "0.1.18"
20
20
  certificate_arn = null
21
21
  hosted_zone_id = null
22
22
  app_env_secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:open-uptime/prod/app/env"
@@ -116,7 +116,7 @@ variable "container_image" {
116
116
  variable "runtime_package_version" {
117
117
  description = "Published @hasna/uptime package version that CodeBuild should build into the ECR image."
118
118
  type = string
119
- default = "0.1.17"
119
+ default = "0.1.18"
120
120
 
121
121
  validation {
122
122
  condition = can(regex("^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?$", var.runtime_package_version))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/uptime",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Local-first uptime and downtime monitoring service with CLI, MCP, SDK, SQLite persistence, and a dashboard.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",