Merge origin/main into align-wilm-main (align wilm with Cameron's latest)

Bring main's endpoint hardening, operator-report validation, launch-path
policy, and theme-variable CSS into wilm. Channel model reconciled to this
repo's shipping (stable=release tag, edge=main trunk) while keeping wilm's
remote-BuildKit publish step and GHCR pull-based launcher.
This commit is contained in:
benjamin.baker
2026-09-02 17:41:03 -04:00
33 changed files with 1539 additions and 117 deletions

View File

@@ -12,7 +12,7 @@
passed, because the app itself runs entirely in the container.
2. Picks a channel:
stable -> pulls the 'stable' image (built from main), no DEV badge.
edge -> pulls the 'edge' image (built from dev-be), red DEV badge.
edge -> pulls the 'edge' image (built from main), red DEV badge.
The two channels use different compose project names, host ports, and
named volumes, so they run side by side without colliding.
3. Generates a .env for the channel (dev-grade secrets, NOT for production)
@@ -25,10 +25,10 @@
installer - see deploy/windows/installer/shopdb-install.ps1 for that.
.PARAMETER Channel
'stable' (main) or 'edge' (dev-be). Defaults to 'stable'.
'stable' (the newest release tag) or 'edge' (main, the trunk). Defaults to 'stable'.
.PARAMETER Ref
Override the git ref to build. Defaults to 'main' for stable, 'dev-be' for
Override the git ref to build. Defaults to the newest v* tag for stable, 'main' for
edge. Retained for compatibility; the pull flow selects the image by channel
tag, so this now only affects which branch the working tree is prepared on.
@@ -74,7 +74,7 @@ $channels = @{
ImageTag = 'stable'
}
edge = @{
Ref = 'dev-be'
Ref = 'main'
Project = 'shopdb-edge'
ApiPort = 5011
MysqlPort = 3316
@@ -282,10 +282,20 @@ try {
} else {
# Dev-grade secrets: generated locally, never for production. A real
# deploy fills .env from the wiki runbook, not from this script.
$secret = [Convert]::ToBase64String((1..48 | ForEach-Object { Get-Random -Maximum 256 }))
$jwt = [Convert]::ToBase64String((1..48 | ForEach-Object { Get-Random -Maximum 256 }))
$dbPass = [Convert]::ToBase64String((1..18 | ForEach-Object { Get-Random -Maximum 256 })) -replace '[^A-Za-z0-9]', 'x'
$rootPass = [Convert]::ToBase64String((1..18 | ForEach-Object { Get-Random -Maximum 256 })) -replace '[^A-Za-z0-9]', 'x'
#
# Get-Random is System.Random: a 32-bit seed, and all four values came
# off one stream, so recovering the seed from any one of them recovers
# the other three. These sign JWTs for a stack a pilot may point at a
# real imported dataset, so they come from the CSPRNG instead. "Dev
# grade" is about rotation and provenance, not about being guessable.
$secret = [Convert]::ToBase64String(
[System.Security.Cryptography.RandomNumberGenerator]::GetBytes(48))
$jwt = [Convert]::ToBase64String(
[System.Security.Cryptography.RandomNumberGenerator]::GetBytes(48))
$dbPass = ([Convert]::ToBase64String(
[System.Security.Cryptography.RandomNumberGenerator]::GetBytes(18))) -replace '[^A-Za-z0-9]', 'x'
$rootPass = ([Convert]::ToBase64String(
[System.Security.Cryptography.RandomNumberGenerator]::GetBytes(18))) -replace '[^A-Za-z0-9]', 'x'
$apiPort = $config.ApiPort
$mysqlPort = $config.MysqlPort
$image = "$imageRepo`:$($config.ImageTag)"