@hasna/uptime 0.1.24 → 0.1.25
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 +14 -0
- package/Dockerfile.package +2 -2
- package/README.md +5 -2
- package/bun.lock +221 -0
- package/dist/cli/index.js +29 -7
- package/dist/cloud-plan.d.ts +11 -0
- package/dist/cloud-plan.d.ts.map +1 -1
- package/dist/cloud-plan.js +23 -6
- package/dist/index.js +23 -6
- package/docs/aws-deployment-runbook.md +27 -6
- package/docs/aws-runtime-security.md +25 -10
- package/docs/deployment-metadata.example.json +4 -2
- package/infra/aws/README.md +26 -11
- package/infra/aws/main.tf +116 -34
- package/infra/aws/outputs.tf +8 -0
- package/infra/aws/terraform.tfvars.example +4 -1
- package/infra/aws/variables.tf +54 -5
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,20 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.25] - 2026-06-29
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added an opt-in CloudFront HTTPS-origin path for the AWS module. Operators can
|
|
14
|
+
set `cloudfront_origin_protocol_policy = "https-only"` with a dedicated
|
|
15
|
+
origin hostname and matching ACM certificate before token-bearing live
|
|
16
|
+
traffic, while the default zero-count bridge remains unchanged.
|
|
17
|
+
- Added AWS ECS service tag propagation and managed tags so service-launched
|
|
18
|
+
tasks keep cost allocation tags.
|
|
19
|
+
- Added optional `runtime_package_integrity` verification for the CodeBuild
|
|
20
|
+
image builder and included the published `bun.lock` in package images so
|
|
21
|
+
production dependency installs can use `--frozen-lockfile`.
|
|
22
|
+
|
|
9
23
|
## [0.1.24] - 2026-06-29
|
|
10
24
|
|
|
11
25
|
### Added
|
package/Dockerfile.package
CHANGED
|
@@ -16,10 +16,10 @@ RUN apk add --no-cache ca-certificates libgcc libstdc++ \
|
|
|
16
16
|
COPY --from=bun /usr/local/bin/bun /usr/local/bin/bun
|
|
17
17
|
COPY --from=bun /usr/local/lib/node_modules/bun /usr/local/lib/node_modules/bun
|
|
18
18
|
|
|
19
|
-
COPY package.json ./
|
|
19
|
+
COPY package.json bun.lock ./
|
|
20
20
|
COPY dist ./dist
|
|
21
21
|
|
|
22
|
-
RUN bun install --production \
|
|
22
|
+
RUN bun install --production --frozen-lockfile \
|
|
23
23
|
&& chown -R uptime:uptime /app
|
|
24
24
|
|
|
25
25
|
USER uptime
|
package/README.md
CHANGED
|
@@ -55,8 +55,11 @@ format/init/validate/plan commands with `applyAllowed: false`. The first
|
|
|
55
55
|
protected access path uses the CloudFront default HTTPS domain with ALB origin
|
|
56
56
|
ingress restricted to CloudFront. The hosted web task must set
|
|
57
57
|
`HASNA_UPTIME_ALLOWED_ORIGINS` to the public HTTPS edge origin so same-origin
|
|
58
|
-
browser mutations still pass
|
|
59
|
-
|
|
58
|
+
browser mutations still pass through the selected ALB origin path. The default
|
|
59
|
+
zero-count bridge keeps `cloudfront_origin_protocol_policy = "http-only"`;
|
|
60
|
+
token-bearing live traffic needs `https-only` with an origin hostname that
|
|
61
|
+
resolves to the ALB and matches `certificate_arn`, or an explicit risk
|
|
62
|
+
acceptance. Hosted AWS runtime state currently uses explicit EFS-backed SQLite via
|
|
60
63
|
`HASNA_UPTIME_HOSTED_SQLITE_DB=/data/uptime/uptime.db` for one protected web
|
|
61
64
|
task maximum; do not set `HASNA_UPTIME_DATABASE_URL` until the async Postgres
|
|
62
65
|
adapter is implemented.
|
package/bun.lock
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 1,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "@hasna/uptime",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
9
|
+
"chalk": "^5.6.2",
|
|
10
|
+
"commander": "^13.1.0",
|
|
11
|
+
"zod": "^4.3.6",
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/bun": "^1.3.14",
|
|
15
|
+
"@types/node": "^20.14.0",
|
|
16
|
+
"typescript": "^5.9.3",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
"packages": {
|
|
21
|
+
"@hono/node-server": ["@hono/node-server@1.19.14", "", { "peerDependencies": { "hono": "^4" } }, "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw=="],
|
|
22
|
+
|
|
23
|
+
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="],
|
|
24
|
+
|
|
25
|
+
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
|
26
|
+
|
|
27
|
+
"@types/node": ["@types/node@20.19.43", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA=="],
|
|
28
|
+
|
|
29
|
+
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
|
30
|
+
|
|
31
|
+
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
|
|
32
|
+
|
|
33
|
+
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
|
|
34
|
+
|
|
35
|
+
"body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="],
|
|
36
|
+
|
|
37
|
+
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
|
38
|
+
|
|
39
|
+
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
|
40
|
+
|
|
41
|
+
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
|
42
|
+
|
|
43
|
+
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
|
44
|
+
|
|
45
|
+
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
|
46
|
+
|
|
47
|
+
"commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="],
|
|
48
|
+
|
|
49
|
+
"content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="],
|
|
50
|
+
|
|
51
|
+
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
|
52
|
+
|
|
53
|
+
"cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
|
54
|
+
|
|
55
|
+
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
|
56
|
+
|
|
57
|
+
"cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
|
|
58
|
+
|
|
59
|
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
60
|
+
|
|
61
|
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
62
|
+
|
|
63
|
+
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
|
64
|
+
|
|
65
|
+
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
|
66
|
+
|
|
67
|
+
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
|
68
|
+
|
|
69
|
+
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
|
70
|
+
|
|
71
|
+
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
|
72
|
+
|
|
73
|
+
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
|
74
|
+
|
|
75
|
+
"es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
|
|
76
|
+
|
|
77
|
+
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
|
|
78
|
+
|
|
79
|
+
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
|
|
80
|
+
|
|
81
|
+
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
|
82
|
+
|
|
83
|
+
"eventsource-parser": ["eventsource-parser@3.1.0", "", {}, "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg=="],
|
|
84
|
+
|
|
85
|
+
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
|
86
|
+
|
|
87
|
+
"express-rate-limit": ["express-rate-limit@8.5.2", "", { "dependencies": { "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A=="],
|
|
88
|
+
|
|
89
|
+
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
|
90
|
+
|
|
91
|
+
"fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="],
|
|
92
|
+
|
|
93
|
+
"finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
|
|
94
|
+
|
|
95
|
+
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
|
96
|
+
|
|
97
|
+
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
|
|
98
|
+
|
|
99
|
+
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
|
100
|
+
|
|
101
|
+
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
|
102
|
+
|
|
103
|
+
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
|
104
|
+
|
|
105
|
+
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
|
106
|
+
|
|
107
|
+
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
|
108
|
+
|
|
109
|
+
"hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
|
|
110
|
+
|
|
111
|
+
"hono": ["hono@4.12.26", "", {}, "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw=="],
|
|
112
|
+
|
|
113
|
+
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
|
114
|
+
|
|
115
|
+
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
|
116
|
+
|
|
117
|
+
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
|
118
|
+
|
|
119
|
+
"ip-address": ["ip-address@10.2.0", "", {}, "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA=="],
|
|
120
|
+
|
|
121
|
+
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
|
|
122
|
+
|
|
123
|
+
"is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
|
|
124
|
+
|
|
125
|
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
126
|
+
|
|
127
|
+
"jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
|
|
128
|
+
|
|
129
|
+
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
|
130
|
+
|
|
131
|
+
"json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
|
|
132
|
+
|
|
133
|
+
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
|
134
|
+
|
|
135
|
+
"media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
|
136
|
+
|
|
137
|
+
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
|
|
138
|
+
|
|
139
|
+
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
|
140
|
+
|
|
141
|
+
"mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
|
142
|
+
|
|
143
|
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
144
|
+
|
|
145
|
+
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
|
146
|
+
|
|
147
|
+
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
|
148
|
+
|
|
149
|
+
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
|
150
|
+
|
|
151
|
+
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
|
|
152
|
+
|
|
153
|
+
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
|
154
|
+
|
|
155
|
+
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
|
|
156
|
+
|
|
157
|
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
|
158
|
+
|
|
159
|
+
"path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
|
|
160
|
+
|
|
161
|
+
"pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
|
|
162
|
+
|
|
163
|
+
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
|
164
|
+
|
|
165
|
+
"qs": ["qs@6.15.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw=="],
|
|
166
|
+
|
|
167
|
+
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
|
168
|
+
|
|
169
|
+
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
|
|
170
|
+
|
|
171
|
+
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
|
172
|
+
|
|
173
|
+
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
|
|
174
|
+
|
|
175
|
+
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
|
176
|
+
|
|
177
|
+
"send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
|
|
178
|
+
|
|
179
|
+
"serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
|
|
180
|
+
|
|
181
|
+
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
|
182
|
+
|
|
183
|
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
|
184
|
+
|
|
185
|
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
186
|
+
|
|
187
|
+
"side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="],
|
|
188
|
+
|
|
189
|
+
"side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
|
|
190
|
+
|
|
191
|
+
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
|
192
|
+
|
|
193
|
+
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
|
194
|
+
|
|
195
|
+
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
|
196
|
+
|
|
197
|
+
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
|
198
|
+
|
|
199
|
+
"type-is": ["type-is@2.1.0", "", { "dependencies": { "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA=="],
|
|
200
|
+
|
|
201
|
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
202
|
+
|
|
203
|
+
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
|
204
|
+
|
|
205
|
+
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
|
206
|
+
|
|
207
|
+
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
|
208
|
+
|
|
209
|
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
|
210
|
+
|
|
211
|
+
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
|
212
|
+
|
|
213
|
+
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
|
214
|
+
|
|
215
|
+
"zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="],
|
|
216
|
+
|
|
217
|
+
"body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
|
218
|
+
|
|
219
|
+
"type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
|
220
|
+
}
|
|
221
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -7217,6 +7217,7 @@ var DEFAULT_WORKSPACE_ID = "workspace-id";
|
|
|
7217
7217
|
var DEFAULT_VPC_ID = "vpc-xxxxxxxx";
|
|
7218
7218
|
var DEFAULT_HOSTED_SQLITE_DB = "/data/uptime/uptime.db";
|
|
7219
7219
|
var DEFAULT_PROTECTED_ACCESS_MODE = "cloudfront_default_domain";
|
|
7220
|
+
var DEFAULT_CLOUDFRONT_ORIGIN_PROTOCOL_POLICY = "http-only";
|
|
7220
7221
|
function buildAwsDeploymentPlan(options = {}) {
|
|
7221
7222
|
const region = clean(options.region, DEFAULT_REGION);
|
|
7222
7223
|
const stage = clean(options.stage, DEFAULT_STAGE);
|
|
@@ -7229,8 +7230,11 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
7229
7230
|
const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
|
|
7230
7231
|
const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
|
|
7231
7232
|
const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
|
|
7232
|
-
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.
|
|
7233
|
+
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.25");
|
|
7234
|
+
const runtimePackageIntegrity = options.runtimePackageIntegrity?.trim() || undefined;
|
|
7233
7235
|
const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
|
|
7236
|
+
const cloudfrontOriginProtocolPolicy = options.cloudfrontOriginProtocolPolicy ?? DEFAULT_CLOUDFRONT_ORIGIN_PROTOCOL_POLICY;
|
|
7237
|
+
const cloudfrontOriginDomainName = clean(options.cloudfrontOriginDomainName, "<alb-dns-name>");
|
|
7234
7238
|
const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
|
|
7235
7239
|
const cluster = `${prefix}-${stage}`;
|
|
7236
7240
|
const secrets = {
|
|
@@ -7297,6 +7301,13 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
7297
7301
|
protectedAccessMode,
|
|
7298
7302
|
edgeDistribution: protectedAccessMode === "cloudfront_default_domain" ? `${prefix}-${stage}-edge` : undefined,
|
|
7299
7303
|
protectedAccessUrl,
|
|
7304
|
+
cloudfrontOrigin: protectedAccessMode === "cloudfront_default_domain" ? {
|
|
7305
|
+
protocolPolicy: cloudfrontOriginProtocolPolicy,
|
|
7306
|
+
domainName: cloudfrontOriginProtocolPolicy === "https-only" ? cloudfrontOriginDomainName : "<alb-dns-name>",
|
|
7307
|
+
requiresMatchingCertificate: cloudfrontOriginProtocolPolicy === "https-only",
|
|
7308
|
+
liveTrafficApproved: false,
|
|
7309
|
+
risk: cloudfrontOriginProtocolPolicy === "http-only" ? "Temporary HTTP-origin bridge: do not use for token-bearing live traffic without explicit risk acceptance, or switch to https-only with cloudfront_origin_domain_name plus certificate_arn." : "CloudFront HTTPS-origin mode requires the origin hostname to resolve to the ALB and match certificate_arn."
|
|
7310
|
+
} : undefined,
|
|
7300
7311
|
originVerification: protectedAccessMode === "cloudfront_default_domain" ? {
|
|
7301
7312
|
mode: "cloudfront_origin_header",
|
|
7302
7313
|
requiredBeforeScaleUp: true,
|
|
@@ -7329,6 +7340,7 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
7329
7340
|
repository: ecrRepository,
|
|
7330
7341
|
uri: image,
|
|
7331
7342
|
dockerfile: "Dockerfile.package",
|
|
7343
|
+
expectedIntegrity: runtimePackageIntegrity,
|
|
7332
7344
|
buildCommand: `BLOCKED: after infra approval, AWS CodeBuild builds Dockerfile.package from @hasna/uptime@${runtimePackageVersion} into ${imageRepositoryUri}`,
|
|
7333
7345
|
pushCommands: [
|
|
7334
7346
|
`BLOCKED: start ${prefix}-${stage}-image-builder only through the approved deploy pipeline after @hasna/uptime@${runtimePackageVersion} is published`,
|
|
@@ -7355,16 +7367,16 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
7355
7367
|
`Infra PR must declare CodeBuild image builder ${prefix}-${stage}-image-builder for @hasna/uptime@${runtimePackageVersion}.`,
|
|
7356
7368
|
`Infra PR must declare hardened S3 evidence bucket ${evidenceBucket} with KMS, versioning, lifecycle, and public access block.`,
|
|
7357
7369
|
`Infra PR must declare encrypted EFS ${prefix}-${stage}-data with access point, mount targets, and AWS Backup plan.`,
|
|
7358
|
-
protectedAccessMode === "cloudfront_default_domain" ? "Infra PR must declare CloudFront default-domain HTTPS edge, ALB
|
|
7370
|
+
protectedAccessMode === "cloudfront_default_domain" ? "Infra PR must declare CloudFront default-domain HTTPS edge, ALB origin listener restricted to CloudFront origin-facing ranges, CloudFront-only origin verification header binding, ECS/Fargate cluster, target groups, security groups, IAM roles, CloudWatch log groups, and Secrets Manager refs. Token-bearing live traffic must use cloudfront_origin_protocol_policy=https-only with a matching origin hostname/certificate, or carry explicit HTTP-origin risk acceptance." : `Infra PR must declare ECS/Fargate cluster ${cluster}, ALB HTTPS listener, target groups, security groups, IAM roles, CloudWatch log groups, and Secrets Manager refs.`,
|
|
7359
7371
|
"Only apply the infra plan from the approved infrastructure repository after review evidence is attached."
|
|
7360
7372
|
],
|
|
7361
7373
|
deploy: [
|
|
7362
7374
|
"Build and publish the image only after the Dockerfile/container target is reviewed.",
|
|
7363
|
-
`Start the AWS image builder for @hasna/uptime@${runtimePackageVersion}
|
|
7375
|
+
runtimePackageIntegrity ? `Start the AWS image builder for @hasna/uptime@${runtimePackageVersion}; it must verify npm dist.integrity ${runtimePackageIntegrity} before extracting the package, then record the pushed image digest.` : `Start the AWS image builder for @hasna/uptime@${runtimePackageVersion}; set runtime_package_integrity from npm dist.integrity before live use, then record the pushed image digest.`,
|
|
7364
7376
|
"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.",
|
|
7365
7377
|
`Register task definitions for ${services.map((service) => service.name).join(", ")} using valueFrom secrets.`,
|
|
7366
7378
|
`Update ECS services in cluster ${cluster} one component at a time through the approved deploy pipeline.`,
|
|
7367
|
-
protectedAccessMode === "cloudfront_default_domain" ? "Use the CloudFront default HTTPS domain with origin verification header binding for first protected access;
|
|
7379
|
+
protectedAccessMode === "cloudfront_default_domain" ? "Use the CloudFront default HTTPS domain with origin verification header binding for first protected access; before token-bearing live traffic, switch the origin to https-only with a matching origin hostname/certificate or record explicit HTTP-origin risk acceptance." : `Create Route53/edge record for ${hostname} only after ALB health checks pass and auth denial smokes succeed.`
|
|
7368
7380
|
],
|
|
7369
7381
|
rollback: [
|
|
7370
7382
|
"Keep previous task definition ARNs before each service update.",
|
|
@@ -7381,6 +7393,8 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
7381
7393
|
blockers: [
|
|
7382
7394
|
"The infrastructure owner repository was not found in this workspace.",
|
|
7383
7395
|
protectedAccessMode === "cloudfront_default_domain" ? "CloudFront origin verification header binding must be enabled and direct-origin denial must be proven before web desired count is raised above 0." : "ALB HTTPS ingress policy and auth-denial smokes must be proven before web desired count is raised above 0.",
|
|
7396
|
+
...protectedAccessMode === "cloudfront_default_domain" && cloudfrontOriginProtocolPolicy === "http-only" ? ["CloudFront-to-ALB origin transport is still http-only; token-bearing live traffic needs https-only origin mode or explicit risk acceptance."] : [],
|
|
7397
|
+
...protectedAccessMode === "cloudfront_default_domain" && cloudfrontOriginProtocolPolicy === "https-only" && cloudfrontOriginDomainName === "<alb-dns-name>" ? ["CloudFront https-only origin mode needs cloudfront_origin_domain_name that resolves to the ALB and matches certificate_arn."] : [],
|
|
7384
7398
|
"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.",
|
|
7385
7399
|
"Hosted production auth/RBAC must replace broad static hosted-token operation before exposure.",
|
|
7386
7400
|
"Public probe execution still needs cloud check-job leases wired to runHostedHttpCheck and live policy-decision log evidence.",
|
|
@@ -7389,8 +7403,9 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
7389
7403
|
requiredEvidence: [
|
|
7390
7404
|
"Infrastructure PR/synth/plan from the approved infra repository.",
|
|
7391
7405
|
"CodeBuild image-builder run, container smoke, and immutable image digest.",
|
|
7406
|
+
"Published package dist.integrity pinned in the private infra root or an explicit not-live exception.",
|
|
7392
7407
|
"ECS task definitions using secrets.valueFrom only.",
|
|
7393
|
-
"CloudFront-default-domain origin-header config
|
|
7408
|
+
"CloudFront-default-domain origin-header config, origin transport decision, direct-origin denial evidence, auth-denial smokes, and web alarm checks.",
|
|
7394
7409
|
"Single-writer ECS evidence: one web task maximum and no scheduler/public-probe/reporter EFS mounts.",
|
|
7395
7410
|
"EFS encryption, access point, mount-target, AWS Backup, and restore-drill evidence.",
|
|
7396
7411
|
"S3 bucket KMS, versioning, lifecycle, and public-access-block evidence.",
|
|
@@ -7403,11 +7418,13 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
7403
7418
|
notes: [
|
|
7404
7419
|
"This plan generator does not call AWS.",
|
|
7405
7420
|
"Blocked plan output intentionally avoids copy-pastable AWS mutation commands.",
|
|
7406
|
-
"Default protected access uses CloudFront's HTTPS default domain so first deploy is not blocked on custom DNS or ACM.",
|
|
7421
|
+
"Default protected access uses CloudFront's HTTPS default domain so first zero-count deploy is not blocked on custom DNS or ACM.",
|
|
7407
7422
|
"CloudFront default-domain mode still requires origin verification header binding before live scale-up; the header value is sensitive state/config material, not public documentation.",
|
|
7423
|
+
"CloudFront HTTPS-origin mode requires a dedicated origin DNS hostname and matching ACM certificate; do not assume the ALB DNS name can satisfy TLS verification.",
|
|
7408
7424
|
"Hosted runtime uses explicit EFS-backed SQLite at HASNA_UPTIME_HOSTED_SQLITE_DB until the async Postgres adapter exists.",
|
|
7409
7425
|
"Do not set HASNA_UPTIME_DATABASE_URL for hosted tasks until the Postgres adapter is implemented.",
|
|
7410
7426
|
"Secrets are represented as secret names/refs and must be injected with valueFrom.",
|
|
7427
|
+
"Set runtime_package_integrity in the approved infra root after publish so the AWS image builder verifies the npm tarball before ECR build.",
|
|
7411
7428
|
"Actual deploy belongs in the deploy_release_operate_final goal node after infra review."
|
|
7412
7429
|
]
|
|
7413
7430
|
}
|
|
@@ -7829,7 +7846,7 @@ program2.command("audit").description("List local audit events").option("--resou
|
|
|
7829
7846
|
}
|
|
7830
7847
|
});
|
|
7831
7848
|
var cloud = program2.command("cloud").description("Generate dry-run cloud deployment and private-probe configuration artifacts");
|
|
7832
|
-
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) => {
|
|
7849
|
+
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("--runtime-package-integrity <integrity>", "expected npm dist.integrity for the runtime package").addOption(new Option("--protected-access-mode <mode>", "protected web access mode").choices(["cloudfront_default_domain", "alb_https_cert"]).default("cloudfront_default_domain")).addOption(new Option("--cloudfront-origin-protocol-policy <policy>", "CloudFront-to-ALB origin protocol policy").choices(["http-only", "https-only"]).default("http-only")).option("--cloudfront-origin-domain-name <hostname>", "origin hostname for CloudFront https-only mode; must resolve to the ALB and match certificate_arn").option("--evidence-bucket <name>", "S3 evidence bucket name").option("-j, --json", "print JSON").action((opts) => {
|
|
7833
7850
|
try {
|
|
7834
7851
|
const plan = buildAwsDeploymentPlan({
|
|
7835
7852
|
accountName: opts.account,
|
|
@@ -7844,7 +7861,10 @@ cloud.command("plan").description("Generate a dry-run AWS deployment plan").opti
|
|
|
7844
7861
|
ecrRepository: opts.ecrRepository,
|
|
7845
7862
|
image: opts.image,
|
|
7846
7863
|
runtimePackageVersion: opts.runtimePackageVersion,
|
|
7864
|
+
runtimePackageIntegrity: opts.runtimePackageIntegrity,
|
|
7847
7865
|
protectedAccessMode: opts.protectedAccessMode,
|
|
7866
|
+
cloudfrontOriginProtocolPolicy: opts.cloudfrontOriginProtocolPolicy,
|
|
7867
|
+
cloudfrontOriginDomainName: opts.cloudfrontOriginDomainName,
|
|
7848
7868
|
evidenceBucket: opts.evidenceBucket
|
|
7849
7869
|
});
|
|
7850
7870
|
print(plan, renderCloudPlan(plan), opts);
|
|
@@ -8248,6 +8268,7 @@ function renderCloudPlan(plan) {
|
|
|
8248
8268
|
`host: ${plan.hostname}`,
|
|
8249
8269
|
`cluster: ${plan.resources.ecsCluster}`,
|
|
8250
8270
|
`image: ${plan.image.uri}`,
|
|
8271
|
+
...plan.image.expectedIntegrity ? [`package integrity: ${plan.image.expectedIntegrity}`] : [],
|
|
8251
8272
|
`image builder: ${plan.resources.imageBuilder}`,
|
|
8252
8273
|
`dockerfile: ${plan.image.dockerfile}`,
|
|
8253
8274
|
`infra: ${plan.infra.path}`,
|
|
@@ -8255,6 +8276,7 @@ function renderCloudPlan(plan) {
|
|
|
8255
8276
|
`efs: ${plan.resources.efsFileSystem}`,
|
|
8256
8277
|
`hosted sqlite: ${plan.resources.hostedSqliteDbPath}`,
|
|
8257
8278
|
`protected access: ${plan.resources.protectedAccessMode} ${plan.resources.protectedAccessUrl}`,
|
|
8279
|
+
...plan.resources.cloudfrontOrigin ? [`cloudfront origin: ${plan.resources.cloudfrontOrigin.protocolPolicy} ${plan.resources.cloudfrontOrigin.domainName}`] : [],
|
|
8258
8280
|
`services: ${plan.resources.services.map((service2) => `${service2.name}:${service2.desiredCount}/${service2.targetDesiredCount}`).join(", ")}`,
|
|
8259
8281
|
`evidence bucket: ${plan.resources.evidenceBucket}`,
|
|
8260
8282
|
`blockers: ${plan.blockers.length}`,
|
package/dist/cloud-plan.d.ts
CHANGED
|
@@ -11,7 +11,10 @@ export interface AwsDeploymentPlanOptions {
|
|
|
11
11
|
evidenceBucket?: string;
|
|
12
12
|
hostedSqliteDbPath?: string;
|
|
13
13
|
runtimePackageVersion?: string;
|
|
14
|
+
runtimePackageIntegrity?: string;
|
|
14
15
|
protectedAccessMode?: "cloudfront_default_domain" | "alb_https_cert";
|
|
16
|
+
cloudfrontOriginProtocolPolicy?: "http-only" | "https-only";
|
|
17
|
+
cloudfrontOriginDomainName?: string;
|
|
15
18
|
/** @deprecated Postgres is target-state only until the async adapter is implemented. */
|
|
16
19
|
rdsInstanceId?: string;
|
|
17
20
|
/** @deprecated Postgres is target-state only until the async adapter is implemented. */
|
|
@@ -49,6 +52,13 @@ export interface AwsDeploymentPlan {
|
|
|
49
52
|
protectedAccessMode: "cloudfront_default_domain" | "alb_https_cert";
|
|
50
53
|
edgeDistribution?: string;
|
|
51
54
|
protectedAccessUrl: string;
|
|
55
|
+
cloudfrontOrigin?: {
|
|
56
|
+
protocolPolicy: "http-only" | "https-only";
|
|
57
|
+
domainName: string;
|
|
58
|
+
requiresMatchingCertificate: boolean;
|
|
59
|
+
liveTrafficApproved: boolean;
|
|
60
|
+
risk?: string;
|
|
61
|
+
};
|
|
52
62
|
originVerification: {
|
|
53
63
|
mode: "cloudfront_origin_header" | "alb_tls";
|
|
54
64
|
requiredBeforeScaleUp: boolean;
|
|
@@ -66,6 +76,7 @@ export interface AwsDeploymentPlan {
|
|
|
66
76
|
repository: string;
|
|
67
77
|
uri: string;
|
|
68
78
|
dockerfile: string;
|
|
79
|
+
expectedIntegrity?: string;
|
|
69
80
|
buildCommand: string;
|
|
70
81
|
pushCommands: string[];
|
|
71
82
|
};
|
package/dist/cloud-plan.d.ts.map
CHANGED
|
@@ -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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"}
|
package/dist/cloud-plan.js
CHANGED
|
@@ -9,6 +9,7 @@ var DEFAULT_WORKSPACE_ID = "workspace-id";
|
|
|
9
9
|
var DEFAULT_VPC_ID = "vpc-xxxxxxxx";
|
|
10
10
|
var DEFAULT_HOSTED_SQLITE_DB = "/data/uptime/uptime.db";
|
|
11
11
|
var DEFAULT_PROTECTED_ACCESS_MODE = "cloudfront_default_domain";
|
|
12
|
+
var DEFAULT_CLOUDFRONT_ORIGIN_PROTOCOL_POLICY = "http-only";
|
|
12
13
|
function buildAwsDeploymentPlan(options = {}) {
|
|
13
14
|
const region = clean(options.region, DEFAULT_REGION);
|
|
14
15
|
const stage = clean(options.stage, DEFAULT_STAGE);
|
|
@@ -21,8 +22,11 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
21
22
|
const image = clean(options.image, `${imageRepositoryUri}@sha256:<image-digest>`);
|
|
22
23
|
const evidenceBucket = clean(options.evidenceBucket, `hasna-${stage}-${prefix}-evidence`);
|
|
23
24
|
const hostedSqliteDbPath = clean(options.hostedSqliteDbPath, DEFAULT_HOSTED_SQLITE_DB);
|
|
24
|
-
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.
|
|
25
|
+
const runtimePackageVersion = clean(options.runtimePackageVersion, "0.1.25");
|
|
26
|
+
const runtimePackageIntegrity = options.runtimePackageIntegrity?.trim() || undefined;
|
|
25
27
|
const protectedAccessMode = options.protectedAccessMode ?? DEFAULT_PROTECTED_ACCESS_MODE;
|
|
28
|
+
const cloudfrontOriginProtocolPolicy = options.cloudfrontOriginProtocolPolicy ?? DEFAULT_CLOUDFRONT_ORIGIN_PROTOCOL_POLICY;
|
|
29
|
+
const cloudfrontOriginDomainName = clean(options.cloudfrontOriginDomainName, "<alb-dns-name>");
|
|
26
30
|
const protectedAccessUrl = protectedAccessMode === "cloudfront_default_domain" ? "https://<cloudfront-domain>" : `https://${hostname}`;
|
|
27
31
|
const cluster = `${prefix}-${stage}`;
|
|
28
32
|
const secrets = {
|
|
@@ -89,6 +93,13 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
89
93
|
protectedAccessMode,
|
|
90
94
|
edgeDistribution: protectedAccessMode === "cloudfront_default_domain" ? `${prefix}-${stage}-edge` : undefined,
|
|
91
95
|
protectedAccessUrl,
|
|
96
|
+
cloudfrontOrigin: protectedAccessMode === "cloudfront_default_domain" ? {
|
|
97
|
+
protocolPolicy: cloudfrontOriginProtocolPolicy,
|
|
98
|
+
domainName: cloudfrontOriginProtocolPolicy === "https-only" ? cloudfrontOriginDomainName : "<alb-dns-name>",
|
|
99
|
+
requiresMatchingCertificate: cloudfrontOriginProtocolPolicy === "https-only",
|
|
100
|
+
liveTrafficApproved: false,
|
|
101
|
+
risk: cloudfrontOriginProtocolPolicy === "http-only" ? "Temporary HTTP-origin bridge: do not use for token-bearing live traffic without explicit risk acceptance, or switch to https-only with cloudfront_origin_domain_name plus certificate_arn." : "CloudFront HTTPS-origin mode requires the origin hostname to resolve to the ALB and match certificate_arn."
|
|
102
|
+
} : undefined,
|
|
92
103
|
originVerification: protectedAccessMode === "cloudfront_default_domain" ? {
|
|
93
104
|
mode: "cloudfront_origin_header",
|
|
94
105
|
requiredBeforeScaleUp: true,
|
|
@@ -121,6 +132,7 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
121
132
|
repository: ecrRepository,
|
|
122
133
|
uri: image,
|
|
123
134
|
dockerfile: "Dockerfile.package",
|
|
135
|
+
expectedIntegrity: runtimePackageIntegrity,
|
|
124
136
|
buildCommand: `BLOCKED: after infra approval, AWS CodeBuild builds Dockerfile.package from @hasna/uptime@${runtimePackageVersion} into ${imageRepositoryUri}`,
|
|
125
137
|
pushCommands: [
|
|
126
138
|
`BLOCKED: start ${prefix}-${stage}-image-builder only through the approved deploy pipeline after @hasna/uptime@${runtimePackageVersion} is published`,
|
|
@@ -147,16 +159,16 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
147
159
|
`Infra PR must declare CodeBuild image builder ${prefix}-${stage}-image-builder for @hasna/uptime@${runtimePackageVersion}.`,
|
|
148
160
|
`Infra PR must declare hardened S3 evidence bucket ${evidenceBucket} with KMS, versioning, lifecycle, and public access block.`,
|
|
149
161
|
`Infra PR must declare encrypted EFS ${prefix}-${stage}-data with access point, mount targets, and AWS Backup plan.`,
|
|
150
|
-
protectedAccessMode === "cloudfront_default_domain" ? "Infra PR must declare CloudFront default-domain HTTPS edge, ALB
|
|
162
|
+
protectedAccessMode === "cloudfront_default_domain" ? "Infra PR must declare CloudFront default-domain HTTPS edge, ALB origin listener restricted to CloudFront origin-facing ranges, CloudFront-only origin verification header binding, ECS/Fargate cluster, target groups, security groups, IAM roles, CloudWatch log groups, and Secrets Manager refs. Token-bearing live traffic must use cloudfront_origin_protocol_policy=https-only with a matching origin hostname/certificate, or carry explicit HTTP-origin risk acceptance." : `Infra PR must declare ECS/Fargate cluster ${cluster}, ALB HTTPS listener, target groups, security groups, IAM roles, CloudWatch log groups, and Secrets Manager refs.`,
|
|
151
163
|
"Only apply the infra plan from the approved infrastructure repository after review evidence is attached."
|
|
152
164
|
],
|
|
153
165
|
deploy: [
|
|
154
166
|
"Build and publish the image only after the Dockerfile/container target is reviewed.",
|
|
155
|
-
`Start the AWS image builder for @hasna/uptime@${runtimePackageVersion}
|
|
167
|
+
runtimePackageIntegrity ? `Start the AWS image builder for @hasna/uptime@${runtimePackageVersion}; it must verify npm dist.integrity ${runtimePackageIntegrity} before extracting the package, then record the pushed image digest.` : `Start the AWS image builder for @hasna/uptime@${runtimePackageVersion}; set runtime_package_integrity from npm dist.integrity before live use, then record the pushed image digest.`,
|
|
156
168
|
"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.",
|
|
157
169
|
`Register task definitions for ${services.map((service) => service.name).join(", ")} using valueFrom secrets.`,
|
|
158
170
|
`Update ECS services in cluster ${cluster} one component at a time through the approved deploy pipeline.`,
|
|
159
|
-
protectedAccessMode === "cloudfront_default_domain" ? "Use the CloudFront default HTTPS domain with origin verification header binding for first protected access;
|
|
171
|
+
protectedAccessMode === "cloudfront_default_domain" ? "Use the CloudFront default HTTPS domain with origin verification header binding for first protected access; before token-bearing live traffic, switch the origin to https-only with a matching origin hostname/certificate or record explicit HTTP-origin risk acceptance." : `Create Route53/edge record for ${hostname} only after ALB health checks pass and auth denial smokes succeed.`
|
|
160
172
|
],
|
|
161
173
|
rollback: [
|
|
162
174
|
"Keep previous task definition ARNs before each service update.",
|
|
@@ -173,6 +185,8 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
173
185
|
blockers: [
|
|
174
186
|
"The infrastructure owner repository was not found in this workspace.",
|
|
175
187
|
protectedAccessMode === "cloudfront_default_domain" ? "CloudFront origin verification header binding must be enabled and direct-origin denial must be proven before web desired count is raised above 0." : "ALB HTTPS ingress policy and auth-denial smokes must be proven before web desired count is raised above 0.",
|
|
188
|
+
...protectedAccessMode === "cloudfront_default_domain" && cloudfrontOriginProtocolPolicy === "http-only" ? ["CloudFront-to-ALB origin transport is still http-only; token-bearing live traffic needs https-only origin mode or explicit risk acceptance."] : [],
|
|
189
|
+
...protectedAccessMode === "cloudfront_default_domain" && cloudfrontOriginProtocolPolicy === "https-only" && cloudfrontOriginDomainName === "<alb-dns-name>" ? ["CloudFront https-only origin mode needs cloudfront_origin_domain_name that resolves to the ALB and matches certificate_arn."] : [],
|
|
176
190
|
"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.",
|
|
177
191
|
"Hosted production auth/RBAC must replace broad static hosted-token operation before exposure.",
|
|
178
192
|
"Public probe execution still needs cloud check-job leases wired to runHostedHttpCheck and live policy-decision log evidence.",
|
|
@@ -181,8 +195,9 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
181
195
|
requiredEvidence: [
|
|
182
196
|
"Infrastructure PR/synth/plan from the approved infra repository.",
|
|
183
197
|
"CodeBuild image-builder run, container smoke, and immutable image digest.",
|
|
198
|
+
"Published package dist.integrity pinned in the private infra root or an explicit not-live exception.",
|
|
184
199
|
"ECS task definitions using secrets.valueFrom only.",
|
|
185
|
-
"CloudFront-default-domain origin-header config
|
|
200
|
+
"CloudFront-default-domain origin-header config, origin transport decision, direct-origin denial evidence, auth-denial smokes, and web alarm checks.",
|
|
186
201
|
"Single-writer ECS evidence: one web task maximum and no scheduler/public-probe/reporter EFS mounts.",
|
|
187
202
|
"EFS encryption, access point, mount-target, AWS Backup, and restore-drill evidence.",
|
|
188
203
|
"S3 bucket KMS, versioning, lifecycle, and public-access-block evidence.",
|
|
@@ -195,11 +210,13 @@ function buildAwsDeploymentPlan(options = {}) {
|
|
|
195
210
|
notes: [
|
|
196
211
|
"This plan generator does not call AWS.",
|
|
197
212
|
"Blocked plan output intentionally avoids copy-pastable AWS mutation commands.",
|
|
198
|
-
"Default protected access uses CloudFront's HTTPS default domain so first deploy is not blocked on custom DNS or ACM.",
|
|
213
|
+
"Default protected access uses CloudFront's HTTPS default domain so first zero-count deploy is not blocked on custom DNS or ACM.",
|
|
199
214
|
"CloudFront default-domain mode still requires origin verification header binding before live scale-up; the header value is sensitive state/config material, not public documentation.",
|
|
215
|
+
"CloudFront HTTPS-origin mode requires a dedicated origin DNS hostname and matching ACM certificate; do not assume the ALB DNS name can satisfy TLS verification.",
|
|
200
216
|
"Hosted runtime uses explicit EFS-backed SQLite at HASNA_UPTIME_HOSTED_SQLITE_DB until the async Postgres adapter exists.",
|
|
201
217
|
"Do not set HASNA_UPTIME_DATABASE_URL for hosted tasks until the Postgres adapter is implemented.",
|
|
202
218
|
"Secrets are represented as secret names/refs and must be injected with valueFrom.",
|
|
219
|
+
"Set runtime_package_integrity in the approved infra root after publish so the AWS image builder verifies the npm tarball before ECR build.",
|
|
203
220
|
"Actual deploy belongs in the deploy_release_operate_final goal node after infra review."
|
|
204
221
|
]
|
|
205
222
|
}
|