feat: Linux/cloud platform stack (TLS, registry, static/cross, selfhost PM)
ci / build (ubuntu) (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled

Ship the QUALITY_PLAN platform focus: thin/minimal runtime, --static/--target,
Nexus HTTPS/mTLS with graceful stop, lock checksums + install --locked,
selfhost registry (search/add/HTTP), containers, and CI smokes for cloud path.
This commit is contained in:
2026-07-23 23:00:55 +03:00
parent a939f74b1b
commit a785747c37
44 changed files with 4318 additions and 279 deletions
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Build examples/http_health.bux → build/http_health for container packaging.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
OUT_DIR="${1:-$ROOT/build}"
mkdir -p "$OUT_DIR"
if [[ ! -x "$ROOT/buxc" ]]; then
(cd "$ROOT" && make build)
fi
PKG=$(mktemp -d)
trap 'rm -rf "$PKG"' EXIT
mkdir -p "$PKG/src"
cp -a "$ROOT/rt" "$PKG/"
cat > "$PKG/bux.toml" <<'EOF'
[Package]
Name = "http_health"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
EOF
cp "$ROOT/examples/http_health.bux" "$PKG/src/Main.bux"
"$ROOT/buxc" --quiet --release build "$PKG"
cp "$PKG/build/http_health" "$OUT_DIR/http_health"
file "$OUT_DIR/http_health"
echo "wrote $OUT_DIR/http_health"
echo "docker: docker build -f examples/docker/Dockerfile.health -t bux-health $ROOT"
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Build a fully-static hello binary for container / distroless demos (session 75).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
OUT_DIR="${1:-$ROOT/build}"
mkdir -p "$OUT_DIR"
if [[ ! -x "$ROOT/buxc" ]]; then
(cd "$ROOT" && make build)
fi
PKG=$(mktemp -d)
trap 'rm -rf "$PKG"' EXIT
mkdir -p "$PKG/src"
cp -a "$ROOT/rt" "$PKG/"
cat > "$PKG/bux.toml" <<'EOF'
[Package]
Name = "hello_static"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
EOF
cp "$ROOT/examples/hello.bux" "$PKG/src/Main.bux"
"$ROOT/buxc" --quiet --static --release build "$PKG"
cp "$PKG/build/hello_static" "$OUT_DIR/hello_static"
file "$OUT_DIR/hello_static"
echo "wrote $OUT_DIR/hello_static"
echo "docker: docker build -f examples/docker/Dockerfile.static --build-arg BIN=$OUT_DIR/hello_static -t bux-hello-static $ROOT"
+31 -1
View File
@@ -150,6 +150,36 @@ if ! sed -n '/^Array_int TakeViaPtr/,/^}/p' "$TMP/mptr/build/main.c" | grep -q '
fi
echo " move_field_ptr: PASS (run + no Bag_Drop + Tracked_Drop remaining)"
# --- cross-function pointer ownership TakeItems(&bag) ---
echo "=== smoke: move_cross_fn ==="
mkdir -p "$TMP/mcf/src"
cp -a "$ROOT/rt" "$TMP/mcf/"
cat > "$TMP/mcf/bux.toml" <<'EOF'
[Package]
Name = "move_cross_fn"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
EOF
cp "$ROOT/examples/move_cross_fn.bux" "$TMP/mcf/src/Main.bux"
out=$(cd "$TMP/mcf" && "$BUXC" run .)
echo "$out" | grep -q 'cross_fn_drops=2'
echo "$out" | grep -q 'PASS'
# CallTakeItems must Tracked_Drop remaining tag, not Bag_Drop (would free moved items)
if sed -n '/^int CallTakeItems/,/^}/p' "$TMP/mcf/build/main.c" | grep -q 'Bag_Drop'; then
echo "error: CallTakeItems still Bag_Drops after TakeItems(&bag)" >&2
sed -n '/^int CallTakeItems/,/^}/p' "$TMP/mcf/build/main.c"
exit 1
fi
if ! sed -n '/^int CallTakeItems/,/^}/p' "$TMP/mcf/build/main.c" | grep -q 'Tracked_Drop'; then
echo "error: CallTakeItems missing Tracked_Drop for remaining tag" >&2
sed -n '/^int CallTakeItems/,/^}/p' "$TMP/mcf/build/main.c"
exit 1
fi
echo " move_cross_fn: PASS (run + no Bag_Drop + Tracked_Drop remaining)"
# --- early return Drop counts ---
echo "=== smoke: drop_early_return ==="
mkdir -p "$TMP/de/src"
@@ -168,4 +198,4 @@ out=$(cd "$TMP/de" && "$BUXC" run .)
echo "$out" | grep -q 'PASS'
echo " drop_early_return: PASS"
echo "PASS: smoke_drop_move (field-move + partial + remaining + nested + ptr + early-return)"
echo "PASS: smoke_drop_move (field-move + partial + remaining + nested + ptr + cross-fn + early-return)"
+117
View File
@@ -0,0 +1,117 @@
#!/usr/bin/env bash
# Session 75 — Linux / cloud / embedded smoke:
# 1) BUX_RUNTIME=minimal (thin runtime, run hello)
# 2) --static --release (fully-static binary, file(1) check)
# 3) --target aarch64-linux-gnu (cross build if toolchain present)
# 4) CTFE CRC example under minimal runtime
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
unset BUX_DEBUG_FILE || true
unset BUX_RUNTIME || true
unset BUX_STATIC || true
unset BUX_CC || true
if [[ -x "$ROOT/buxc" ]]; then
BUXC="$ROOT/buxc"
else
(cd "$ROOT" && make build)
BUXC="$ROOT/buxc"
fi
mkpkg() {
local name="$1" src="$2"
local d
d=$(mktemp -d)
mkdir -p "$d/src"
cp -a "$ROOT/rt" "$d/"
cat > "$d/bux.toml" <<EOF
[Package]
Name = "$name"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
EOF
cp "$src" "$d/src/Main.bux"
echo "$d"
}
pass=0
fail=0
note() { echo "=== $* ==="; }
# ── 1) minimal runtime ──────────────────────────────────────────────────
note "minimal runtime (BUX_RUNTIME=minimal)"
PKG=$(mkpkg hello_min "$ROOT/examples/hello.bux")
trap 'rm -rf "$PKG" "${PKG2:-}" "${PKG3:-}" "${PKG4:-}"' EXIT
export BUX_RUNTIME=minimal
out=$("$BUXC" --quiet run "$PKG" 2>&1) || { echo "$out" >&2; exit 1; }
echo "$out" | grep -q 'Hello, Bux!'
grep -q 'minimal / embedded / static' "$PKG/build/runtime.c"
# must not pull full POSIX
if grep -q 'openssl/evp\|pthread.h' "$PKG/build/runtime.c"; then
echo "error: minimal runtime still has pthread/openssl includes" >&2
exit 1
fi
echo "PASS: minimal runtime"
pass=$((pass+1))
unset BUX_RUNTIME
# ── 2) fully-static (thin runtime implied) ──────────────────────────────
note "static link (--static --release)"
PKG2=$(mkpkg hello_static "$ROOT/examples/hello.bux")
out=$("$BUXC" --quiet --static --release build "$PKG2" 2>&1) || { echo "$out" >&2; exit 1; }
BIN="$PKG2/build/hello_static"
[[ -x "$BIN" ]] || BIN="$PKG2/build/hello_static.exe"
file_out=$(file "$BIN")
echo "$file_out"
echo "$file_out" | grep -qi 'statically linked\|static-pie\|static '
# run only if host arch matches
if echo "$file_out" | grep -qi 'x86-64\|x86_64\|Intel 80386'; then
run_out=$("$BIN" 2>&1) || { echo "$run_out" >&2; exit 1; }
echo "$run_out" | grep -q 'Hello, Bux!'
fi
grep -q 'minimal / embedded / static' "$PKG2/build/runtime.c"
echo "PASS: static link"
pass=$((pass+1))
# ── 3) cross aarch64 (optional toolchain) ───────────────────────────────
note "cross aarch64-linux-gnu"
PKG3=$(mkpkg hello_arm "$ROOT/examples/hello.bux")
if command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then
out=$("$BUXC" --quiet --static --release --target aarch64-linux-gnu build "$PKG3" 2>&1) || {
echo "$out" >&2
exit 1
}
BIN3="$PKG3/build/hello_arm"
[[ -x "$BIN3" ]] || BIN3="$PKG3/build/hello_arm.exe"
file_out=$(file "$BIN3")
echo "$file_out"
echo "$file_out" | grep -qi 'ARM aarch64\|aarch64'
echo "$file_out" | grep -qi 'statically linked\|static-pie\|static '
echo "PASS: cross aarch64"
pass=$((pass+1))
else
echo "SKIP: aarch64-linux-gnu-gcc not on PATH"
fi
# ── 4) CTFE CRC under minimal runtime ───────────────────────────────────
note "ctfe_crc (minimal)"
if [[ -f "$ROOT/examples/ctfe_crc.bux" ]]; then
PKG4=$(mkpkg ctfe_crc "$ROOT/examples/ctfe_crc.bux")
export BUX_RUNTIME=minimal
out=$("$BUXC" --quiet run "$PKG4" 2>&1) || { echo "$out" >&2; exit 1; }
echo "$out"
echo "$out" | grep -q 'PASS ctfe_crc'
echo "PASS: ctfe_crc"
pass=$((pass+1))
unset BUX_RUNTIME
else
echo "SKIP: examples/ctfe_crc.bux missing"
fi
echo ""
echo "smoke_linux_targets: $pass checks passed"
echo "PASS: smoke_linux_targets"
+86
View File
@@ -0,0 +1,86 @@
#!/usr/bin/env bash
# Session 79 — musl fully-static path (skips if no musl-gcc / zig musl target).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
if [[ ! -x "$ROOT/buxc" ]]; then
(cd "$ROOT" && make build)
fi
pick_cc() {
if command -v musl-gcc >/dev/null 2>&1; then
echo "musl-gcc"
return
fi
if command -v x86_64-linux-musl-gcc >/dev/null 2>&1; then
echo "x86_64-linux-musl-gcc"
return
fi
if command -v zig >/dev/null 2>&1; then
# zig cc -target x86_64-linux-musl acts as a C compiler when BUX_CC is a wrapper
echo "zig-musl"
return
fi
echo ""
}
CC_KIND=$(pick_cc)
if [[ -z "$CC_KIND" ]]; then
echo "SKIP: no musl-gcc / zig on PATH (install musl-tools or zig for Alpine static)"
echo "PASS: smoke_musl_static (skipped)"
exit 0
fi
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
mkdir -p "$TMP/src"
cp -a "$ROOT/rt" "$TMP/"
cp "$ROOT/examples/hello.bux" "$TMP/src/Main.bux"
cat > "$TMP/bux.toml" <<'EOF'
[Package]
Name = "hello_musl"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
EOF
export BUX_RUNTIME=minimal
if [[ "$CC_KIND" == "zig-musl" ]]; then
# Wrapper so buxc invokes zig as cc
cat > "$TMP/zigcc" <<'EOF'
#!/bin/sh
exec zig cc -target x86_64-linux-musl "$@"
EOF
chmod +x "$TMP/zigcc"
export BUX_CC="$TMP/zigcc"
else
export BUX_CC="$CC_KIND"
fi
echo "=== musl static hello (BUX_CC=$BUX_CC) ==="
"$ROOT/buxc" --quiet --static --release build "$TMP"
BIN="$TMP/build/hello_musl"
file "$BIN"
# musl static often reports "statically linked"
if file "$BIN" | grep -qi 'statically linked\|static-pie\|static '; then
echo "static: ok"
else
# some musl toolchains still produce dynamic musl — accept if ldd mentions musl
if command -v ldd >/dev/null 2>&1 && ldd "$BIN" 2>&1 | grep -qi musl; then
echo "dynamic musl: ok"
else
echo "WARN: could not confirm musl/static; file output above"
fi
fi
# Run only if host can execute
if "$BIN" 2>/dev/null | grep -q 'Hello, Bux!'; then
echo "run: ok"
else
echo "run: skipped or failed (cross?)"
fi
echo "PASS: smoke_musl_static"
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Session 80 — Nexus mTLS: reject no-client-cert; accept with client cert.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
PORT="${NEXUS_PORT:-18444}"
BIND="${NEXUS_BIND:-127.0.0.1}"
if [[ ! -x "$ROOT/apps/nexus/build/nexus" ]]; then
(cd "$ROOT/apps/nexus" && "$ROOT/buxc" --release build)
fi
NEXUS="$ROOT/apps/nexus/build/nexus"
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"; kill $NPID 2>/dev/null || true' EXIT
# CA + server + client certs
openssl req -x509 -newkey rsa:2048 -nodes -keyout "$TMP/ca.key" -out "$TMP/ca.pem" \
-days 1 -subj "/CN=TestCA" 2>/dev/null
openssl req -newkey rsa:2048 -nodes -keyout "$TMP/server.key" -out "$TMP/server.csr" \
-subj "/CN=localhost" 2>/dev/null
openssl x509 -req -in "$TMP/server.csr" -CA "$TMP/ca.pem" -CAkey "$TMP/ca.key" \
-CAcreateserial -out "$TMP/server.pem" -days 1 2>/dev/null
openssl req -newkey rsa:2048 -nodes -keyout "$TMP/client.key" -out "$TMP/client.csr" \
-subj "/CN=client" 2>/dev/null
openssl x509 -req -in "$TMP/client.csr" -CA "$TMP/ca.pem" -CAkey "$TMP/ca.key" \
-CAcreateserial -out "$TMP/client.pem" -days 1 2>/dev/null
NEXUS_PORT="$PORT" NEXUS_BIND="$BIND" NEXUS_WORKERS=2 NEXUS_ACCESS_LOG=0 \
NEXUS_TLS=1 NEXUS_TLS_CERT="$TMP/server.pem" NEXUS_TLS_KEY="$TMP/server.key" \
NEXUS_TLS_CLIENT_CA="$TMP/ca.pem" \
"$NEXUS" >"$TMP/nexus.log" 2>&1 &
NPID=$!
sleep 0.7
if ! kill -0 "$NPID" 2>/dev/null; then
echo "error: nexus failed" >&2
cat "$TMP/nexus.log" >&2
exit 1
fi
# Without client cert → fail
if curl -sk --max-time 3 "https://${BIND}:${PORT}/api/health" -o /dev/null 2>/dev/null; then
# some curl versions might still get empty; check exit code
:
fi
set +e
curl -sk --max-time 3 "https://${BIND}:${PORT}/api/health" >/dev/null 2>&1
noclient=$?
set -e
if [[ $noclient -eq 0 ]]; then
# Try again more strictly — handshake should fail
if curl -sk --max-time 3 "https://${BIND}:${PORT}/api/health" 2>&1 | grep -q status; then
echo "error: mTLS allowed request without client cert" >&2
cat "$TMP/nexus.log" >&2
exit 1
fi
fi
echo "no-client: rejected (curl exit $noclient)"
# With client cert → ok
body=$(curl -sk --max-time 5 \
--cert "$TMP/client.pem" --key "$TMP/client.key" \
--cacert "$TMP/ca.pem" \
"https://${BIND}:${PORT}/api/health")
echo "$body"
echo "$body" | grep -q '"status":"ok"'
echo "$body" | grep -q '0.6.0'
kill -TERM "$NPID" 2>/dev/null || true
sleep 0.6
kill -0 "$NPID" 2>/dev/null && kill -9 "$NPID" 2>/dev/null || true
grep -q 'mTLS' "$TMP/nexus.log" || grep -q 'client certificates' "$TMP/nexus.log"
echo "PASS: smoke_nexus_mtls"
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# Session 78 — Nexus HTTPS smoke (self-signed cert + curl -k).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
PORT="${NEXUS_PORT:-18443}"
BIND="${NEXUS_BIND:-127.0.0.1}"
if [[ ! -x "$ROOT/apps/nexus/build/nexus" ]]; then
(cd "$ROOT/apps/nexus" && "$ROOT/buxc" --release build)
fi
NEXUS="$ROOT/apps/nexus/build/nexus"
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"; kill $NPID 2>/dev/null || true' EXIT
# Self-signed cert (10y, CN=localhost)
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout "$TMP/key.pem" -out "$TMP/cert.pem" \
-days 3650 -subj "/CN=localhost" 2>/dev/null
NEXUS_PORT="$PORT" NEXUS_BIND="$BIND" NEXUS_WORKERS=2 NEXUS_ACCESS_LOG=1 \
NEXUS_TLS=1 NEXUS_TLS_CERT="$TMP/cert.pem" NEXUS_TLS_KEY="$TMP/key.pem" \
"$NEXUS" >"$TMP/nexus.log" 2>&1 &
NPID=$!
sleep 0.6
if ! kill -0 "$NPID" 2>/dev/null; then
echo "error: nexus failed to start" >&2
cat "$TMP/nexus.log" >&2
exit 1
fi
body=$(curl -sk --max-time 5 "https://${BIND}:${PORT}/api/health")
echo "$body"
echo "$body" | grep -q '"status":"ok"'
echo "$body" | grep -q '0.6.0'
info=$(curl -sk --max-time 5 "https://${BIND}:${PORT}/api/info")
echo "$info" | grep -q 'TLS'
kill -TERM "$NPID" 2>/dev/null || true
sleep 0.8
if kill -0 "$NPID" 2>/dev/null; then
kill -9 "$NPID" 2>/dev/null || true
echo "WARN: forced kill after SIGTERM"
else
echo "PASS: SIGTERM exit"
fi
grep -q 'Listening on https://' "$TMP/nexus.log" || {
echo "error: expected https banner" >&2
cat "$TMP/nexus.log" >&2
exit 1
}
grep -q 'GET /api/health' "$TMP/nexus.log" || true
echo "PASS: smoke_nexus_tls"
+93 -10
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env bash
# Smoke: registry search + add + install + build with greet package (E.1)
# Also verifies HTTP-fetchable registry index (E.1b).
# Smoke: registry search + add + install + lock reproducibility + HTTPS (E.1 / session 79)
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
BUXC="$ROOT/buxc"
@@ -12,11 +11,16 @@ fi
TMP=$(mktemp -d)
HTTP_PID=""
HTTPS_PID=""
cleanup() {
if [[ -n "$HTTP_PID" ]]; then
kill "$HTTP_PID" 2>/dev/null || true
wait "$HTTP_PID" 2>/dev/null || true
fi
if [[ -n "$HTTPS_PID" ]]; then
kill "$HTTPS_PID" 2>/dev/null || true
wait "$HTTPS_PID" 2>/dev/null || true
fi
rm -rf "$TMP"
}
trap cleanup EXIT
@@ -60,20 +64,67 @@ echo "=== bux add greet ==="
grep -q greet bux.toml
cat bux.toml
echo "=== bux install ==="
echo "=== bux install (with checksum) ==="
"$BUXC" install
test -f bux.lock
grep -q greet bux.lock
grep -q Checksum bux.lock
cat bux.lock
cp bux.lock "$TMP/lock1"
echo "=== lock reproducibility (second install) ==="
"$BUXC" install
# Source path + version + checksum must match
diff -u "$TMP/lock1" bux.lock
echo "=== bux install --locked ==="
"$BUXC" install --locked
echo "=== install --locked fails without lock ==="
rm -f bux.lock
if "$BUXC" install --locked 2>"$TMP/locked_err"; then
echo "error: expected --locked to fail without lock" >&2
exit 1
fi
grep -qi 'missing\|locked' "$TMP/locked_err"
"$BUXC" install
test -f bux.lock
echo "=== checksum mismatch detected ==="
# Corrupt checksum
python3 - <<'PY'
from pathlib import Path
p = Path("bux.lock")
t = p.read_text()
# flip last hex nibble of Checksum line if present
lines = []
for line in t.splitlines():
if line.startswith("Checksum"):
# Checksum = "abcdef..."
import re
m = re.search(r'"([0-9a-fA-F]+)"', line)
if m:
h = m.group(1)
h2 = h[:-1] + ("0" if h[-1] != "0" else "1")
line = f'Checksum = "{h2}"'
lines.append(line)
p.write_text("\n".join(lines) + "\n")
PY
if "$BUXC" install --locked 2>"$TMP/csum_err"; then
echo "error: expected checksum mismatch failure" >&2
exit 1
fi
grep -qi 'checksum' "$TMP/csum_err"
# restore good lock
"$BUXC" install >/dev/null
echo "=== bux run ==="
"$BUXC" run . | tee "$TMP/run.out"
grep -q "Hello, Bux!" "$TMP/run.out"
# --- HTTP registry index ---
echo "=== HTTP registry index (E.1b) ==="
echo "=== HTTP registry index ==="
mkdir -p "$TMP/http"
# Absolute file: path so resolution works after download to ~/.bux/cache
cat > "$TMP/http/registry.toml" <<EOF
[[package]]
name = "greet"
@@ -82,14 +133,12 @@ source = "file:$ROOT/registry/packages/greet"
description = "HTTP-served greet package"
EOF
# Free port via python
PORT=$(python3 -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1",0)); print(s.getsockname()[1]); s.close()')
(
cd "$TMP/http"
python3 -m http.server "$PORT" --bind 127.0.0.1 >/dev/null 2>&1
) &
HTTP_PID=$!
# Wait until server responds
for _ in 1 2 3 4 5 6 7 8 9 10; do
if curl -fsS "http://127.0.0.1:${PORT}/registry.toml" >/dev/null 2>&1; then
break
@@ -101,9 +150,43 @@ export BUX_REGISTRY="http://127.0.0.1:${PORT}/registry.toml"
export BUX_REGISTRY_REFRESH=1
"$BUXC" search greet | tee "$TMP/http_search.out"
grep -q greet "$TMP/http_search.out"
grep -q "http://127.0.0.1" "$TMP/http_search.out" || grep -q "cached" "$TMP/http_search.out"
unset BUX_REGISTRY_REFRESH
# Second search should hit cache without refresh
"$BUXC" search greet | grep -q greet
echo "PASS: registry smoke (local + HTTP search + add + install + build)"
# --- HTTPS registry (self-signed) ---
echo "=== HTTPS registry index (self-signed + BUX_REGISTRY_INSECURE) ==="
mkdir -p "$TMP/https"
cp "$TMP/http/registry.toml" "$TMP/https/registry.toml"
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout "$TMP/https/key.pem" -out "$TMP/https/cert.pem" \
-days 1 -subj "/CN=localhost" 2>/dev/null
SPORT=$(python3 -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1",0)); print(s.getsockname()[1]); s.close()')
python3 - <<PY &
import http.server, ssl, os
os.chdir("$TMP/https")
httpd = http.server.HTTPServer(("127.0.0.1", $SPORT), http.server.SimpleHTTPRequestHandler)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("$TMP/https/cert.pem", "$TMP/https/key.pem")
httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()
PY
HTTPS_PID=$!
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
if curl -kfsS "https://127.0.0.1:${SPORT}/registry.toml" >/dev/null 2>&1; then
break
fi
sleep 0.15
done
export BUX_REGISTRY="https://127.0.0.1:${SPORT}/registry.toml"
export BUX_REGISTRY_REFRESH=1
export BUX_REGISTRY_INSECURE=1
"$BUXC" search greet | tee "$TMP/https_search.out"
grep -q greet "$TMP/https_search.out"
grep -q "https://" "$TMP/https_search.out" || grep -q "cached" "$TMP/https_search.out"
unset BUX_REGISTRY_INSECURE
unset BUX_REGISTRY_REFRESH
unset BUX_REGISTRY
echo "PASS: registry smoke (local + lock/checksum + locked + HTTP + HTTPS)"
+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env bash
# Session 80 — selfhost buxc2 install + --locked checksum parity
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
if [[ ! -x "$ROOT/build/selfhost/build/buxc2" ]]; then
(cd "$ROOT" && make selfhost)
fi
BUXC2="$ROOT/build/selfhost/build/buxc2"
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
mkdir -p "$TMP/app/src" "$TMP/libpkg/src"
# mini lib package
cat > "$TMP/libpkg/bux.toml" <<'EOF'
[Package]
Name = "mini"
Version = "1.2.3"
Type = "lib"
EOF
cat > "$TMP/libpkg/src/Lib.bux" <<'EOF'
func Mini_Version() -> String { return "1.2.3"; }
EOF
cat > "$TMP/app/bux.toml" <<EOF
[Package]
Name = "app"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
[Dependencies]
mini = { Path = "$TMP/libpkg" }
EOF
cat > "$TMP/app/src/Main.bux" <<'EOF'
func Main() -> int { return 0; }
EOF
cd "$TMP/app"
echo "=== buxc2 install ==="
"$BUXC2" install .
test -f bux.lock
grep -q mini bux.lock
grep -q Checksum bux.lock
cat bux.lock
cp bux.lock "$TMP/lock1"
echo "=== install reproducible ==="
"$BUXC2" install .
diff -u "$TMP/lock1" bux.lock
echo "=== install --locked ==="
"$BUXC2" install --locked .
echo "=== --locked fails without lock ==="
rm bux.lock
if "$BUXC2" install --locked . >"$TMP/err" 2>&1; then
echo "error: expected failure" >&2
cat "$TMP/err" >&2
exit 1
fi
grep -qi 'missing\|locked' "$TMP/err"
"$BUXC2" install . >/dev/null
echo "=== checksum mismatch ==="
python3 - <<'PY'
from pathlib import Path
import re
p = Path("bux.lock")
t = p.read_text()
lines = []
for line in t.splitlines():
if line.startswith("Checksum"):
m = re.search(r'"([0-9a-fA-F]+)"', line)
if m:
h = m.group(1)
h2 = h[:-1] + ("0" if h[-1] != "0" else "1")
line = f'Checksum = "{h2}"'
lines.append(line)
p.write_text("\n".join(lines) + "\n")
PY
if "$BUXC2" install --locked . >"$TMP/err2" 2>&1; then
echo "error: expected checksum fail" >&2
cat "$TMP/err2" >&2
exit 1
fi
grep -qi checksum "$TMP/err2"
echo "PASS: smoke_selfhost_install"
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env bash
# Session 81 — selfhost registry: search / add by name / install / HTTP index
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
export BUX_STDLIB="${BUX_STDLIB:-$ROOT/lib}"
export BUX_REGISTRY="$ROOT/config/registry.toml"
if [[ ! -x "$ROOT/build/selfhost/build/buxc2" ]]; then
(cd "$ROOT" && make selfhost)
fi
BUXC2="$ROOT/build/selfhost/build/buxc2"
TMP=$(mktemp -d)
HTTP_PID=""
cleanup() {
[[ -n "$HTTP_PID" ]] && kill "$HTTP_PID" 2>/dev/null || true
rm -rf "$TMP"
}
trap cleanup EXIT
echo "=== buxc2 search greet (local) ==="
"$BUXC2" search greet | tee "$TMP/s.out"
grep -q greet "$TMP/s.out"
echo "=== consumer + add greet (registry) ==="
mkdir -p "$TMP/app/src"
cat > "$TMP/app/bux.toml" <<'EOF'
[Package]
Name = "reg_consumer"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
EOF
cat > "$TMP/app/src/Main.bux" <<'EOF'
import Std::Io::{PrintLine};
import Std::String::{String_Eq};
import Std::Test::{Test_AssertTrue, Test_Pass};
func Main() -> int {
let msg: String = Greet_Hello("Bux");
Test_AssertTrue(String_Eq(msg, "Hello, Bux!"));
PrintLine(msg);
Test_Pass("reg_consumer");
return 0;
}
EOF
cd "$TMP/app"
"$BUXC2" add greet | tee "$TMP/add.out"
grep -q greet bux.toml
"$BUXC2" install .
test -f bux.lock
grep -q Checksum bux.lock
"$BUXC2" install --locked .
echo "=== buxc2 run with registry dep ==="
"$BUXC2" run . | tee "$TMP/run.out"
grep -q "Hello, Bux!" "$TMP/run.out"
echo "=== HTTP registry search ==="
mkdir -p "$TMP/http"
cat > "$TMP/http/registry.toml" <<EOF
[[package]]
name = "greet"
version = "0.1.1"
source = "file:$ROOT/registry/packages/greet"
description = "HTTP-served greet (selfhost)"
EOF
PORT=$(python3 -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1",0)); print(s.getsockname()[1]); s.close()')
python3 -m http.server "$PORT" --bind 127.0.0.1 -d "$TMP/http" >/dev/null 2>&1 &
HTTP_PID=$!
for _ in 1 2 3 4 5 6 7 8 9 10; do
curl -fsS "http://127.0.0.1:${PORT}/registry.toml" >/dev/null 2>&1 && break
sleep 0.1
done
export BUX_REGISTRY="http://127.0.0.1:${PORT}/registry.toml"
export BUX_REGISTRY_REFRESH=1
"$BUXC2" search greet | tee "$TMP/http.out"
grep -q greet "$TMP/http.out"
grep -q "http://" "$TMP/http.out" || grep -q cached "$TMP/http.out"
echo "PASS: smoke_selfhost_registry"