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
2 changes: 1 addition & 1 deletion build/dependencies.lock
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ manifest = "build/legacy-manifest.json"
schema = 1
component_count = 332
file_count = 2131
byte_count = 314669717
byte_count = 314676226
source_build_components = 228
unresolved_components = 104
inherited_baseline = "07505ea58c7bba698d6b9220ff43946a43cac76b"
Expand Down
16 changes: 8 additions & 8 deletions build/legacy-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -605,8 +605,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/bin/bloom-network",
"file_count": 1,
"byte_count": 8583,
"tree_sha256": "ee0dd293f4c6e56efd7c853203db60209d116b8f8858a51aaa0734019f11662b",
"byte_count": 9428,
"tree_sha256": "6b0235ded2cd16f8134dc85b4825066213d31259c41e142b1380f0158a1f4917",
"source": "https://github.com/boburning/BloomOS",
"source_revision": "release-commit",
"license": "GPL-3.0-only",
Expand All @@ -631,8 +631,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/bin/bloom-network-transaction",
"file_count": 1,
"byte_count": 27658,
"tree_sha256": "96398c18ceb12113691600ebdf18de86ff8a1dc96022ecaa9d0111f851495efe",
"byte_count": 33007,
"tree_sha256": "cbe6b067187a9d20d9cb62efe389323933c7f6111002af706c5252fd1bc25260",
"source": "https://github.com/boburning/BloomOS",
"source_revision": "release-commit",
"license": "GPL-3.0-only",
Expand Down Expand Up @@ -982,8 +982,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/bin/bloom-wifi",
"file_count": 1,
"byte_count": 9401,
"tree_sha256": "d7dd29d8ae55b7d5f2e8b2febf1bfc318dd60f389e7bab0fe59da12e14f3d7ab",
"byte_count": 9695,
"tree_sha256": "a9dcd950bf0cd94da139656db9ff29db4ab40889a64cd6d5309308e3abc67ea6",
"source": "https://github.com/boburning/BloomOS",
"source_revision": "release-commit",
"license": "GPL-3.0-only",
Expand Down Expand Up @@ -1021,8 +1021,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/bin/bloomctl",
"file_count": 1,
"byte_count": 35351,
"tree_sha256": "db5fa1c268ed71f098c626f80d29edb2f21896469262a7c2acfaeb49e48dad02",
"byte_count": 35372,
"tree_sha256": "653222365d8f06ca4bae9a750525e04649991943afab1701eb6a0f6919a6578d",
"source": "https://github.com/boburning/BloomOS",
"source_revision": "release-commit",
"license": "GPL-3.0-only",
Expand Down
2 changes: 1 addition & 1 deletion docs/1.0_TEST_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ observable properties and never substitutes for physical UX review.
| Performance | Input/render timings, 30-minute shell soak, 500 open/back cycles |
| Privacy | Allowlisted health/support export contains no private data |
| Developer deployment | Dual-marker/update/session preflight; deterministic allowlisted manifest; exact byte/hash/mode transfer; sealed slots; atomic activation; readiness auto-rollback; active/previous overlay; bounded cleanup; ordinary network-helper activation denied |
| Remote network transaction | Separate local marker; known-good station/key/update/session preflight; private prior state; nonce digest; monotonic detached watchdog; one bounded mutation; unqualified remote Wi-Fi disable rejected before state or radio mutation; legacy Wi-Fi-disable recovery; apply-failure, explicit, timeout, and boot-interruption restoration; safe empty stale-lock recovery; transaction-bound network/boot-runtime overlay; already-restored overlay closes without preference replay; privacy-bounded health; fresh-connection confirmation; sole-route disable confirmation denied |
| Remote network transaction | Separate local marker; known-good station/key/update/session preflight; exact mode-0600 station snapshot in a mode-0700 JFFS2-private root with only its digest in public metadata; nonce digest; monotonic detached watchdog; one bounded mutation; guarded profile projection and explicit station restart; association/global-IPv4 deadline; corrupt-snapshot denial; apply-failure, explicit, timeout, and boot-interruption exact restoration; unqualified remote Wi-Fi disable rejected before state or radio mutation; legacy Wi-Fi-disable recovery; safe empty stale-lock recovery; transaction-bound network/boot-runtime overlay; already-restored overlay closes without preference replay; privacy-bounded health; fresh-connection confirmation; sole-route disable confirmation denied |

## Task-based UX certification

Expand Down
13 changes: 13 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,19 @@ and classify only explicit open, WPA2-PSK, or unsupported security. A caller
can cancel active work and explicitly discard any terminal result. The scanner
does not change a profile, preference, association, DHCP client, or listener.

