@hasna/uptime 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/store.js CHANGED
@@ -27,6 +27,40 @@ import { Database } from "bun:sqlite";
27
27
  // src/target-policy.ts
28
28
  import net from "net";
29
29
  var SECRET_PARAM_PATTERN = /(token|secret|password|passwd|api[_-]?key|access[_-]?token|auth|credential|session)/i;
30
+ var DENIED_IPV4_CIDRS = [
31
+ ["0.0.0.0", 8],
32
+ ["10.0.0.0", 8],
33
+ ["100.64.0.0", 10],
34
+ ["127.0.0.0", 8],
35
+ ["169.254.0.0", 16],
36
+ ["172.16.0.0", 12],
37
+ ["192.0.0.0", 24],
38
+ ["192.0.2.0", 24],
39
+ ["192.88.99.0", 24],
40
+ ["192.168.0.0", 16],
41
+ ["198.18.0.0", 15],
42
+ ["198.51.100.0", 24],
43
+ ["203.0.113.0", 24],
44
+ ["224.0.0.0", 4],
45
+ ["240.0.0.0", 4]
46
+ ];
47
+ var DENIED_IPV6_CIDRS = [
48
+ ["::", 128],
49
+ ["::1", 128],
50
+ ["64:ff9b::", 96],
51
+ ["64:ff9b:1::", 48],
52
+ ["100::", 64],
53
+ ["100:0:0:1::", 64],
54
+ ["2001::", 23],
55
+ ["2001:db8::", 32],
56
+ ["2002::", 16],
57
+ ["2620:4f:8000::", 48],
58
+ ["3fff::", 20],
59
+ ["5f00::", 16],
60
+ ["fc00::", 7],
61
+ ["fe80::", 10],
62
+ ["ff00::", 8]
63
+ ];
30
64
  function assertHostedTargetAllowed(target) {
31
65
  if (target.kind === "http" || target.kind === "browser_page") {
32
66
  if (!target.url)
@@ -64,7 +98,7 @@ function assertHostedHttpUrlAllowed(value) {
64
98
  assertHostedHostAllowed(parsed.hostname, "HTTP host");
65
99
  }
66
100
  function assertHostedHostAllowed(hostname, label = "host") {
67
- const host = normalizeHost(hostname);
101
+ const host = normalizeHostedHost(hostname);
68
102
  if (!host)
69
103
  throw new Error(`${label} is required`);
70
104
  if (host === "localhost" || host.endsWith(".localhost")) {
@@ -81,20 +115,130 @@ function assertHostedHostAllowed(hostname, label = "host") {
81
115
  throw new Error(`${label} is not allowed in hosted mode: private or reserved IPv6`);
82
116
  }
83
117
  }
84
- function normalizeHost(hostname) {
118
+ function assertHostedResolvedAddressesAllowed(hostname, addresses, label = "resolved address") {
119
+ if (addresses.length === 0) {
120
+ throw new Error(`${label} is not allowed in hosted mode: DNS returned no addresses for ${normalizeHostedHost(hostname) || "host"}`);
121
+ }
122
+ for (const entry of addresses) {
123
+ assertHostedAddressAllowed(entry.address, label);
124
+ }
125
+ }
126
+ function assertHostedAddressAllowed(address, label = "resolved address") {
127
+ const host = normalizeHostedHost(address);
128
+ const ipVersion = net.isIP(host);
129
+ if (ipVersion === 4 && isDeniedIpv4(host)) {
130
+ throw new Error(`${label} is not allowed in hosted mode: private or reserved IPv4`);
131
+ }
132
+ if (ipVersion === 6 && isDeniedIpv6(host)) {
133
+ throw new Error(`${label} is not allowed in hosted mode: private or reserved IPv6`);
134
+ }
135
+ if (ipVersion === 0) {
136
+ throw new Error(`${label} is not allowed in hosted mode: DNS returned a non-IP address`);
137
+ }
138
+ }
139
+ function normalizeHostedHost(hostname) {
85
140
  return hostname.trim().toLowerCase().replace(/^\[|\]$/g, "").replace(/\.$/, "");
86
141
  }
87
142
  function isDeniedIpv4(ip) {
88
- const parts = ip.split(".").map((part) => Number(part));
89
- if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
143
+ const parts = parseIpv4Words(ip);
144
+ if (!parts)
90
145
  return true;
91
- }
92
- const [a, b] = parts;
93
- return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a >= 224;
146
+ return DENIED_IPV4_CIDRS.some(([base, prefix]) => ipv4MatchesCidr(parts, parseIpv4Words(base), prefix));
94
147
  }
95
148
  function isDeniedIpv6(ip) {
96
149
  const normalized = ip.toLowerCase();
97
- return normalized === "::" || normalized === "::1" || normalized.startsWith("fe80:") || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("ff") || normalized.startsWith("::ffff:127.") || normalized.startsWith("::ffff:10.") || normalized.startsWith("::ffff:169.254.") || /^::ffff:172\.(1[6-9]|2\d|3[0-1])\./.test(normalized) || normalized.startsWith("::ffff:192.168.");
150
+ const words = parseIpv6Words(normalized);
151
+ if (!words)
152
+ return true;
153
+ const mappedIpv4 = ipv4FromMappedIpv6Words(words);
154
+ if (mappedIpv4)
155
+ return isDeniedIpv4(mappedIpv4);
156
+ return isIpv4CompatibleIpv6(words) || DENIED_IPV6_CIDRS.some(([base, prefix]) => ipv6MatchesCidr(words, parseIpv6Words(base), prefix));
157
+ }
158
+ function isIpv4CompatibleIpv6(words) {
159
+ if (!words)
160
+ return false;
161
+ if (!words.slice(0, 6).every((word) => word === 0))
162
+ return false;
163
+ if (words[6] === 0 && (words[7] === 0 || words[7] === 1))
164
+ return false;
165
+ return true;
166
+ }
167
+ function ipv4FromMappedIpv6Words(words) {
168
+ if (words[0] !== 0 || words[1] !== 0 || words[2] !== 0 || words[3] !== 0 || words[4] !== 0 || words[5] !== 65535) {
169
+ return null;
170
+ }
171
+ return ipv4FromWords(words[6], words[7]);
172
+ }
173
+ function ipv4FromWords(high, low) {
174
+ return [
175
+ high >> 8,
176
+ high & 255,
177
+ low >> 8,
178
+ low & 255
179
+ ].join(".");
180
+ }
181
+ function ipv4MatchesCidr(parts, base, prefix) {
182
+ const mask = prefix === 0 ? 0 : 4294967295 << 32 - prefix >>> 0;
183
+ return (ipv4ToNumber(parts) & mask) >>> 0 === (ipv4ToNumber(base) & mask) >>> 0;
184
+ }
185
+ function ipv4ToNumber(parts) {
186
+ return (parts[0] << 24 >>> 0 | parts[1] << 16 | parts[2] << 8 | parts[3]) >>> 0;
187
+ }
188
+ function ipv6MatchesCidr(words, base, prefix) {
189
+ const fullWords = Math.floor(prefix / 16);
190
+ for (let index = 0;index < fullWords; index += 1) {
191
+ if (words[index] !== base[index])
192
+ return false;
193
+ }
194
+ const remainingBits = prefix % 16;
195
+ if (remainingBits === 0)
196
+ return true;
197
+ const mask = 65535 << 16 - remainingBits & 65535;
198
+ return (words[fullWords] & mask) === (base[fullWords] & mask);
199
+ }
200
+ function parseIpv6Words(value) {
201
+ let ip = value.toLowerCase();
202
+ const zoneIndex = ip.indexOf("%");
203
+ if (zoneIndex >= 0)
204
+ ip = ip.slice(0, zoneIndex);
205
+ if (ip.includes(".")) {
206
+ const lastColon = ip.lastIndexOf(":");
207
+ if (lastColon < 0)
208
+ return null;
209
+ const ipv4 = parseIpv4Words(ip.slice(lastColon + 1));
210
+ if (!ipv4)
211
+ return null;
212
+ ip = `${ip.slice(0, lastColon)}:${(ipv4[0] << 8 | ipv4[1]).toString(16)}:${(ipv4[2] << 8 | ipv4[3]).toString(16)}`;
213
+ }
214
+ const compressed = ip.split("::");
215
+ if (compressed.length > 2)
216
+ return null;
217
+ const left = parseIpv6Side(compressed[0]);
218
+ const right = compressed.length === 2 ? parseIpv6Side(compressed[1]) : [];
219
+ if (!left || !right)
220
+ return null;
221
+ if (compressed.length === 1)
222
+ return left.length === 8 ? left : null;
223
+ const missing = 8 - left.length - right.length;
224
+ if (missing < 1)
225
+ return null;
226
+ return [...left, ...Array(missing).fill(0), ...right];
227
+ }
228
+ function parseIpv6Side(value) {
229
+ if (!value)
230
+ return [];
231
+ const words = value.split(":");
232
+ if (words.some((word) => !/^[0-9a-f]{1,4}$/.test(word)))
233
+ return null;
234
+ return words.map((word) => Number.parseInt(word, 16));
235
+ }
236
+ function parseIpv4Words(value) {
237
+ const words = value.split(".").map((part) => Number(part));
238
+ if (words.length !== 4 || words.some((word) => !Number.isInteger(word) || word < 0 || word > 255)) {
239
+ return null;
240
+ }
241
+ return words;
98
242
  }
99
243
 
100
244
  // src/limits.ts
@@ -1,7 +1,14 @@
1
1
  import type { CreateMonitorInput, Monitor } from "./types.js";
2
2
  type MonitorTarget = Pick<CreateMonitorInput | Monitor, "kind" | "url" | "host" | "port">;
3
+ export interface HostedResolvedAddress {
4
+ address: string;
5
+ family?: 4 | 6 | number;
6
+ }
3
7
  export declare function assertHostedTargetAllowed(target: MonitorTarget): void;
4
8
  export declare function assertHostedHttpUrlAllowed(value: string): void;
5
9
  export declare function assertHostedHostAllowed(hostname: string, label?: string): void;
10
+ export declare function assertHostedResolvedAddressesAllowed(hostname: string, addresses: HostedResolvedAddress[], label?: string): void;
11
+ export declare function assertHostedAddressAllowed(address: string, label?: string): void;
12
+ export declare function normalizeHostedHost(hostname: string): string;
6
13
  export {};
7
14
  //# sourceMappingURL=target-policy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"target-policy.d.ts","sourceRoot":"","sources":["../src/target-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE9D,KAAK,aAAa,GAAG,IAAI,CAAC,kBAAkB,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC;AAI1F,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAerE;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAiB9D;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAS,GAAG,IAAI,CAgB9E"}
1
+ {"version":3,"file":"target-policy.d.ts","sourceRoot":"","sources":["../src/target-policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE9D,KAAK,aAAa,GAAG,IAAI,CAAC,kBAAkB,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC;AAuC1F,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;CACzB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAerE;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAiB9D;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAS,GAAG,IAAI,CAgB9E;AAED,wBAAgB,oCAAoC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,qBAAqB,EAAE,EAAE,KAAK,SAAqB,GAAG,IAAI,CAO3I;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAqB,GAAG,IAAI,CAY5F;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D"}
package/dist/types.d.ts CHANGED
@@ -216,7 +216,32 @@ export interface ListAuditEventsOptions {
216
216
  resourceId?: string;
217
217
  limit?: number;
218
218
  }
219
- export type CheckEvidence = BrowserPageEvidence;
219
+ export type CheckEvidence = BrowserPageEvidence | HttpTargetPolicyEvidence;
220
+ export interface HttpTargetPolicyEvidence {
221
+ kind: "http_target_policy";
222
+ mode: "hosted";
223
+ finalUrl: string | null;
224
+ redirectCount: number;
225
+ decisions: HttpTargetPolicyDecision[];
226
+ redacted: boolean;
227
+ redactionStatus: "redacted";
228
+ retentionClass: "short";
229
+ }
230
+ export interface HttpTargetPolicyDecision {
231
+ stage: "request" | "redirect";
232
+ decision: "allowed" | "blocked";
233
+ url: string;
234
+ host: string;
235
+ targetClass: "public_http";
236
+ probeClass: "public";
237
+ protocol: "http:" | "https:";
238
+ resolvedAddresses: Array<{
239
+ address: string;
240
+ family: 4 | 6;
241
+ }>;
242
+ ruleId: string;
243
+ reason: string | null;
244
+ }
220
245
  export interface BrowserPageEvidence {
221
246
  kind: "browser_page";
222
247
  finalUrl: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -40,20 +40,29 @@ write a sourceable env file with a placeholder probe identity.
40
40
 
41
41
  1. Locate the real infrastructure repository or create the change in the
42
42
  approved owner repository.
43
- 2. Confirm the AWS caller identity:
43
+ 2. Set the operator shell variables used by the command snippets:
44
44
 
45
45
  ```bash
46
- aws sts get-caller-identity --profile <aws-profile>
46
+ : "${AWS_PROFILE_NAME:?set AWS_PROFILE_NAME to the reviewed AWS profile}"
47
+ AWS_REGION="${AWS_REGION:-us-east-1}"
48
+ TF_DIR="${TF_DIR:-infra/aws}"
49
+ PLAN_FILE="${PLAN_FILE:-open-uptime.tfplan}"
47
50
  ```
48
51
 
49
- 3. Confirm the target VPC, private subnets, KMS key, and EFS/Backup plan inputs
52
+ 3. Confirm the AWS caller identity:
53
+
54
+ ```bash
55
+ aws sts get-caller-identity --profile "$AWS_PROFILE_NAME"
56
+ ```
57
+
58
+ 4. Confirm the target VPC, private subnets, KMS key, and EFS/Backup plan inputs
50
59
  still match the plan.
51
- 4. Confirm the protected access mode. The first deploy can use the CloudFront
60
+ 5. Confirm the protected access mode. The first deploy can use the CloudFront
52
61
  default HTTPS domain without custom DNS or ACM. Custom hostname deploys still
53
62
  require Route53/edge ownership and an ACM certificate.
54
- 5. Confirm the deployment role uses short-lived credentials or OIDC, not copied
63
+ 6. Confirm the deployment role uses short-lived credentials or OIDC, not copied
55
64
  access keys.
56
- 6. Create a private evidence directory outside the public repository. Store
65
+ 7. Create a private evidence directory outside the public repository. Store
57
66
  command output, plan summaries, screenshots, and incident notes there. Do
58
67
  not store tokens, database URLs, probe private keys, or secret values.
59
68
 
@@ -84,10 +93,10 @@ copy-pastable AWS mutation commands.
84
93
  Plan the included Terraform/OpenTofu starter without a backend:
85
94
 
86
95
  ```bash
87
- terraform -chdir=infra/aws fmt -check
88
- terraform -chdir=infra/aws init -backend=false
89
- terraform -chdir=infra/aws validate
90
- terraform -chdir=infra/aws plan -out open-uptime.tfplan
96
+ terraform -chdir="$TF_DIR" fmt -check
97
+ terraform -chdir="$TF_DIR" init -backend=false
98
+ terraform -chdir="$TF_DIR" validate
99
+ terraform -chdir="$TF_DIR" plan -out "$PLAN_FILE"
91
100
  ```
92
101
 
93
102
  Use Terraform/OpenTofu 1.9 or newer for this starter.
@@ -101,14 +110,14 @@ desired count `0`.
101
110
  dormant:
102
111
 
103
112
  ```bash
104
- terraform show -json open-uptime.tfplan \
113
+ terraform -chdir="$TF_DIR" show -json "$PLAN_FILE" \
105
114
  | jq -r '.resource_changes[] | select(.type=="aws_ecs_service") | [.address, .change.after.desired_count] | @tsv'
106
115
  ```
107
116
 
108
117
  2. Confirm Terraform is not managing secret values:
109
118
 
110
119
  ```bash
111
- terraform show -json open-uptime.tfplan \
120
+ terraform -chdir="$TF_DIR" show -json "$PLAN_FILE" \
112
121
  | jq -r '.resource_changes[] | select(.type | test("secret_version|random_password|random_string")) | .address'
113
122
  ```
114
123
 
@@ -117,7 +126,7 @@ desired count `0`.
117
126
  3. Apply only the reviewed zero-count plan:
118
127
 
119
128
  ```bash
120
- terraform apply open-uptime.tfplan
129
+ terraform -chdir="$TF_DIR" apply "$PLAN_FILE"
121
130
  ```
122
131
 
123
132
  4. Capture outputs, the source commit, the package version, the plan summary,
@@ -130,10 +139,11 @@ or the declared image builder. Record only the immutable digest, not build logs
130
139
  that contain environment values:
131
140
 
132
141
  ```bash
142
+ IMAGE_BUILDER_PROJECT="$(terraform -chdir="$TF_DIR" output -raw image_builder_project_name)"
133
143
  aws codebuild start-build \
134
- --profile <aws-profile> \
135
- --region <region> \
136
- --project-name <image-builder-project>
144
+ --profile "$AWS_PROFILE_NAME" \
145
+ --region "$AWS_REGION" \
146
+ --project-name "$IMAGE_BUILDER_PROJECT"
137
147
  ```
138
148
 
139
149
  Update the approved infra root so `container_image` is the immutable ECR digest,
@@ -142,8 +152,16 @@ then re-plan with all services still at `0`.
142
152
  Populate Secrets Manager values out of band. Verify metadata only:
143
153
 
144
154
  ```bash
145
- aws secretsmanager describe-secret --profile <aws-profile> --region <region> --secret-id <secret-name>
146
- aws secretsmanager list-secret-version-ids --profile <aws-profile> --region <region> --secret-id <secret-name>
155
+ terraform -chdir="$TF_DIR" output -json secret_refs | jq -r '.[]' | while read -r SECRET_ID; do
156
+ aws secretsmanager describe-secret \
157
+ --profile "$AWS_PROFILE_NAME" \
158
+ --region "$AWS_REGION" \
159
+ --secret-id "$SECRET_ID"
160
+ aws secretsmanager list-secret-version-ids \
161
+ --profile "$AWS_PROFILE_NAME" \
162
+ --region "$AWS_REGION" \
163
+ --secret-id "$SECRET_ID"
164
+ done
147
165
  ```
148
166
 
149
167
  Each required secret must have an `AWSCURRENT` version before any task is
@@ -166,11 +184,13 @@ Scale only the web task, then capture the ECS deployment id and task definition
166
184
  ARN:
167
185
 
168
186
  ```bash
187
+ ECS_CLUSTER="$(terraform -chdir="$TF_DIR" output -raw ecs_cluster_name)"
188
+ WEB_SERVICE="$(terraform -chdir="$TF_DIR" output -json service_names | jq -r '.[] | select(endswith("-web"))')"
169
189
  aws ecs describe-services \
170
- --profile <aws-profile> \
171
- --region <region> \
172
- --cluster <ecs-cluster> \
173
- --services <web-service> \
190
+ --profile "$AWS_PROFILE_NAME" \
191
+ --region "$AWS_REGION" \
192
+ --cluster "$ECS_CLUSTER" \
193
+ --services "$WEB_SERVICE" \
174
194
  --query 'services[0].{taskDefinition:taskDefinition,deployments:deployments[*].{id:id,status:status,desired:desiredCount,running:runningCount}}'
175
195
  ```
176
196
 
@@ -180,10 +200,14 @@ Run these checks through the public edge URL and record status codes and request
180
200
  ids. Use a scoped hosted token only from the operator secret store.
181
201
 
182
202
  ```bash
183
- curl -fsS https://<edge-host>/health
184
- curl -i https://<edge-host>/
185
- curl -i https://<edge-host>/api/v1/summary
186
- curl -i -H "Authorization: Bearer <token-from-secret-store>" https://<edge-host>/api/v1/summary
203
+ EDGE_URL="$(terraform -chdir="$TF_DIR" output -raw protected_access_url)"
204
+ : "${HOSTED_TOKEN_FILE:?set HOSTED_TOKEN_FILE to a 0600 file containing the scoped hosted token}"
205
+ HOSTED_TOKEN="$(tr -d '\n' < "$HOSTED_TOKEN_FILE")"
206
+
207
+ curl -fsS "$EDGE_URL/health"
208
+ curl -i "$EDGE_URL/"
209
+ curl -i "$EDGE_URL/api/v1/summary"
210
+ curl -i -H "Authorization: Bearer $HOSTED_TOKEN" "$EDGE_URL/api/v1/summary"
187
211
  ```
188
212
 
189
213
  Expected results:
@@ -200,19 +224,22 @@ Expected results:
200
224
  Inspect recent web logs without printing secrets:
201
225
 
202
226
  ```bash
203
- aws logs tail /ecs/<web-service> \
204
- --profile <aws-profile> \
205
- --region <region> \
227
+ WEB_LOG_GROUP="$(terraform -chdir="$TF_DIR" output -json log_group_names | jq -r '.web')"
228
+ aws logs tail "$WEB_LOG_GROUP" \
229
+ --profile "$AWS_PROFILE_NAME" \
230
+ --region "$AWS_REGION" \
206
231
  --since 15m
207
232
  ```
208
233
 
209
234
  Verify the initial web alarms exist and are not already alarming:
210
235
 
211
236
  ```bash
237
+ WEB_5XX_ALARM="$(terraform -chdir="$TF_DIR" output -json alarm_names | jq -r '.web_5xx')"
238
+ WEB_UNHEALTHY_ALARM="$(terraform -chdir="$TF_DIR" output -json alarm_names | jq -r '.web_unhealthy')"
212
239
  aws cloudwatch describe-alarms \
213
- --profile <aws-profile> \
214
- --region <region> \
215
- --alarm-names <web-5xx-alarm> <web-unhealthy-alarm> \
240
+ --profile "$AWS_PROFILE_NAME" \
241
+ --region "$AWS_REGION" \
242
+ --alarm-names "$WEB_5XX_ALARM" "$WEB_UNHEALTHY_ALARM" \
216
243
  --query 'MetricAlarms[*].{name:AlarmName,state:StateValue,reason:StateReason}'
217
244
  ```
218
245
 
@@ -224,14 +251,24 @@ those workers are implemented, emit metrics, and are enabled.
224
251
  Verify EFS backup coverage after the first apply:
225
252
 
226
253
  ```bash
254
+ BACKUP_VAULT="$(terraform -chdir="$TF_DIR" output -raw backup_vault_name)"
255
+ EFS_FILE_SYSTEM_ID="$(terraform -chdir="$TF_DIR" output -raw efs_file_system_id)"
256
+ EFS_FILE_SYSTEM_ARN="$(aws efs describe-file-systems \
257
+ --profile "$AWS_PROFILE_NAME" \
258
+ --region "$AWS_REGION" \
259
+ --file-system-id "$EFS_FILE_SYSTEM_ID" \
260
+ --query 'FileSystems[0].FileSystemArn' \
261
+ --output text)"
262
+
227
263
  aws backup list-protected-resources \
228
- --profile <aws-profile> \
229
- --region <region> \
230
- --query 'Results[?ResourceType==`EFS`].[ResourceArn,LastBackupTime]'
264
+ --profile "$AWS_PROFILE_NAME" \
265
+ --region "$AWS_REGION" \
266
+ --query "Results[?ResourceArn=='$EFS_FILE_SYSTEM_ARN'].[ResourceArn,LastBackupTime]"
231
267
  aws backup list-recovery-points-by-backup-vault \
232
- --profile <aws-profile> \
233
- --region <region> \
234
- --backup-vault-name <backup-vault>
268
+ --profile "$AWS_PROFILE_NAME" \
269
+ --region "$AWS_REGION" \
270
+ --backup-vault-name "$BACKUP_VAULT" \
271
+ --query "RecoveryPoints[?ResourceArn=='$EFS_FILE_SYSTEM_ARN'].[RecoveryPointArn,Status,CreationDate]"
235
272
  ```
236
273
 
237
274
  A restore drill must restore to a separate file system or staging target first.
@@ -239,6 +276,65 @@ Do not overwrite the production EFS file system during a drill. Record the
239
276
  recovery point ARN, restore job id, target resource, validation result, and
240
277
  cleanup action.
241
278
 
279
+ Run the restore drill with a dedicated restore role and a staging security group
280
+ and subnet. The metadata keys are AWS Backup EFS restore metadata; keep the
281
+ staging file system encrypted with the Open Uptime KMS key.
282
+
283
+ ```bash
284
+ : "${RECOVERY_POINT_ARN:?set RECOVERY_POINT_ARN to the selected recovery point ARN}"
285
+ : "${RESTORE_ROLE_ARN:?set RESTORE_ROLE_ARN to the AWS Backup restore role ARN}"
286
+ : "${STAGING_SUBNET_ID:?set STAGING_SUBNET_ID to the staging private subnet id}"
287
+ : "${STAGING_SECURITY_GROUP_ID:?set STAGING_SECURITY_GROUP_ID to the staging EFS security group id}"
288
+ KMS_KEY_ARN="$(terraform -chdir="$TF_DIR" output -raw kms_key_arn)"
289
+
290
+ RESTORE_JOB_ID="$(aws backup start-restore-job \
291
+ --profile "$AWS_PROFILE_NAME" \
292
+ --region "$AWS_REGION" \
293
+ --recovery-point-arn "$RECOVERY_POINT_ARN" \
294
+ --iam-role-arn "$RESTORE_ROLE_ARN" \
295
+ --resource-type EFS \
296
+ --metadata "file-system-id=$EFS_FILE_SYSTEM_ID,newFileSystem=true,encrypted=true,kmsKeyId=$KMS_KEY_ARN,performanceMode=generalPurpose,throughputMode=bursting" \
297
+ --query 'RestoreJobId' \
298
+ --output text)"
299
+
300
+ aws backup describe-restore-job \
301
+ --profile "$AWS_PROFILE_NAME" \
302
+ --region "$AWS_REGION" \
303
+ --restore-job-id "$RESTORE_JOB_ID" \
304
+ --query '{status:Status,createdResourceArn:CreatedResourceArn,statusMessage:StatusMessage}'
305
+ ```
306
+
307
+ Poll `describe-restore-job` until `Status` is `COMPLETED`, then create a
308
+ temporary mount target for the restored file system in the staging subnet:
309
+
310
+ ```bash
311
+ RESTORED_EFS_ID="$(aws backup describe-restore-job \
312
+ --profile "$AWS_PROFILE_NAME" \
313
+ --region "$AWS_REGION" \
314
+ --restore-job-id "$RESTORE_JOB_ID" \
315
+ --query 'CreatedResourceArn' \
316
+ --output text | awk -F/ '{print $NF}')"
317
+
318
+ aws efs create-mount-target \
319
+ --profile "$AWS_PROFILE_NAME" \
320
+ --region "$AWS_REGION" \
321
+ --file-system-id "$RESTORED_EFS_ID" \
322
+ --subnet-id "$STAGING_SUBNET_ID" \
323
+ --security-groups "$STAGING_SECURITY_GROUP_ID"
324
+ ```
325
+
326
+ Validate the restored `/data/uptime/uptime.db` from a staging host or task with
327
+ read-only SQLite integrity checks. Capture only counts and integrity status, not
328
+ monitor targets or secrets:
329
+
330
+ ```bash
331
+ sqlite3 /mnt/restore/uptime/uptime.db 'PRAGMA integrity_check;'
332
+ sqlite3 /mnt/restore/uptime/uptime.db 'SELECT COUNT(*) FROM monitors;'
333
+ ```
334
+
335
+ After evidence is recorded, delete the staging mount target and restored file
336
+ system. Never mount the restored file system over production during a drill.
337
+
242
338
  ## Reports And Reporter Gate
243
339
 
244
340
  Report preview can be tested locally or through authenticated read APIs. Hosted
@@ -273,6 +369,11 @@ routes are backed by cloud check jobs and cloud audit rows.
273
369
  URLs, or probe private keys in task definitions. Use ECS `secrets.valueFrom`
274
370
  refs such as `HASNA_UPTIME_HOSTED_TOKEN`.
275
371
  - Do not run public probe workers against private targets.
372
+ - Do not enable public probe workers until their cloud check-job path calls
373
+ `runHostedHttpCheck`, records target-policy decision evidence, and passes AWS
374
+ smokes for denied DNS answers, redirect-to-denied targets, and address
375
+ pinning. The SDK runner now handles execution-time DNS and redirect
376
+ enforcement, but it is not active until the worker is wired to it.
276
377
  - Do not enable scheduler, public-probe, reporter, or migration workers against
277
378
  the EFS SQLite bridge; those services need Postgres/cloud leases first.
278
379
  - Do not expose dashboard/API routes without hosted auth and workspace checks.
@@ -293,11 +394,13 @@ Before each service update, record the previous task definition ARN and current
293
394
  desired counts:
294
395
 
295
396
  ```bash
397
+ ECS_CLUSTER="$(terraform -chdir="$TF_DIR" output -raw ecs_cluster_name)"
398
+ WEB_SERVICE="$(terraform -chdir="$TF_DIR" output -json service_names | jq -r '.[] | select(endswith("-web"))')"
296
399
  aws ecs describe-services \
297
- --profile <aws-profile> \
298
- --region <region> \
299
- --cluster <ecs-cluster> \
300
- --services <service-name> \
400
+ --profile "$AWS_PROFILE_NAME" \
401
+ --region "$AWS_REGION" \
402
+ --cluster "$ECS_CLUSTER" \
403
+ --services "$WEB_SERVICE" \
301
404
  --query 'services[0].{taskDefinition:taskDefinition,desired:desiredCount,running:runningCount}'
302
405
  ```
303
406
 
@@ -305,10 +408,10 @@ If web health fails after scale-up, first scale web back to `0`:
305
408
 
306
409
  ```bash
307
410
  aws ecs update-service \
308
- --profile <aws-profile> \
309
- --region <region> \
310
- --cluster <ecs-cluster> \
311
- --service <web-service> \
411
+ --profile "$AWS_PROFILE_NAME" \
412
+ --region "$AWS_REGION" \
413
+ --cluster "$ECS_CLUSTER" \
414
+ --service "$WEB_SERVICE" \
312
415
  --desired-count 0
313
416
  ```
314
417
 
@@ -316,12 +419,13 @@ If a later task definition is bad, restore the previous task definition and keep
316
419
  workers disabled:
317
420
 
318
421
  ```bash
422
+ : "${PREVIOUS_TASK_DEFINITION_ARN:?set PREVIOUS_TASK_DEFINITION_ARN from the pre-update evidence}"
319
423
  aws ecs update-service \
320
- --profile <aws-profile> \
321
- --region <region> \
322
- --cluster <ecs-cluster> \
323
- --service <web-service> \
324
- --task-definition <previous-task-definition-arn> \
424
+ --profile "$AWS_PROFILE_NAME" \
425
+ --region "$AWS_REGION" \
426
+ --cluster "$ECS_CLUSTER" \
427
+ --service "$WEB_SERVICE" \
428
+ --task-definition "$PREVIOUS_TASK_DEFINITION_ARN" \
325
429
  --desired-count 1
326
430
  ```
327
431
 
@@ -55,8 +55,9 @@ creation and is not sufficient for live scale-out approval.
55
55
  ## Current Blockers
56
56
 
57
57
  - Hosted production auth/RBAC still needs scoped, revocable credentials.
58
- - Public probe runtime still needs execution-time DNS/redirect/rebinding SSRF
59
- enforcement.
58
+ - Public probe runtime has SDK-level hosted HTTP target-policy enforcement, but
59
+ the public-probe worker and cloud check-job lease path are still disabled until
60
+ they are wired to that runner and validated in AWS.
60
61
  - Hosted private-probe enrollment/heartbeat/revocation is still
61
62
  fail-closed.
62
63