Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions build/dependencies.lock
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,10 @@ legacy_channels = ["development"]
[legacy_inventory]
manifest = "build/legacy-manifest.json"
schema = 1
component_count = 333
file_count = 2132
byte_count = 314698725
source_build_components = 229
component_count = 334
file_count = 2133
byte_count = 314701761
source_build_components = 230
unresolved_components = 104
inherited_baseline = "07505ea58c7bba698d6b9220ff43946a43cac76b"

Expand Down
25 changes: 19 additions & 6 deletions build/legacy-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/bin/bloom-dev-deploy",
"file_count": 1,
"byte_count": 32728,
"tree_sha256": "fc439fab7129c7c67ad7c4a3cc7e910f27bebc08097ffe0eb7f33c4b9d7ec0bd",
"byte_count": 32818,
"tree_sha256": "d07c796d29881fc16ce3674d028d3232fe1079288d71c0311acbcdc45c9511ea",
"source": "https://github.com/boburning/BloomOS",
"source_revision": "release-commit",
"license": "GPL-3.0-only",
Expand Down Expand Up @@ -652,6 +652,19 @@
"build_recipe": "Makefile",
"resolution": "source-build"
},
{
"id": "runtime-tmp-update-bin-bloom-network-update",
"kind": "runtime",
"path": "static/build/.tmp_update/bin/bloom-network-update",
"file_count": 1,
"byte_count": 2972,
"tree_sha256": "fbf5422ec5b391a7abd2ebd0fcd728d590f0bf87d5bd221028f6ec415919a50b",
"source": "https://github.com/boburning/BloomOS",
"source_revision": "release-commit",
"license": "GPL-3.0-only",
"build_recipe": "Makefile",
"resolution": "source-build"
},
{
"id": "runtime-tmp-update-bin-bloom-platform",
"kind": "runtime",
Expand Down Expand Up @@ -995,8 +1008,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/bin/bloom-wifi",
"file_count": 1,
"byte_count": 10293,
"tree_sha256": "11378a22655246e12060c3c87ce2c7a7ef0ee105dddd8a1c70d52dabf46e4adc",
"byte_count": 10455,
"tree_sha256": "06534f60dada7c8ccbbdd86e54b99c69a57408c85e01a114f928a779aa3d3d38",
"source": "https://github.com/boburning/BloomOS",
"source_revision": "release-commit",
"license": "GPL-3.0-only",
Expand Down Expand Up @@ -2347,8 +2360,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/script/network",
"file_count": 7,
"byte_count": 29493,
"tree_sha256": "54b4e17fdb22cc5d42d61c3d7020ebdee1278788f52e1ae43be3f20143ddc429",
"byte_count": 29305,
"tree_sha256": "f74d0227f1280c03cdfe56cad3be8c87ddb61fd9591bcdd7fba33e0542665140",
"source": "https://github.com/OnionUI/Onion",
"source_revision": "07505ea58c7bba698d6b9220ff43946a43cac76b",
"license": "GPL-3.0-only",
Expand Down
11 changes: 10 additions & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,16 @@ local, future-deadline, leased, completed, failed, and cancelled work is not
claimed or run by this boundary. Invalid event or scheduler output, a busy or
failed database, and acknowledgement failure leave the generation pending for
a later idempotent reconciliation. Delivery remains secondary to Wi-Fi health.
Update and sync consumption remain separate follow-up integration steps.
`bloom-network-update` is the second fixed consumer. It validates and
acknowledges only its exact update generation, but does not perform network I/O:
BloomOS has no configured public release provider, and the inherited Onion OTA
checker is not a trusted Bloom update path. Associated events therefore receive
the explicit `provider_unconfigured` disposition and offline events receive the
explicit `offline` disposition. The compatibility network script no longer
launches the inherited TLS-bypassing check or publishes its legacy availability
marker. Acknowledgement failure leaves the event pending, and consumer failure
remains secondary to Wi-Fi health. Sync consumption remains a separate follow-up
integration step.

Bounded `request enable` and `request disable` operations persist only
`device.wifi_enabled` through the active `bloom-settings` authority before
Expand Down
2 changes: 2 additions & 0 deletions static/build/.tmp_update/bin/bloom-dev-deploy
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ allowed_path() {
launch-session:script/bloom-launch-trace.sh) return 0 ;;
network-helpers:bin/bloom-settings|network-helpers:bin/bloom-network|\
network-helpers:bin/bloom-network-metadata|\
network-helpers:bin/bloom-network-update|\
network-helpers:bin/bloom-network-services|network-helpers:bin/bloom-network-transaction|\
network-helpers:bin/bloom-platform|network-helpers:bin/bloom-dev-ssh|\
network-helpers:bin/bloom-sftp-gate|network-helpers:bin/bloom-sftp-server|\
Expand Down Expand Up @@ -193,6 +194,7 @@ validate_manifest() {
bin/bloom-settings \
bin/bloom-network \
bin/bloom-network-metadata \
bin/bloom-network-update \
bin/bloom-network-services \
bin/bloom-network-transaction \
bin/bloom-platform \
Expand Down
82 changes: 82 additions & 0 deletions static/build/.tmp_update/bin/bloom-network-update
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/sh

set -u

SYSTEM_ROOT=${BLOOM_NETWORK_UPDATE_SYSTEM_ROOT:-/mnt/SDCARD/.tmp_update}
NETWORK=${BLOOM_NETWORK_UPDATE_NETWORK_BIN:-$SYSTEM_ROOT/bin/bloom-network}
JQ=${BLOOM_NETWORK_UPDATE_JQ_BIN:-$SYSTEM_ROOT/bin/jq}

result() {
printf '{"schema":1,"service":"bloom-network-update","applied":%s,"state":"%s"}\n' \
"$1" "$2"
}

reconcile() {
[ -x "$NETWORK" ] && [ -x "$JQ" ] || {
result false dependency_unavailable
return 1
}
event=$($NETWORK events status update 2>/dev/null) || {
result false event_unavailable
return 1
}
fields=$(printf '%s\n' "$event" | "$JQ" -er '
if .schema == 1 and .service == "bloom-network-events" and
.operation == "status" and .client == "update" and
(.connectivity == "unknown" or .connectivity == "associated" or
.connectivity == "offline") and
(.generation | type) == "number" and .generation >= 0 and
.generation <= 2147483647 and (.generation | floor) == .generation and
(.pending | type) == "boolean"
then "\(.connectivity) \(.generation) \(.pending)"
else error("invalid update network event") end
' 2>/dev/null) || {
result false event_invalid
return 1
}
set -- $fields
[ "$#" -eq 3 ] || { result false event_invalid; return 1; }
connectivity=$1
generation=$2
pending=$3
if [ "$pending" = false ]; then
result false no_pending_event
return 0
fi
case "$connectivity:$generation" in
associated:[1-9]*|offline:[1-9]*) ;;
*) result false event_invalid; return 1 ;;
esac

# BloomOS has no configured public release provider. Consuming this event is
# an explicit disposition, not permission to invoke the inherited Onion OTA
# checker, bypass TLS verification, download an archive, or stage an update.
case "$connectivity" in
associated) disposition=provider_unconfigured ;;
offline) disposition=offline ;;
esac

