try{requireSameOrigin(request);constuser=awaitrequireUser();const{id: rawId}=awaitparams;constid=Number(rawId);constsource=db.prepare("SELECT id FROM sources WHERE id=? AND user_id=?").get(id,user.id);if(!source)returnNextResponse.json({error:"Not found"},{status: 404});const{role}=awaitrequest.json()as{role?: string};if(!['viewer','editor'].includes(role||''))returnNextResponse.json({error:"Invalid role"},{status: 400});consttoken=randomBytes(24).toString("base64url");consthash=createHash("sha256").update(token).digest("hex");db.prepare("INSERT INTO source_invites(source_id,token_hash,role,expires_at,created_by) VALUES(?,?,?,datetime('now','+7 days'),?)").run(id,hash,role,user.id);audit(user.id,"source.invite.create","source",id,{role});constorigin=(process.env.NEXT_PUBLIC_APP_URL||newURL(request.url).origin).replace(/\/$/,"");returnNextResponse.json({url:`${origin}/invite/${token}`});}catch{returnNextResponse.json({error:"Unauthorized"},{status: 401});}