Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(native): seed global Wi-Fi preset list on every flash + template

Picks up Codex's media-layout.sh helpers (write_global_wifi_creds,
merge_wifi_creds, summarize_wifi_creds_file) and finishes the wiring
in ac-os so every flashed USB and every template OTA image ships with
the lab/home network presets ready out of the box.

Changes:

1. ac-os flash_usb()
- Always writes the global preset list to a fresh wifi_creds.json
- If the existing USB still has a saved wifi_creds.json from a
previous flash, merge_wifi_creds folds the user's saved networks
on TOP of the presets so personal entries are never clobbered
- Result: a re-flash never wipes saved networks, but a virgin USB
gets the presets immediately
- Logs the final wifi cred count via summarize_wifi_creds_file

2. ac-os generate_template_image()
- Writes the global preset list into the staging tree before
ac_media_create_efi_disk_image runs, so OTA download images land
on a freshly-flashed USB with presets already in /mnt/wifi_creds.json
- The downstream image creator already picks up stage_root/wifi_creds.json

3. flash-helper-runner.sh
- sfdisk now uses --no-reread (Codex), avoids EBUSY when /dev/sda
is mid-flash and the kernel is still reading the partition table

The preset list lives in media-layout.sh:
aesthetic.computer / aesthetic.computer
ATT2AWTpcr / t84q%7%g2h8u
GettyLink / (open)
Tondo_Guest / California

These are the same SSIDs notepat.mjs auto-tries via AC_SSID, so the
JS-side fallback logic is already in place — this commit makes the
script side match the JS side so the preset is on disk for first boot.

bash -n syntax-checked: ac-os, media-layout.sh, flash-helper-runner.sh.

