Skip to content

Commit 709fd27

Browse files
committed
lab: remove privileged repository staging fallback
1 parent 73926b6 commit 709fd27

1 file changed

Lines changed: 23 additions & 61 deletions

File tree

scripts/resolve_native_repository.sh

Lines changed: 23 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,24 @@
11
#!/usr/bin/env bash
2-
# Source this file from a native client suite after WORKSPACE, NIAKVIO,
3-
# TARGET_MANIFEST, SOURCE_SHA and SOURCE_REPOSITORY are defined.
2+
# Source from a native client suite after WORKSPACE, NIAKVIO, TARGET_MANIFEST,
3+
# SOURCE_SHA and SOURCE_REPOSITORY are defined.
4+
#
5+
# Human-UX invariant: repository staging may make the NiakVIO candidate reachable,
6+
# but it must never grant the Nuvio process privileges or network capabilities that
7+
# a normal user process does not have. No sudo/root, proxy, DNS, TLS or OS-policy
8+
# bypass belongs here. If ordinary process access cannot reach the staged candidate,
9+
# the evidence is infrastructure-invalid and the suite must fail closed.
410

511
NIAKVIO_RESOLVED_MANIFEST_URL=""
612
NIAKVIO_RESOLVED_ALLOW_LOCAL="0"
713
NIAKVIO_LOCAL_REPOSITORY_PID=""
814
NIAKVIO_LOCAL_REPOSITORY_LOG=""
915
NIAKVIO_LOCAL_REPOSITORY_ROOT=""
1016
NIAKVIO_LOCAL_REPOSITORY_KEY=""
11-
NIAKVIO_LOCAL_REPOSITORY_PRIVILEGED_CLIENT="0"
1217

1318
probe_native_repository_loopback() {
1419
local port="${1:?port required}"
1520
local candidate_dir="${2:?candidate dir required}"
16-
local use_privileged_client="${3:-0}"
17-
local python_args=(python3 - "$port" "$candidate_dir")
18-
19-
if [[ "$use_privileged_client" == "1" ]]; then
20-
sudo -n "${python_args[@]}" <<'PY'
21-
import http.client
22-
import sys
23-
24-
port = int(sys.argv[1])
25-
candidate = sys.argv[2]
26-
connection = http.client.HTTPConnection("127.0.0.1", port, timeout=1.0)
27-
try:
28-
connection.request("GET", f"/{candidate}/manifest.json", headers={"Connection": "close"})
29-
response = connection.getresponse()
30-
if response.status != 200:
31-
raise SystemExit(1)
32-
response.read(64)
33-
finally:
34-
connection.close()
35-
PY
36-
else
37-
"${python_args[@]}" <<'PY'
21+
python3 - "$port" "$candidate_dir" <<'PY'
3822
import http.client
3923
import sys
4024
@@ -50,7 +34,6 @@ try:
5034
finally:
5135
connection.close()
5236
PY
53-
fi
5437
}
5538