acknowledgement=$($NETWORK events ack update "$generation" 2>/dev/null) || {
result false acknowledgement_failed
return 1
}
printf '%s\n' "$acknowledgement" | "$JQ" -e \
--argjson generation "$generation" --arg connectivity "$connectivity" '
.schema == 1 and .service == "bloom-network-events" and
.operation == "ack" and .client == "update" and
.connectivity == $connectivity and .generation == $generation and
.pending == false
' >/dev/null 2>&1 || {
result false acknowledgement_invalid
return 1
}
printf '{"schema":1,"service":"bloom-network-update","applied":true,'
printf '"state":"acknowledged","connectivity":"%s","generation":%s,' \
"$connectivity" "$generation"
printf '"disposition":"%s"}\n' "$disposition"
}

case "$#:${1:-}" in
1:reconcile) reconcile ;;
*) result false invalid_arguments; exit 2 ;;
esac
2 changes: 2 additions & 0 deletions static/build/.tmp_update/bin/bloom-wifi
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ START_SLEEP=${BLOOM_WIFI_START_SLEEP_BIN:-sleep}
SERVICES=${BLOOM_WIFI_SERVICES_BIN:-/mnt/SDCARD/.tmp_update/bin/bloom-network-services}
NETWORK=${BLOOM_WIFI_NETWORK_BIN:-/mnt/SDCARD/.tmp_update/bin/bloom-network}
METADATA=${BLOOM_WIFI_METADATA_EVENT_BIN:-/mnt/SDCARD/.tmp_update/bin/bloom-network-metadata}
UPDATE=${BLOOM_WIFI_UPDATE_EVENT_BIN:-/mnt/SDCARD/.tmp_update/bin/bloom-network-update}
NOHUP=${BLOOM_WIFI_NOHUP_BIN:-/usr/bin/nohup}
SELF=${BLOOM_WIFI_SELF:-/mnt/SDCARD/.tmp_update/bin/bloom-wifi}
INTERFACE=${BLOOM_WIFI_INTERFACE:-wlan0}
Expand Down Expand Up @@ -58,6 +59,7 @@ notify_connectivity() {
[ -x "$NETWORK" ] || return 0
if "$NETWORK" events publish "$1" >/dev/null 2>&1; then
[ ! -x "$METADATA" ] || "$METADATA" reconcile >/dev/null 2>&1 || true
[ ! -x "$UPDATE" ] || "$UPDATE" reconcile >/dev/null 2>&1 || true
fi
return 0
}
Expand Down
15 changes: 4 additions & 11 deletions static/build/.tmp_update/script/network/update_networking.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,12 @@ check_services() {
$timebin network-opportunity >/dev/null 2>&1 &
fi

if [ -f "$sysdir/.updateAvailable" ] && [ $is_booting -eq 1 ]; then
bootScreen Boot "Update available!"
sleep 1
elif [ "$has_wifi" -eq 1 ] && [ ! -f /tmp/update_checked ]; then
touch /tmp/update_checked
$sysdir/script/ota_update.sh check &
fi

}