+139 -5
+22 -4
fedac/native/ac-os
··· 1011 1011 } 1012 1012 1013 1013 write_usb_config_file "${CONFIG_FILE}" 1014 - preserve_existing_usb_wifi_creds "${USB_DEV}" "${WIFI_CREDS_FILE}" || true 1014 + 1015 + # Always seed the global preset Wi-Fi list (kept in sync with the JS 1016 + # auto-connect entries in notepat.mjs / wifi.mjs / prompt.mjs). If the 1017 + # USB still has a valid wifi_creds.json from a previous flash, merge 1018 + # the user's saved networks on top of the presets so personal entries 1019 + # never get clobbered by a re-flash. 1020 + local GLOBAL_WIFI_FILE="${MEDIA_TMP}/global-wifi-creds.json" 1021 + local PRESERVED_WIFI_FILE="${MEDIA_TMP}/preserved-wifi-creds.json" 1022 + ac_media_write_global_wifi_creds "${GLOBAL_WIFI_FILE}" 1023 + if preserve_existing_usb_wifi_creds "${USB_DEV}" "${PRESERVED_WIFI_FILE}"; then 1024 + ac_media_merge_wifi_creds "${WIFI_CREDS_FILE}" "${GLOBAL_WIFI_FILE}" "${PRESERVED_WIFI_FILE}" || \ 1025 + cp "${GLOBAL_WIFI_FILE}" "${WIFI_CREDS_FILE}" 1026 + else 1027 + cp "${GLOBAL_WIFI_FILE}" "${WIFI_CREDS_FILE}" 1028 + fi 1015 1029 1016 1030 ac_media_stage_boot_tree "${STAGE_ROOT}" "${VMLINUZ}" "${CONFIG_FILE}" 1017 - if [ -f "${WIFI_CREDS_FILE}" ]; then 1018 - cp "${WIFI_CREDS_FILE}" "${STAGE_ROOT}/wifi_creds.json" 1019 - fi 1031 + cp "${WIFI_CREDS_FILE}" "${STAGE_ROOT}/wifi_creds.json" 1020 1032 1021 1033 ensure_media_helper_image 1022 1034 CONTAINER=$(sudo docker create --rm --privileged -v /dev:/dev \ ··· 1031 1043 return "${rc}" 1032 1044 fi 1033 1045 log "Verified config: $(ac_media_summarize_config_file "${CONFIG_FILE}")" 1046 + log "Verified $(ac_media_summarize_wifi_creds_file "${WIFI_CREDS_FILE}")" 1034 1047 cleanup_flash_usb 1035 1048 } 1036 1049 ··· 1114 1127 ac_media_write_identity_config "${IDENTITY_FILE}" 1115 1128 ac_media_stage_boot_tree "${STAGING}" "${VMLINUZ}" "${LEGACY_CONFIG}" 1116 1129 cp "${IDENTITY_FILE}" "${STAGING}/$(ac_media_identity_filename)" 1130 + # Embed the global Wi-Fi presets so every freshly-flashed download has 1131 + # the lab/home networks ready out of the box. ac_media_create_efi_disk_image 1132 + # will pick this up automatically (it copies stage_root/wifi_creds.json 1133 + # into the EFI partition when present). 1134 + ac_media_write_global_wifi_creds "${STAGING}/wifi_creds.json" 1117 1135 ac_media_create_efi_disk_image "${STAGING}" "${IMAGE}" "AC_NATIVE" 1118 1136 ac_media_generate_manifest "${IMAGE}" "${AC_BUILD_NAME:-unknown}" "${MANIFEST}" 1119 1137
+1 -1
fedac/native/scripts/flash-helper-runner.sh
··· 318 318 sgdisk --zap-all "${USB_DEV}" >/dev/null 2>&1 || true 319 319 dd if=/dev/zero of="${USB_DEV}" bs=1M count=16 status=none 320 320 321 - cat <<PART_EOF | sfdisk --force "${USB_DEV}" 321 + cat <<PART_EOF | sfdisk --force --no-reread "${USB_DEV}" 322 322 label: gpt 323 323 size=${MAIN_MB}M, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name="ACBOOT" 324 324 size=${EFI_MB}M, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name="ACEFI"
+116
fedac/native/scripts/media-layout.sh
··· 132 132 fi 133 133 } 134 134 135 + ac_media_write_global_wifi_creds() { 136 + local out_path="$1" 137 + 138 + mkdir -p "$(dirname "${out_path}")" 139 + # Keep this preset list in sync with the hardcoded fallbacks in src/wifi.c. 140 + cat > "${out_path}" <<'EOF' 141 + [ 142 + {"ssid":"aesthetic.computer","pass":"aesthetic.computer"}, 143 + {"ssid":"ATT2AWTpcr","pass":"t84q%7%g2h8u"}, 144 + {"ssid":"GettyLink","pass":""}, 145 + {"ssid":"Tondo_Guest","pass":"California"} 146 + ] 147 + EOF 148 + } 149 + 150 + ac_media_merge_wifi_creds() { 151 + local out_path="$1" 152 + local base_path="$2" 153 + local extra_path="${3:-}" 154 + 155 + if [ ! -f "${base_path}" ]; then 156 + echo "Missing base wifi creds: ${base_path}" >&2 157 + return 1 158 + fi 159 + 160 + if [ -z "${extra_path}" ] || [ ! -f "${extra_path}" ]; then 161 + cp "${base_path}" "${out_path}" 162 + return 0 163 + fi 164 + 165 + python3 - "${base_path}" "${extra_path}" "${out_path}" <<'PYEOF' 166 + import json 167 + import pathlib 168 + import sys 169 + 170 + base_path, extra_path, out_path = sys.argv[1:] 171 + 172 + def read_creds(path): 173 + try: 174 + data = json.loads(pathlib.Path(path).read_text()) 175 + except Exception: 176 + return [] 177 + if not isinstance(data, list): 178 + return [] 179 + 180 + creds = [] 181 + for entry in data: 182 + if not isinstance(entry, dict): 183 + continue 184 + ssid = entry.get("ssid") 185 + password = entry.get("pass", "") 186 + if not isinstance(ssid, str) or not ssid: 187 + continue 188 + if not isinstance(password, str): 189 + password = "" 190 + creds.append({"ssid": ssid, "pass": password}) 191 + return creds 192 + 193 + merged = {} 194 + order = [] 195 + for path in (base_path, extra_path): 196 + for entry in read_creds(path): 197 + ssid = entry["ssid"] 198 + if ssid not in merged: 199 + order.append(ssid) 200 + merged[ssid] = entry 201 + 202 + pathlib.Path(out_path).write_text( 203 + json.dumps([merged[ssid] for ssid in order], indent=2) + "\n" 204 + ) 205 + PYEOF 206 + } 207 + 208 + ac_media_summarize_wifi_creds_file() { 209 + local wifi_path="$1" 210 + 211 + if [ ! -f "${wifi_path}" ]; then 212 + echo "wifi=missing" 213 + return 1 214 + fi 215 + 216 + python3 - "${wifi_path}" <<'PYEOF' 217 + import json 218 + import pathlib 219 + import sys 220 + 221 + path = pathlib.Path(sys.argv[1]) 222 + try: 223 + data = json.loads(path.read_text()) 224 + except Exception: 225 + print("wifi=invalid") 226 + raise SystemExit(1) 227 + 228 + if not isinstance(data, list): 229 + print("wifi=invalid") 230 + raise SystemExit(1) 231 + 232 + count = sum( 233 + 1 234 + for entry in data 235 + if isinstance(entry, dict) and isinstance(entry.get("ssid"), str) and entry.get("ssid") 236 + ) 237 + print(f"wifi={count}") 238 + PYEOF 239 + } 240 + 135 241 ac_media_stage_boot_tree() { 136 242 local stage_root="$1" 137 243 local kernel_path="$2" ··· 199 305 if [ -f "${stage_root}/config.json" ]; then 200 306 mcopy -o -i "${image_path}" "${stage_root}/config.json" ::config.json 201 307 fi 308 + if [ -f "${stage_root}/wifi_creds.json" ]; then 309 + mcopy -o -i "${image_path}" "${stage_root}/wifi_creds.json" ::wifi_creds.json 310 + fi 202 311 mcopy -o -i "${image_path}" "${stage_root}/EFI/BOOT/BOOTX64.EFI" ::EFI/BOOT/BOOTX64.EFI 203 312 # 32-bit UEFI fallback (kernel with EFI_MIXED=y) 204 313 if [ -f "${stage_root}/EFI/BOOT/BOOTIA32.EFI" ]; then ··· 229 338 mmd -i "${image_path}@@${esp_offset}" ::EFI ::EFI/BOOT 2>/dev/null || true 230 339 if [ -f "${stage_root}/config.json" ]; then 231 340 mcopy -o -i "${image_path}@@${esp_offset}" "${stage_root}/config.json" ::config.json 341 + fi 342 + if [ -f "${stage_root}/wifi_creds.json" ]; then 343 + mcopy -o -i "${image_path}@@${esp_offset}" "${stage_root}/wifi_creds.json" ::wifi_creds.json 232 344 fi 233 345 if [ -f "${stage_root}/$(ac_media_identity_filename)" ]; then 234 346 mcopy -o -i "${image_path}@@${esp_offset}" "${stage_root}/$(ac_media_identity_filename)" "::$(ac_media_identity_filename)" ··· 445 557 local image_path="$1" 446 558 local config_path="$2" 447 559 local data_size_mib="${3:-$(ac_media_nixos_data_size_mib)}" 560 + local wifi_creds_path="${4:-}" 448 561 local sector_size=512 449 562 local data_start 450 563 local data_offset ··· 482 595 export MTOOLS_SKIP_CHECK=1 483 596 mmd -i "${image_path}@@${data_offset}" ::logs 2>/dev/null || true 484 597 mcopy -o -i "${image_path}@@${data_offset}" "${config_path}" ::config.json 598 + if [ -n "${wifi_creds_path}" ] && [ -f "${wifi_creds_path}" ]; then 599 + mcopy -o -i "${image_path}@@${data_offset}" "${wifi_creds_path}" ::wifi_creds.json 600 + fi 485 601 } 486 602 487 603 ac_media_build_hybrid_iso() {