Profile association reuses the one guarded network-transaction authority rather
than adding a second recovery mechanism. `begin` copies the exact current
supplicant file into a mode-0700 JFFS2-private transaction root, records only
its SHA-256 in public transaction metadata, and arms the existing durable
watchdog before `wifi-profile-connect ID` may project a stored profile. The
canonical `bloom-network` owner then requests an explicit `bloom-wifi` station
restart and waits only until the monotonic transaction deadline for association
and a global IPv4 address. Apply failure, explicit rollback, timeout, and boot
recovery verify the private snapshot, atomically restore it, restart the station
lifecycle, and recheck services and listeners. Confirmation still requires a
fresh host-key-verified SSH connection; neither status nor evidence exposes a
profile, SSID, credential, address, nonce, or snapshot content.

Listener reconciliation is event-driven at existing fixed boundaries: boot,
Wi-Fi reconciliation, Wi-Fi preference changes, remote-key publication, and
each listener preference request. A request publishes its desired boolean and
Expand Down
19 changes: 19 additions & 0 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,25 @@ timeout, backend failure, oversized output, duplicate SSIDs, security
classification, unsafe paths, stale/live locks, rate limiting, and bounded
history. This slice performs no connect or forget transition.

The first connect transition is deliberately routed through the existing
network transaction and its independent-confirmation workflow:

```sh
tools/bloom-device network-begin bloom-plus 120
tools/bloom-device network-apply bloom-plus NONCE wifi-profile-connect PROFILE_ID
tools/bloom-device network-confirm bloom-plus NONCE
```

`PROFILE_ID` is a bounded non-secret handle; profile data remains in the
private store. Begin must preserve the exact current supplicant bytes in the
private JFFS2 transaction root before apply. A dropped apply connection is not
success: wait for a fresh independent connection and confirm only after
association, global IPv4, key-only SSH, listener audit, and aggregate health
all pass. Otherwise let the watchdog restore the exact prior configuration or
invoke `network-rollback` from an independently safe path. Never exercise this
transition over the only unattended device route until its exact candidate has
passed the host fault matrix and a local synthetic device fixture.

An activated update is not considered successful merely because the installer
or MainUI started. The runtime records each unconfirmed boot in durable
`.bloom/update` state. After device checks pass, developers can promote the
Expand Down
9 changes: 9 additions & 0 deletions docs/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ and the expected active overlay. The host never confirms persistent Wi-Fi or
SSH disable operations over their sole route. Public status and evidence omit
addresses, SSIDs, profiles, public-key material, and nonce material.

Wi-Fi profile rollback material is credential-bearing and therefore never
resides beside public SD-card transaction metadata. The guarded transaction
stores only a SHA-256 there and keeps the exact mode-0600 snapshot beneath the
mode-0700 JFFS2 private network root. Restore rejects links, changed snapshots,
unsafe parents, occupied candidates, and hash mismatches before replacing the
live supplicant file. Profile IDs are non-secret handles, but status, health,
logs, screenshots, PR evidence, and remote diagnostics still omit profile
contents, SSIDs, credentials, addresses, nonces, and snapshot bytes.

Updates and packages must be staged and verified with at least SHA-256; release signing is preferred. Downloaded code must never be executed through a `curl | sh` pattern. Logs and support bundles must redact credentials, tokens, and private keys.