# Bloom retains this compatibility script only for station bring-up, time, OTA,
# and delegation to the reviewed key-only SSH/SFTP owner. Inherited listener
# flags are never authoritative and cannot activate a service.
# Bloom retains this compatibility script only for station bring-up, time, and
# delegation to the reviewed key-only SSH/SFTP owner. Update opportunities are
# consumed through bloom-network-update; this path never invokes inherited OTA.
# Inherited listener flags are never authoritative and cannot activate a service.
stop_busybox_telnet() {
for process_dir in "$procroot"/[0-9]*; do
[ -d "$process_dir" ] && [ ! -L "$process_dir" ] &&
Expand Down
1 change: 1 addition & 0 deletions test/shell/dev_deploy.bats
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ stage_network_bundle() {
bin/bloom-settings \
bin/bloom-network \
bin/bloom-network-metadata \
bin/bloom-network-update \
bin/bloom-network-services \
bin/bloom-network-transaction \
bin/bloom-platform \
Expand Down
4 changes: 2 additions & 2 deletions test/shell/legacy_manifest.bats
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
--manifest /workspace/build/legacy-manifest.json

[ "$status" -eq 0 ]
[[ "$output" == "legacy manifest validate: 333 components" ]]
[[ "$output" == "legacy manifest validate: 334 components" ]]
[ ! -e "/workspace/static/packages/RApp/SNK - Neo Geo (GnGeo)" ]
[ ! -e "/workspace/static/packages/RApp/PICO-8 (PICO-8 standalone)" ]
[ ! -e "/workspace/static/packages/RApp/SCUMM (ScummVM standalone)" ]
Expand Down Expand Up @@ -104,7 +104,7 @@ import sys
components = json.load(open(sys.argv[1], encoding="utf-8"))["components"]
runtime = [item for item in components if item["id"].startswith("runtime-")]
bloom = [item for item in runtime if item["source"] == "https://github.com/boburning/BloomOS"]
assert len(bloom) == 56
assert len(bloom) == 57
assert all(item["resolution"] == "source-build" for item in bloom)
assert all(item["source_revision"] == "release-commit" for item in bloom)
PY
Expand Down
103 changes: 103 additions & 0 deletions test/shell/network_update.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env bats

setup() {
export SERVICE=/workspace/static/build/.tmp_update/bin/bloom-network-update
export BLOOM_NETWORK_UPDATE_NETWORK_BIN="$BATS_TEST_TMPDIR/bloom-network"
export BLOOM_NETWORK_UPDATE_JQ_BIN=/usr/bin/jq
export EVENT_STATUS="$BATS_TEST_TMPDIR/event-status.json"
export ACK_STATUS="$BATS_TEST_TMPDIR/ack-status.json"
export CLIENT_LOG="$BATS_TEST_TMPDIR/client.log"
cat >"$BLOOM_NETWORK_UPDATE_NETWORK_BIN" <<'SH'
#!/bin/sh
printf '%s\n' "$*" >>"$CLIENT_LOG"
case "$*" in
'events status update') cat "$EVENT_STATUS" ;;
'events ack update '*)
[ ! -e "$ACK_STATUS.exit" ] || exit "$(cat "$ACK_STATUS.exit")"
cat "$ACK_STATUS"
;;
*) exit 2 ;;
esac
SH
chmod +x "$BLOOM_NETWORK_UPDATE_NETWORK_BIN"
}