5639
resolve_native_repository() {
@@ -61,14 +44,12 @@ resolve_native_repository() {
6144
if [[ -n "${NIAKVIO_MANIFEST_URL:-}" ]]; then
6245
NIAKVIO_RESOLVED_MANIFEST_URL="$NIAKVIO_MANIFEST_URL"
6346
NIAKVIO_RESOLVED_ALLOW_LOCAL="${NIAKVIO_ALLOW_LOCAL_MANIFEST:-0}"
64-
echo "FIELD_NATIVE_REPOSITORY_SOURCE client=$client mode=explicit local=$NIAKVIO_RESOLVED_ALLOW_LOCAL"
47+
echo "FIELD_NATIVE_REPOSITORY_SOURCE client=$client mode=explicit local=$NIAKVIO_RESOLVED_ALLOW_LOCAL observational=true"
6548
return 0
6649
fi
6750

68-
# raw.githubusercontent.com resolves repository-relative provider filenames only
69-
# when the manifest itself is at the repository root. It must also be a tracked,
70-
# unchanged file from the exact SOURCE_SHA under test. The SHA in the URL makes
71-
# Nuvio's persistent repository/provider cache safe across CI runs.
51+
# Prefer the exact SHA-pinned public repository whenever the selected manifest is
52+
# a tracked unchanged root file. This is closest to what a real Nuvio user loads.
7253
local pinned=false
7354
if [[ "$TARGET_MANIFEST" != */* ]] \
7455
&& git -C "$NIAKVIO" ls-files --error-unmatch "$TARGET_MANIFEST" >/dev/null 2>&1 \
@@ -80,19 +61,13 @@ resolve_native_repository() {
8061
if [[ "$pinned" == true ]]; then
8162
NIAKVIO_RESOLVED_MANIFEST_URL="https://raw.githubusercontent.com/${SOURCE_REPOSITORY}/${SOURCE_SHA}/${TARGET_MANIFEST}"
8263
NIAKVIO_RESOLVED_ALLOW_LOCAL="0"
83-
echo "FIELD_NATIVE_REPOSITORY_SOURCE client=$client mode=pinned_github local=0 cache_key=${SOURCE_SHA}"
64+
echo "FIELD_NATIVE_REPOSITORY_SOURCE client=$client mode=pinned_github local=0 cache_key=${SOURCE_SHA} observational=true"
8465
return 0
8566
fi
8667

87-
# Generated, modified, or nested manifests are materialized as a root repository
88-
# and served only on the runner bridge. Android emulators must reach the host at
89-
# 10.0.2.2, so they bind all interfaces. Desktop only consumes 127.0.0.1 and is
90-
# deliberately bound to loopback; this avoids macOS Local Network Privacy treating
91-
# an otherwise local-only CI repository as a LAN listener.
92-
#
93-
# IMPORTANT: the URL path is content-addressed from manifest + every provider
94-
# byte. A persisted AVD/profile may therefore reuse the cache for the exact same
95-
# candidate, but can never silently reuse old JS after the candidate changes.
68+
# Generated/modified manifests must still resolve repository-relative provider
69+
# filenames. Materialize manifest + every provider into a content-addressed local
70+
# repository so persistent Nuvio caches cannot reuse stale JS.
9671
local serve_root="${WORKSPACE}/native-candidate-repository-${client}"
9772
local prepared_root="${serve_root}.prepared"
9873
local server_log="${WORKSPACE}/native-candidate-repository-${client}.server.log"
@@ -104,7 +79,9 @@ resolve_native_repository() {
10479
local content_key
10580
content_key="$(python3 - "$prepared_root" <<'PY'
10681
from pathlib import Path
107-
import hashlib, sys
82+
import hashlib
83+
import sys
84+
10885
root = Path(sys.argv[1]).resolve()
10986
h = hashlib.sha256()
11087
files = sorted((p for p in root.rglob('*') if p.is_file()), key=lambda p: p.relative_to(root).as_posix())
@@ -142,16 +119,6 @@ PY
142119
NIAKVIO_LOCAL_REPOSITORY_PID=$!
143120
NIAKVIO_LOCAL_REPOSITORY_LOG="$server_log"
144121

145-
# Readiness always starts through the same unprivileged loopback path the client
146-
# should use. On macOS CI only, sudo is a bounded fallback after several ordinary
147-
# attempts; it is never required just because the runner happens to be macOS.
148-
local allow_privileged_probe=0
149-
if [[ "$client" == "desktop" && "$(uname -s)" == "Darwin" && "${CI:-}" == "true" ]]; then
150-
if sudo -n true >/dev/null 2>&1; then
151-
allow_privileged_probe=1
152-
fi
153-
fi
154-
155122
local ready=0
156123
local attempt
157124
for attempt in $(seq 1 40); do
@@ -162,29 +129,24 @@ PY
162129
NIAKVIO_LOCAL_REPOSITORY_PID=""
163130
return 2
164131
fi
165-
if probe_native_repository_loopback "$port" "$candidate_dir" 0 >/dev/null 2>&1; then
166-
ready=1
167-
break
168-
fi
169-
if [[ "$allow_privileged_probe" == "1" && "$attempt" -ge 5 ]] \
170-
&& probe_native_repository_loopback "$port" "$candidate_dir" 1 >/dev/null 2>&1; then
132+
if probe_native_repository_loopback "$port" "$candidate_dir" >/dev/null 2>&1; then
171133
ready=1
172-
NIAKVIO_LOCAL_REPOSITORY_PRIVILEGED_CLIENT="1"
173134
break
174135
fi
175136
sleep 0.2
176137
done
177138
if [[ "$ready" != "1" ]]; then
178-
echo "FIELD_NATIVE_REPOSITORY_SOURCE_ERROR client=$client reason=local_server_not_ready cache_key=$content_key bind_host=$bind_host privileged_fallback=$allow_privileged_probe" >&2
139+
echo "FIELD_NATIVE_REPOSITORY_SOURCE_ERROR client=$client reason=local_server_not_ready_unprivileged cache_key=$content_key bind_host=$bind_host" >&2
179140
cat "$server_log" >&2 2>/dev/null || true
180141
kill "$NIAKVIO_LOCAL_REPOSITORY_PID" 2>/dev/null || true
181142
rm -rf "$serve_root"
143+
NIAKVIO_LOCAL_REPOSITORY_PID=""
182144
return 2
183145
fi
184146

185147
NIAKVIO_RESOLVED_MANIFEST_URL="http://${device_host}:${port}/${candidate_dir}/manifest.json"
186148
NIAKVIO_RESOLVED_ALLOW_LOCAL="1"
187-
echo "FIELD_NATIVE_REPOSITORY_SOURCE client=$client mode=local_candidate local=1 port=$port bind_host=$bind_host cache_key=$content_key privileged_client=$NIAKVIO_LOCAL_REPOSITORY_PRIVILEGED_CLIENT"
149+
echo "FIELD_NATIVE_REPOSITORY_SOURCE client=$client mode=local_candidate local=1 port=$port bind_host=$bind_host cache_key=$content_key observational=true privileged=false"
188150
}
189151

190152
cleanup_native_repository() {

0 commit comments

Comments
 (0)