The removable SD card is VFAT and cannot enforce Unix secret permissions.
Expand Down
9 changes: 6 additions & 3 deletions docs/program/BloomOS_Work_Program_v3.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,18 +833,21 @@
],
"github_prs": [
487,
488
488,
489
],
"risk_tier": 2,
"deployment_tier": "warm",
"device_gate_required": true,
"last_audited_main": "105f744d2fc88d0cacf023ecb62e800572dd0933",
"last_audited_main": "5f155d6d16fd927d775f18219353c76ae641d750",
"evidence": [
"issue #486 tracks NET-04 after NET-03 merged as fca10bb0168d8bc38737881745b68cd3bab9da59; no prior NET-04 issue or implementation PR exists and current main has no bounded scan/connect/forget orchestration",
"draft PR #487 is the first host-safe NET-04 slice and extends the private NET-03 authority with stdin-only atomic single-profile upsert, requested/document ID binding, inactive-profile deletion, a non-secret projected-profile marker, and fail-closed refusal to replace or forget the active profile; 16/16 focused tests passed in 4.8 seconds with exact 314651736-byte dependency preflight, and the slice does not scan, associate, restart Wi-Fi, change preferences, or complete NET-04",
"exact head b6e96eebd08df0eb8b75867b8e341f3e7a76a830 passed risk-scoped shell workflow 33171784731 with 1m29s test execution; its exact 14104-byte helper with SHA-256 5fd88c120a0a4a979a890865a5ac06e7dbeb7e50ffcd99ce08cfa389e637ecc7 was transferred through strict key-only SSH and exercised only under /tmp/bloom-net04a-fixture-b6e96eeb with synthetic profiles, where active deletion failed closed, inactive deletion succeeded, root/store/config modes were 0700/0600/0600, live supplicant SHA-256 d7fbadd510e76c423638513337620e17944d51b4505ff314354971d97114bdef remained unchanged, temporary state was removed, and aggregate device health remained green; PR #487 merged as 105f744d2fc88d0cacf023ecb62e800572dd0933",
"draft PR #488 adds a fixed-interface asynchronous scan worker with immediate high-entropy operation IDs, redacted status, explicit local-only results, cancellation, terminal discard, one active worker, bounded rate/runtime/raw output/results/history, open/WPA2-PSK/unsupported classification, and bloomctl delegation; 9/9 affected tests passed in 13.8 seconds and 13/13 focused manifest/provenance tests passed in 271 seconds with exact 314669717-byte dependency preflight, and the slice does not connect, forget, change a preference, restart Wi-Fi, modify DHCP, or complete NET-04",
"exact head b5de4b1ae7f7d558886a8c55047b3a7ada141621 passed risk-scoped shell workflow 33173965383 with 1m39s test execution; its exact 17244-byte helper with SHA-256 0d3b3e1ac893fb787fcd7c3d28b2c526175475d360bab83836d9072efab695b3 and a 156-byte synthetic platform fixture were transferred through strict key-only SSH and exercised only under /tmp with /bin/echo replacing iw, transitioned RUNNING to SUCCEEDED with zero results, enforced 0700/0700/0600/0600 root-operation-state-result modes, discarded the terminal operation, removed every task file, retained live supplicant SHA-256 d7fbadd510e76c423638513337620e17944d51b4505ff314354971d97114bdef, and left aggregate device health green without a real scan or network mutation"
"exact head b5de4b1ae7f7d558886a8c55047b3a7ada141621 passed risk-scoped shell workflow 33173965383 with 1m39s test execution; its exact 17244-byte helper with SHA-256 0d3b3e1ac893fb787fcd7c3d28b2c526175475d360bab83836d9072efab695b3 and a 156-byte synthetic platform fixture were transferred through strict key-only SSH and exercised only under /tmp with /bin/echo replacing iw, transitioned RUNNING to SUCCEEDED with zero results, enforced 0700/0700/0600/0600 root-operation-state-result modes, discarded the terminal operation, removed every task file, retained live supplicant SHA-256 d7fbadd510e76c423638513337620e17944d51b4505ff314354971d97114bdef, and left aggregate device health green without a real scan or network mutation",
"PR #489 adds a rollback-bounded wifi-profile-connect transaction that preserves the exact prior supplicant bytes in a mode-0600 snapshot below a mode-0700 JFFS2-private root, places only its SHA-256 in public transaction metadata, routes station replacement through the canonical network and Wi-Fi owners, and restores the exact prior configuration after apply failure, explicit rollback, timeout, or interrupted boot; 88/88 direct affected tests and 140/140 exhaustive focused tests passed with exact 314676226-byte inventory preflight",
"exact candidate ff5b0775 was 33007 bytes with SHA-256 d3bed4f13e6e3b84344ba9c370f6a258b09d5e23a96378068a64eff30b2ab68e and passed an isolated Mini Plus /tmp fixture using synthetic station content and mocked dependencies: apply changed only the fixture, rollback restored the exact prior hash, private root/snapshot modes were 0700/0600, no public secret copy existed, all task files were removed, and the live device remained associated and healthy without a real scan, profile transition, Wi-Fi toggle, DHCP mutation, listener mutation, update, or reboot"
]
},
{
Expand Down
16 changes: 16 additions & 0 deletions static/build/.tmp_update/bin/bloom-network
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ preference_result() {
"$1" "$2" "$3" "$4"
}

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

wifi_capability() {
[ -x "$PLATFORM" ] || return 1
wifi=$($PLATFORM capability-status network.wifi_station 2>/dev/null) || return 1
Expand Down Expand Up @@ -200,9 +204,21 @@ set_preference() {
preference_result "$operation" true true applied
}

reconnect() {
wifi=$(wifi_capability) || { reconnect_result false platform_unavailable; return 1; }
[ "$wifi" = true ] || { reconnect_result false no_network_hardware; return 1; }
[ -x "$BACKEND" ] || { reconnect_result false backend_unavailable; return 1; }
preference=$(wifi_preference) || { reconnect_result false wifi_state_unavailable; return 1; }
[ "$preference" = 1 ] || { reconnect_result false wifi_disabled; return 1; }
"$BACKEND" restart >/dev/null 2>&1 || { reconnect_result false backend_failed; return 1; }
reconcile_services || { reconnect_result false remote_services_failed; return 1; }
reconnect_result true applied
}

case "$#:${1:-}:${2:-}" in
1:status:) status ;;
2:request:reconcile) reconcile ;;
2:request:reconnect) reconnect ;;
2:request:enable) set_preference enable ;;
2:request:disable) set_preference disable ;;
*) result false false false false invalid_arguments; exit 2 ;;
Expand Down
Loading