Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

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

flash-mac: bake Claude OAuth token from MongoDB into initramfs

flash-mac.sh now fetches the user's year-long Claude Code token from
/api/claude-token (stored in MongoDB as @handles.claudeCodeToken) using
the ac-login access_token from ~/.ac-token as the auth bearer. The
response token is appended to the initramfs as a supplementary cpio
archive containing /claude-token + /claude-state.json, concatenated as
a second gzipped stream (Linux kernel unpack_to_rootfs handles multiple
concatenated gzip+cpio segments, same as intel-ucode injection).

pty.c already reads /claude-token at child-spawn time and sets
CLAUDE_CODE_OAUTH_TOKEN — so the claude binary launches without an
interactive login prompt. If ~/.ac-token is expired the bake is
gracefully skipped with a hint to run ac-login; if no token is stored
in MongoDB for the user, bake is skipped with a hint to POST one.

Also broadens initramfs/init so /claude-state.json → /tmp/.claude.json
copy runs when either /claude-creds.json (legacy full-JSON bake path)
or /claude-token (new plain-bearer bake path) is present. Previously
only the legacy path triggered the /tmp/.claude/ setup, so a macOS
flash would bake the token correctly but still show Claude's onboarding
screen on first launch because /tmp/.claude.json never got populated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+72 -8
+9 -3
fedac/native/initramfs/init
··· 29 29 # Loopback 30 30 ip link set lo up 2>/dev/null 31 31 32 - # Restore baked Claude credentials (tmpfs mount hid the originals) 33 - if [ -f /claude-creds.json ]; then 32 + # Restore baked Claude credentials (tmpfs mount hid the originals). 33 + # Two bake paths produce creds at /: 34 + # /claude-creds.json legacy full JSON (linux ac-os, reads ~/.claude/.credentials.json) 35 + # /claude-token plain OAuth bearer (macOS flash-mac.sh, MongoDB year-long token) 36 + # Either presence triggers setup of /tmp/.claude/ so Claude Code boots without 37 + # onboarding/login prompts. pty.c separately reads /claude-token to set 38 + # CLAUDE_CODE_OAUTH_TOKEN in the child's env. 39 + if [ -f /claude-creds.json ] || [ -f /claude-token ]; then 34 40 mkdir -p /tmp/.claude 35 - cp /claude-creds.json /tmp/.claude/.credentials.json 41 + [ -f /claude-creds.json ] && cp /claude-creds.json /tmp/.claude/.credentials.json 36 42 cp /claude-state.json /tmp/.claude.json 2>/dev/null 37 43 printf '{"permissions":{"allow":["Bash(*)","Read(*)","Write(*)","Edit(*)","Glob(*)","Grep(*)","WebFetch(*)","WebSearch(*)"]},"autoUpdates":false,"installMethod":"native"}\n' > /tmp/.claude/settings.json 38 44 fi
+63 -5
fedac/native/scripts/flash-mac.sh
··· 71 71 TOKEN_FILE="${TOKEN_HOME}/.ac-token" 72 72 73 73 USER_HANDLE=""; USER_SUB=""; USER_EMAIL="" 74 + AC_ACCESS_TOKEN=""; AC_TOKEN_EXPIRED=0 74 75 if [ -f "${TOKEN_FILE}" ] && command -v node >/dev/null 2>&1; then 75 76 eval "$(node -e ' 76 77 const t = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); 77 78 let h = t.user?.handle || t.user?.name || ""; 78 79 if (h.startsWith("@")) h = h.slice(1); 80 + const now = Date.now(); 81 + const rawExp = t.expires_at || 0; 82 + const expMs = rawExp > 10_000_000_000 ? rawExp : rawExp * 1000; 83 + const fresh = expMs && now < expMs; 79 84 const out = (k, v) => process.stdout.write(`${k}=${JSON.stringify(v || "")}\n`); 80 - out("USER_HANDLE", h); 81 - out("USER_SUB", t.user?.sub); 82 - out("USER_EMAIL", t.user?.email); 85 + out("USER_HANDLE", h); 86 + out("USER_SUB", t.user?.sub); 87 + out("USER_EMAIL", t.user?.email); 88 + out("AC_ACCESS_TOKEN", fresh ? (t.access_token || "") : ""); 89 + process.stdout.write(`AC_TOKEN_EXPIRED=${fresh ? 0 : 1}\n`); 83 90 ' "${TOKEN_FILE}" 2>/dev/null)" 84 91 [ -n "${USER_HANDLE}" ] && log "Authenticated as @${USER_HANDLE}" 85 92 fi 86 93 [ -z "${USER_HANDLE}${USER_SUB}${USER_EMAIL}" ] && \ 87 94 log "No ~/.ac-token (run \`ac-login\` first to bake credentials in)" 88 95 96 + # --- fetch Claude OAuth token from MongoDB (year-long token per handle) --- 97 + # The claude-token netlify function returns the token stored at 98 + # @handles.claudeCodeToken for the authenticated user's sub. pty.c reads 99 + # /claude-token at spawn time and sets CLAUDE_CODE_OAUTH_TOKEN so 100 + # `claude` launches without an interactive login prompt. 101 + CLAUDE_TOKEN="" 102 + if [ -n "${AC_ACCESS_TOKEN}" ]; then 103 + log "Fetching Claude OAuth token from MongoDB…" 104 + CT_RESP="$(curl -fsS -H "Authorization: Bearer ${AC_ACCESS_TOKEN}" \ 105 + "https://aesthetic.computer/api/claude-token" 2>/dev/null || echo "")" 106 + if [ -n "${CT_RESP}" ]; then 107 + CLAUDE_TOKEN="$(node -e ' 108 + try { process.stdout.write(JSON.parse(process.argv[1]).token || ""); } catch {} 109 + ' "${CT_RESP}" 2>/dev/null)" 110 + fi 111 + if [ -n "${CLAUDE_TOKEN}" ]; then 112 + log " claude token: ${#CLAUDE_TOKEN} bytes fetched" 113 + else 114 + log " claude token: none stored in MongoDB (POST to /api/claude-token from the web to save one)" 115 + fi 116 + elif [ "${AC_TOKEN_EXPIRED}" = "1" ]; then 117 + log " claude token: skipped (~/.ac-token expired — run \`ac-login\` to refresh)" 118 + fi 119 + 120 + # --- bake Claude creds into initramfs via concatenated cpio archive --- 121 + # The Linux kernel's unpack_to_rootfs() accepts multiple concatenated 122 + # gzipped cpio archives in the initrd stream (same trick intel-ucode 123 + # uses). We build a tiny supplementary archive containing /claude-token 124 + # + /claude-state.json and append it to the end of initramfs.cpio.gz. 125 + # pty.c reads /claude-token directly; init copies /claude-state.json to 126 + # /tmp/.claude.json so Claude Code skips onboarding prompts. 127 + if [ -n "${CLAUDE_TOKEN}" ]; then 128 + BAKE_DIR="$(mktemp -d /tmp/ac-bake.XXXXXX)" 129 + BAKED_INITRAMFS="/tmp/ac-initramfs-baked.$$.cpio.gz" 130 + ORIG_INITRD_SIZE="$(stat -f%z "${INITRAMFS}")" 131 + printf %s "${CLAUDE_TOKEN}" > "${BAKE_DIR}/claude-token" 132 + chmod 600 "${BAKE_DIR}/claude-token" 133 + cat > "${BAKE_DIR}/claude-state.json" <<STATE 134 + {"oauthAccount":{"emailAddress":"${USER_EMAIL}","organizationName":"","accountUuid":""},"hasCompletedOnboarding":true,"installMethod":"manual","numStartups":1,"autoUpdates":false,"autoUpdatesProtectedForNative":true} 135 + STATE 136 + cp "${INITRAMFS}" "${BAKED_INITRAMFS}" 137 + ( cd "${BAKE_DIR}" && printf 'claude-token\nclaude-state.json\n' \ 138 + | cpio -o -H newc 2>/dev/null ) \ 139 + | gzip -9 >> "${BAKED_INITRAMFS}" \ 140 + || die "Failed to append Claude creds cpio to initramfs" 141 + rm -rf "${BAKE_DIR}" 142 + INITRAMFS="${BAKED_INITRAMFS}" 143 + NEW_INITRD_SIZE="$(stat -f%z "${INITRAMFS}")" 144 + log " baked initramfs: ${NEW_INITRD_SIZE} bytes (+$(( NEW_INITRD_SIZE - ORIG_INITRD_SIZE )) bytes for creds cpio)" 145 + fi 146 + 89 147 # --- preserve existing wifi_creds.json from target USB before we wipe it --- 90 148 # Linux `ac-os flash` does this via ac_media_merge_wifi_creds: read the 91 149 # previously-flashed USB for user-added networks, then merge with the ··· 100 158 log "Preserving wifi_creds.json from ${mnt}" && break 101 159 fi 102 160 done 103 - trap "rm -f '${PRESERVE_WIFI}' 2>/dev/null" EXIT 161 + trap "rm -f '${PRESERVE_WIFI}' '${BAKED_INITRAMFS:-}' 2>/dev/null" EXIT 104 162 105 163 # --- hardcoded preset networks (kept in sync with media-layout.sh + src/wifi.c) --- 106 164 WIFI_PRESETS_JSON='[ ··· 184 242 # --- mount --- 185 243 M1=$(mktemp -d /tmp/ac-main.XXXXXX) 186 244 M2=$(mktemp -d /tmp/ac-efi.XXXXXX) 187 - trap "umount '${M1}' 2>/dev/null; umount '${M2}' 2>/dev/null; rmdir '${M1}' '${M2}' 2>/dev/null; true" EXIT 245 + trap "umount '${M1}' 2>/dev/null; umount '${M2}' 2>/dev/null; rmdir '${M1}' '${M2}' 2>/dev/null; rm -f '${PRESERVE_WIFI}' '${BAKED_INITRAMFS:-}' 2>/dev/null; true" EXIT 188 246 189 247 log "Mounting partitions…" 190 248 mount_msdos "${P1}" "${M1}"