fix: make server operations executable
This commit is contained in:
@@ -20,6 +20,8 @@ for fixture in \
|
||||
"Caddy reverse-proxy guide contract" \
|
||||
"local installation example rendered from path with spaces" \
|
||||
"server installation example rendered from path with spaces" \
|
||||
"server pinned migration image fixture" \
|
||||
"server backup checksum root-only fixture" \
|
||||
"local manual canonical base+override references" \
|
||||
"server manual canonical base+override references" \
|
||||
"canonical local base+override fixture" \
|
||||
@@ -33,6 +35,32 @@ for fixture in \
|
||||
}
|
||||
done
|
||||
|
||||
server_guide="$root/docs/install/server.md"
|
||||
for required in \
|
||||
'thothii-ops' \
|
||||
'THT_BACKUP_ROOT=/srv/thothii-backups' \
|
||||
'sessions migrate --yes' \
|
||||
'"pending":[]' \
|
||||
'"drifted":[]' \
|
||||
'remove --yes' \
|
||||
'sha256sum --check SHA256SUMS' \
|
||||
'DOCKER-USER' \
|
||||
'iptables -I INPUT' \
|
||||
'com.docker.network.bridge.name'; do
|
||||
grep -Fq -- "$required" "$server_guide" || {
|
||||
echo "server operations guide lacks executable contract: $required" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
grep -Fq '"$THTCTL" --help' "$server_guide" || {
|
||||
echo "server guide lacks plain thothctl --help" >&2
|
||||
exit 1
|
||||
}
|
||||
if grep -Fq '"$THTCTL" --installation "$INSTALLATION" --help' "$server_guide"; then
|
||||
echo "server guide still uses installation-scoped --help" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for manual in "$root/docs/install/local-workspace-registry.md"; do
|
||||
grep -Fq 'export THT_SOURCE_ROOT=/absolute/path/to/ThothII' "$manual" || {
|
||||
echo "installation manual does not publish a self-contained THT_SOURCE_ROOT export: $manual" >&2
|
||||
@@ -114,6 +142,18 @@ switch (mutation) {
|
||||
case "server-coupling":
|
||||
changed += "\nAttach core to the omics_portal application network.\n";
|
||||
break;
|
||||
case "server-host-loopback":
|
||||
changed += "\nFor host-gateway, keep the external service listening on 127.0.0.1.\n";
|
||||
break;
|
||||
case "server-raw-remove":
|
||||
changed += "\n```sh\ndocker rm thothii-core thothii-frontend\n```\n";
|
||||
break;
|
||||
case "server-pinned-migrator-mismatch":
|
||||
changed += "\n```yaml\nservices:\n core:\n image: registry.invalid/core@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n session-migrate:\n image: thothii-core:local\n```\n";
|
||||
break;
|
||||
case "server-pinned-frontend-missing":
|
||||
changed = original.replace(' frontend:\n build: !reset null\n image: registry.example.com/thothii/frontend@sha256:<64-lowercase-hex-digits>\n', '');
|
||||
break;
|
||||
case "nginx-no-auth":
|
||||
changed = original.replace(" auth_request /_authenticate;", " # authentication omitted");
|
||||
break;
|
||||
@@ -123,6 +163,18 @@ switch (mutation) {
|
||||
case "nginx-no-sse":
|
||||
changed = original.replace(" proxy_buffering off;", " proxy_buffering on;");
|
||||
break;
|
||||
case "nginx-no-issuer-clear":
|
||||
changed = original.replaceAll('proxy_set_header X-Thoth-Principal-Issuer "";', 'proxy_set_header X-Thoth-Principal-Issuer $http_x_thoth_principal_issuer;');
|
||||
break;
|
||||
case "nginx-no-subject-capture":
|
||||
changed = original.replace("auth_request_set $thoth_principal_subject", "# missing auth capture $thoth_principal_subject");
|
||||
break;
|
||||
case "nginx-no-display-map":
|
||||
changed = original.replace("proxy_set_header X-Thoth-Trusted-Principal-Display-Name $thoth_principal_display_name;", "proxy_set_header X-Thoth-Trusted-Principal-Display-Name \"\";");
|
||||
break;
|
||||
case "nginx-no-admin-map":
|
||||
changed = original.replace("proxy_set_header X-Thoth-Trusted-Is-Admin $thoth_is_admin;", "proxy_set_header X-Thoth-Trusted-Is-Admin \"\";");
|
||||
break;
|
||||
case "caddy-no-auth":
|
||||
changed = original.replace("forward_auth auth-gateway:4180 {", "# forward authentication omitted");
|
||||
break;
|
||||
@@ -132,6 +184,18 @@ switch (mutation) {
|
||||
case "caddy-core-upstream":
|
||||
changed = original.replaceAll("127.0.0.1:8080", "127.0.0.1:8787");
|
||||
break;
|
||||
case "caddy-no-issuer-public-clear":
|
||||
changed = original.replace("request_header -X-Thoth-Principal-Issuer", "request_header X-Thoth-Principal-Issuer {header.X-Thoth-Principal-Issuer}");
|
||||
break;
|
||||
case "caddy-no-subject-trusted-clear":
|
||||
changed = original.replace("request_header -X-Thoth-Trusted-Principal-Subject", "request_header X-Thoth-Trusted-Principal-Subject {header.X-Thoth-Trusted-Principal-Subject}");
|
||||
break;
|
||||
case "caddy-no-display-map":
|
||||
changed = original.replace("X-Thoth-Principal-Display-Name>X-Thoth-Trusted-Principal-Display-Name", "X-Thoth-Principal-Display-Name");
|
||||
break;
|
||||
case "caddy-no-admin-map":
|
||||
changed = original.replace("X-Thoth-Is-Admin>X-Thoth-Trusted-Is-Admin", "X-Thoth-Is-Admin");
|
||||
break;
|
||||
case "dirty-source":
|
||||
changed = original.replaceAll("git status --porcelain --untracked-files=all", "git status --short");
|
||||
break;
|
||||
@@ -215,6 +279,22 @@ expect_guide_rejected \
|
||||
"server application coupling" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-coupling \
|
||||
"server installation guide introduces forbidden application coupling"
|
||||
expect_guide_rejected \
|
||||
"server host-gateway loopback listener" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-host-loopback \
|
||||
"server host-gateway guidance assumes a host loopback listener"
|
||||
expect_guide_rejected \
|
||||
"server raw container removal" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-raw-remove \
|
||||
"server uninstall bypasses installation-aware removal"
|
||||
expect_guide_rejected \
|
||||
"server pinned migrator differs from core" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-pinned-migrator-mismatch \
|
||||
"server pinned migration image must equal the pinned core image"
|
||||
expect_guide_rejected \
|
||||
"server pinned frontend is missing" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-pinned-frontend-missing \
|
||||
"server pinned image override must pin core, session-migrate, and frontend without builds"
|
||||
expect_guide_rejected \
|
||||
"Nginx identity without authentication" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-auth \
|
||||
@@ -227,6 +307,22 @@ expect_guide_rejected \
|
||||
"Nginx buffered SSE" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-sse \
|
||||
"Nginx proxy lacks structural token: proxy_buffering off;"
|
||||
expect_guide_rejected \
|
||||
"Nginx issuer inbound claim not cleared" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-issuer-clear \
|
||||
"Nginx proxy does not clear inbound issuer identity"
|
||||
expect_guide_rejected \
|
||||
"Nginx subject auth response not captured" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-subject-capture \
|
||||
"Nginx proxy does not capture authenticated subject identity"
|
||||
expect_guide_rejected \
|
||||
"Nginx display identity not mapped to private hop" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-display-map \
|
||||
"Nginx proxy does not map authenticated display identity"
|
||||
expect_guide_rejected \
|
||||
"Nginx admin identity not mapped to private hop" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-admin-map \
|
||||
"Nginx proxy does not map authenticated admin identity"
|
||||
expect_guide_rejected \
|
||||
"Caddy identity without authentication" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-no-auth \
|
||||
@@ -234,11 +330,27 @@ expect_guide_rejected \
|
||||
expect_guide_rejected \
|
||||
"Caddy untrusted identity forwarding" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-client-identity \
|
||||
"Caddy proxy lacks structural token: X-Thoth-Principal-Subject>X-Thoth-Trusted-Principal-Subject"
|
||||
"Caddy proxy does not map authenticated subject identity"
|
||||
expect_guide_rejected \
|
||||
"Caddy direct core exposure" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-core-upstream \
|
||||
"Caddy proxy must forward only to frontend on 127.0.0.1:8080"
|
||||
expect_guide_rejected \
|
||||
"Caddy issuer inbound claim not cleared" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-no-issuer-public-clear \
|
||||
"Caddy proxy does not clear inbound issuer identity"
|
||||
expect_guide_rejected \
|
||||
"Caddy subject private-hop claim not cleared" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-no-subject-trusted-clear \
|
||||
"Caddy proxy does not clear inbound trusted subject identity"
|
||||
expect_guide_rejected \
|
||||
"Caddy display identity not mapped to private hop" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-no-display-map \
|
||||
"Caddy proxy does not map authenticated display identity"
|
||||
expect_guide_rejected \
|
||||
"Caddy admin identity not mapped to private hop" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-no-admin-map \
|
||||
"Caddy proxy does not map authenticated admin identity"
|
||||
|
||||
expect_guide_rejected \
|
||||
"dirty or untracked source tree" verify_local_guide \
|
||||
|
||||
Reference in New Issue
Block a user