write_event() {
connectivity=$1
generation=$2
pending=$3
printf '{"schema":1,"service":"bloom-network-events","operation":"status","client":"update","connectivity":"%s","generation":%s,"changed":false,"pending":%s}\n' \
"$connectivity" "$generation" "$pending" >"$EVENT_STATUS"
}

write_ack() {
connectivity=$1
generation=$2
printf '{"schema":1,"service":"bloom-network-events","operation":"ack","client":"update","connectivity":"%s","generation":%s,"changed":false,"pending":false}\n' \
"$connectivity" "$generation" >"$ACK_STATUS"
}

@test "update consumer treats an absent pending generation as a no-op" {
write_event unknown 0 false
run "$SERVICE" reconcile
[ "$status" -eq 0 ]
[ "$output" = '{"schema":1,"service":"bloom-network-update","applied":false,"state":"no_pending_event"}' ]
[ "$(cat "$CLIENT_LOG")" = 'events status update' ]
}

@test "associated update event receives an explicit unconfigured-provider disposition" {
write_event associated 7 true
write_ack associated 7
run "$SERVICE" reconcile
[ "$status" -eq 0 ]
[[ "$output" == *'"state":"acknowledged","connectivity":"associated","generation":7,"disposition":"provider_unconfigured"'* ]]
[ "$(sed -n '1p' "$CLIENT_LOG")" = 'events status update' ]
[ "$(sed -n '2p' "$CLIENT_LOG")" = 'events ack update 7' ]
[ "$(wc -l <"$CLIENT_LOG" | tr -d ' ')" -eq 2 ]
}

@test "offline update event receives an explicit offline disposition" {
write_event offline 8 true
write_ack offline 8
run "$SERVICE" reconcile
[ "$status" -eq 0 ]
[[ "$output" == *'"connectivity":"offline","generation":8,"disposition":"offline"'* ]]
[ "$(sed -n '2p' "$CLIENT_LOG")" = 'events ack update 8' ]
}

@test "update consumer rejects malformed event authority output" {
printf '%s\n' '{"schema":1,"client":"update","connectivity":"associated","generation":1,"pending":true}' >"$EVENT_STATUS"
run "$SERVICE" reconcile
[ "$status" -eq 1 ]
[[ "$output" == *'"state":"event_invalid"'* ]]
[ "$(wc -l <"$CLIENT_LOG" | tr -d ' ')" -eq 1 ]
}

@test "acknowledgement failure remains retryable" {
write_event associated 9 true
write_ack associated 9
printf 1 >"$ACK_STATUS.exit"
run "$SERVICE" reconcile
[ "$status" -eq 1 ]
[[ "$output" == *'"state":"acknowledgement_failed"'* ]]
[ "$(sed -n '2p' "$CLIENT_LOG")" = 'events ack update 9' ]
}

@test "update consumer rejects mismatched acknowledgement output" {
write_event associated 10 true
write_ack offline 10
run "$SERVICE" reconcile
[ "$status" -eq 1 ]
[[ "$output" == *'"state":"acknowledgement_invalid"'* ]]
}

@test "automatic update opportunity contains no inherited downloader or TLS bypass" {
compatibility=/workspace/static/build/.tmp_update/script/network/update_networking.sh
! grep -F 'ota_update.sh check' "$compatibility"
! grep -F '/tmp/update_checked' "$compatibility"
! grep -F '.updateAvailable' "$compatibility"
! grep -E 'curl|wget|--no-check-certificate|-k([[:space:]]|$)' "$SERVICE"
run "$SERVICE" arbitrary
[ "$status" -eq 2 ]
[[ "$output" == *'"state":"invalid_arguments"'* ]]
}
3 changes: 2 additions & 1 deletion test/shell/transfer_policy.bats
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ teardown() {
bin/bloom-settings \
bin/bloom-network \
bin/bloom-network-metadata \
bin/bloom-network-update \
bin/bloom-network-services \
bin/bloom-network-transaction \
bin/bloom-platform \
Expand Down Expand Up @@ -130,7 +131,7 @@ teardown() {
run python3 /workspace/tools/dev-deploy-manifest.py network-helpers "$payload" \
net02-fixture 0123456789abcdef0123456789abcdef01234567 "$manifest"
[ "$status" -eq 0 ] || printf '%s\n' "$output" >&3
[ "$(jq '.files | length' "$manifest")" -eq 18 ]
[ "$(jq '.files | length' "$manifest")" -eq 19 ]

rm "$payload/bin/bloom-platform"
run python3 /workspace/tools/dev-deploy-manifest.py network-helpers "$payload" \
Expand Down
Loading
Loading