feat(hololake): render bounded release front door config
This commit is contained in:
parent
9006075310
commit
461517c25f
6 changed files with 131 additions and 0 deletions
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"schema": "hololake.jd-release-public-path-acceptance-receipt/v1",
|
||||
"receiptId": "GH-HOLOLAKE-JD-RELEASE-PUBLIC-PATH-20260813-004",
|
||||
"observedAt": "2026-08-13T19:13:32+08:00",
|
||||
"state": "JD_LOOPBACK_PUBLIC_NAMESPACE_READY_FRONT_DOOR_NOT_DEPLOYED",
|
||||
"target": "JD-FD-PRIMARY",
|
||||
"sourceCommit": "9006075310729cb7c266decff529066053969f18",
|
||||
"immutableSourcePath": "/opt/guanghu/hololake-release-broadcast-candidate/9006075310729cb7c266decff529066053969f18",
|
||||
"serverOwnedReceipt": "/var/lib/guanghu/architecture-provision/receipts/GH-HOLOLAKE-JD-RELEASE-PUBLIC-PATH-20260813-001.json",
|
||||
"serverOwnedReceiptSha256": "923564c7f624921bcab247e9e27fc007953bbd6c06733356be1bdd9420f5ef1d",
|
||||
"liveReadback": {
|
||||
"serviceActive": true,
|
||||
"serviceEnabled": true,
|
||||
"listener": "127.0.0.1:3940",
|
||||
"publicPathPrefix": "/hololake/releases",
|
||||
"releaseEndpointPath": "/hololake/releases/latest.json",
|
||||
"legacyLatestStatus": 204,
|
||||
"publicLatestStatus": 204,
|
||||
"broadcastState": "EMPTY_FAIL_CLOSED",
|
||||
"updateAvailable": false,
|
||||
"stateFileCount": 0,
|
||||
"automaticUpload": false,
|
||||
"automaticActivation": false,
|
||||
"automaticRestart": false,
|
||||
"existingDiscoveryServiceActive": true,
|
||||
"existingLivingControllerActive": true,
|
||||
"existingMotherBrainActive": true
|
||||
},
|
||||
"publicObservation": {
|
||||
"url": "https://guanghulab.com/hololake/releases/latest.json",
|
||||
"httpStatus": 200,
|
||||
"contentType": "text/html",
|
||||
"matchesReleaseProtocol": false,
|
||||
"inference": "BS_GZ_006_HOMEPAGE_FALLBACK_NO_HOLOLAKE_PROXY"
|
||||
},
|
||||
"productionBoundary": {
|
||||
"frontDoorLoopbackPortAssigned": false,
|
||||
"frontDoorProxyDeployed": false,
|
||||
"publicHttpsReleaseEndpointProvisioned": false,
|
||||
"updaterPublicKeyProvisioned": false,
|
||||
"desktopReleaseTrustProvisioned": false,
|
||||
"publicDistributionReady": false,
|
||||
"repositoryPublicationClaimed": false
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
"release_public_route_contract": "server/release-broadcast/public-route.json",
|
||||
"release_public_path_prefix": "/hololake/releases",
|
||||
"release_public_route_deployed": false,
|
||||
"release_front_door_bounded_config_renderer_implemented": true,
|
||||
"release_broadcast_explicit_operator_activation_implemented": true,
|
||||
"release_broadcast_activation_requires_exact_human_approval": true,
|
||||
"release_broadcast_activation_requires_repeated_expected_facts": true,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ test('release activation remains explicitly human controlled', () => {
|
|||
assert.equal(publicRoute.proxyRequestUriPolicy, 'PRESERVE_FULL_PUBLIC_PATH')
|
||||
assert.equal(publicRoute.frontDoorLoopbackPort, null)
|
||||
assert.equal(publicRoute.deployed, false)
|
||||
assert.equal(foundation.release_front_door_bounded_config_renderer_implemented, true)
|
||||
assert.equal(foundation.release_pipeline_automatic_upload_allowed, false)
|
||||
assert.equal(
|
||||
foundation.release_production_activation_state,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import { renderFrontDoorSnippet } from '../server/release-broadcast/render-front-door.mjs'
|
||||
|
||||
test('front-door renderer refuses an unassigned or privileged loopback port', () => {
|
||||
assert.throws(() => renderFrontDoorSnippet(null), /PORT_REQUIRED/)
|
||||
assert.throws(() => renderFrontDoorSnippet(443), /PORT_REQUIRED|PORT_INVALID/)
|
||||
assert.throws(() => renderFrontDoorSnippet('not-a-port'), /PORT_REQUIRED/)
|
||||
})
|
||||
|
||||
test('rendered proxy preserves the public path and strips request authority', () => {
|
||||
const snippet = renderFrontDoorSnippet(23940)
|
||||
assert.match(snippet, /location \^~ \/hololake\/releases\//)
|
||||
assert.match(snippet, /proxy_pass http:\/\/127\.0\.0\.1:23940;/)
|
||||
assert.doesNotMatch(snippet, /proxy_pass http:\/\/127\.0\.0\.1:23940\//)
|
||||
assert.match(snippet, /limit_except GET HEAD \{ deny all; \}/)
|
||||
assert.match(snippet, /proxy_pass_request_body off;/)
|
||||
assert.match(snippet, /proxy_set_header Authorization "";/)
|
||||
assert.match(snippet, /proxy_set_header Cookie "";/)
|
||||
assert.match(snippet, /proxy_set_header X-Forwarded-For "";/)
|
||||
})
|
||||
|
|
@ -23,6 +23,14 @@ preserve the full request URI. Its loopback tunnel port remains deliberately
|
|||
unassigned until the BS-GZ-006 route owner returns the live, non-conflicting
|
||||
topology.
|
||||
|
||||
Once that port is returned and independently verified, `render-front-door.mjs
|
||||
--loopback-port PORT` renders the bounded Nginx location. It refuses an omitted
|
||||
port, preserves the full public request path by leaving `proxy_pass` without a
|
||||
URI suffix, accepts only GET and HEAD, forwards no request body, and strips
|
||||
authorization, cookies, and client forwarding headers. Rendering is not
|
||||
deployment; Nginx validation, transactional install, public certificate/readback,
|
||||
and a separate server receipt remain required.
|
||||
|
||||
`operator.mjs` supplies the separate, root-operated verification and activation
|
||||
boundary. `verify` reconstructs a private candidate tree and accepts it only when
|
||||
the broadcast, pipeline receipt, package bytes, Developer ID receipt, Apple
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const PORT_PATTERN = /^(?:[1-9]\d{3,4})$/
|
||||
|
||||
const fail = (code) => {
|
||||
throw new Error(code)
|
||||
}
|
||||
|
||||
export function renderFrontDoorSnippet(portValue) {
|
||||
const text = String(portValue ?? '')
|
||||
if (!PORT_PATTERN.test(text)) fail('HOLOLAKE_RELEASE_FRONT_DOOR_PORT_REQUIRED')
|
||||
const port = Number(text)
|
||||
if (!Number.isInteger(port) || port < 1024 || port > 65535) fail('HOLOLAKE_RELEASE_FRONT_DOOR_PORT_INVALID')
|
||||
return `location = /hololake/releases {
|
||||
return 308 /hololake/releases/;
|
||||
}
|
||||
|
||||
location ^~ /hololake/releases/ {
|
||||
limit_except GET HEAD { deny all; }
|
||||
client_max_body_size 0;
|
||||
proxy_pass http://127.0.0.1:${port};
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Connection "";
|
||||
proxy_set_header Authorization "";
|
||||
proxy_set_header Cookie "";
|
||||
proxy_set_header X-Forwarded-For "";
|
||||
proxy_set_header X-Forwarded-Host "";
|
||||
proxy_set_header X-Forwarded-Proto "";
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_connect_timeout 2s;
|
||||
proxy_send_timeout 10s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
export function main(argv = process.argv.slice(2)) {
|
||||
const portIndex = argv.indexOf('--loopback-port')
|
||||
if (portIndex < 0 || portIndex + 1 >= argv.length || argv.length !== 2) {
|
||||
fail('HOLOLAKE_RELEASE_FRONT_DOOR_USAGE:--loopback-port PORT')
|
||||
}
|
||||
process.stdout.write(renderFrontDoorSnippet(argv[portIndex + 1]))
|
||||
}
|
||||
|
||||
if (process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href) {
|
||||
try {
|
||||
main()
|
||||
} catch (error) {
|
||||
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`)
|
||||
process.exitCode = 1
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue