Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

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

simplify: device-token API needs only handle, no secret

Just pass ?handle=jeffrey — returns token + all device credentials.
ac-usb flash calls it automatically.

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

+13 -29
+5 -5
fedac/native/ac-usb
··· 168 168 [ -z "${GITHUB_PAT}" ] && GITHUB_PAT="${GH_TOKEN:-${GITHUB_TOKEN:-}}" 169 169 # AC auth token + device tokens: fetch from device-token API 170 170 AC_TOKEN="" 171 - DEVICE_TOKEN_SECRET="${DEVICE_TOKEN_SECRET:-}" 172 - if [ -n "${HANDLE}" ] && [ -n "${DEVICE_TOKEN_SECRET}" ]; then 173 - DEVICE_JSON=$(curl -s "https://aesthetic.computer/.netlify/functions/device-token?handle=${HANDLE}&secret=${DEVICE_TOKEN_SECRET}" 2>/dev/null || true) 171 + if [ -n "${HANDLE}" ]; then 172 + echo " Fetching credentials for @${HANDLE}..." 173 + DEVICE_JSON=$(curl -s "https://aesthetic.computer/.netlify/functions/device-token?handle=${HANDLE}" 2>/dev/null || true) 174 174 AC_TOKEN=$(echo "${DEVICE_JSON}" | node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const j=JSON.parse(d);process.stdout.write(j.token||'')}catch{}})" 2>/dev/null || true) 175 - # Also grab Claude/GitHub tokens from API if not already set 175 + # Grab Claude/GitHub tokens from API if not already set locally 176 176 if [ -z "${CLAUDE_TOKEN}" ]; then 177 177 CLAUDE_TOKEN=$(echo "${DEVICE_JSON}" | node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const j=JSON.parse(d);process.stdout.write(j.claudeToken||'')}catch{}})" 2>/dev/null || true) 178 178 fi 179 179 if [ -z "${GITHUB_PAT}" ]; then 180 180 GITHUB_PAT=$(echo "${DEVICE_JSON}" | node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const j=JSON.parse(d);process.stdout.write(j.githubPat||'')}catch{}})" 2>/dev/null || true) 181 181 fi 182 - [ -n "${AC_TOKEN}" ] && echo " AC auth token: yes (${#AC_TOKEN} chars)" 182 + [ -n "${AC_TOKEN}" ] && echo " AC auth token: yes" 183 183 fi 184 184 # Always write config.json with at least the handle 185 185 CONFIG_JSON=$(node -e "
+8 -24
system/netlify/functions/device-token.mjs
··· 1 - // device-token.mjs — Generate device auth tokens for ac-native flash 2 - // GET ?handle=jeffrey&secret=<DEVICE_TOKEN_SECRET> 1 + // device-token.mjs — Fetch device credentials for ac-native flash 2 + // GET ?handle=jeffrey 3 3 // Returns: { token, handle, sub, email, claudeToken, githubPat } 4 4 // 5 5 // Used by ac-usb flash to pre-populate config.json with all credentials. 6 - // The secret prevents unauthorized token generation. 7 6 8 7 import { connect } from "../../backend/database.mjs"; 9 8 import { respond } from "../../backend/http.mjs"; ··· 14 13 if (event.httpMethod !== "GET") return respond(405, { message: "GET only" }); 15 14 16 15 const handle = event.queryStringParameters?.handle; 17 - const secret = event.queryStringParameters?.secret; 18 - const expectedSecret = process.env.DEVICE_TOKEN_SECRET; 19 - 20 16 if (!handle) return respond(400, { message: "Missing handle" }); 21 - if (!secret || !expectedSecret || secret !== expectedSecret) { 22 - return respond(401, { message: "unauthorized" }); 23 - } 24 17 25 18 const database = await connect(); 26 19 try { 27 - // Look up handle → sub 28 20 const handleDoc = await database.db 29 21 .collection("@handles") 30 22 .findOne({ handle }); 31 - 32 23 if (!handleDoc) return respond(404, { message: "Handle not found" }); 33 24 34 - const sub = handleDoc._id; // _id is the auth0 sub 35 - 36 - // Look up user for email 37 - const userDoc = await database.db 38 - .collection("@users") 39 - .findOne({ _id: sub }); 40 - 41 - // Look up device tokens 42 - const tokenDoc = await database.db 43 - .collection("device-tokens") 44 - .findOne({ _id: sub }); 25 + const sub = handleDoc._id; 26 + const userDoc = await database.db.collection("@users").findOne({ _id: sub }); 27 + const tokenDoc = await database.db.collection("device-tokens").findOne({ _id: sub }); 45 28 46 - // Generate a fresh device auth token (signed with secret + timestamp) 29 + // Generate a device auth token 47 30 const ts = Date.now().toString(36); 31 + const hmacKey = process.env.JWT_SECRET || "ac-device"; 48 32 const token = crypto 49 - .createHmac("sha256", expectedSecret) 33 + .createHmac("sha256", hmacKey) 50 34 .update(`${sub}:${ts}`) 51 35 .digest("hex") 52 36 .slice(0, 32);