# การเริ่มต้น รหัส QR ของอุปกรณ์ และการเข้าสู่ระบบด้วยรหัสหกหลัก

> HTML: https://remote.ivjn.us/docs/th/pairing/

Agent มีค่าเริ่มต้นเป็น Exchange ที่ `wss://exchange.ivjn.us`; API การจัดการ CLI/Console ใช้ `https://exchange.ivjn.us` การกำหนดค่าที่มีอยู่จะมีความสำคัญกว่า ดังนั้นที่อยู่ Exchange ที่โฮสต์ด้วยตนเองจึงยังคงอยู่

## การลงทะเบียน SaaS และการเข้าสู่ระบบครั้งแรก

```powershell
remote-cli register --username alice --email alice@example.com
# 按隐藏输入提示设置密码，注册后向邮箱发送验证码。
remote-cli verify-email --username alice
# 隐藏输入邮件中的 8 位数字验证码，然后登录。
remote-cli login --email alice@example.com
# init 是 login 的别名，不带 --email 时交互输入邮箱和密码。
remote-cli init
# 原有令牌仍可使用：
remote-cli login --server https://exchange.ivjn.us --token-stdin
```

การลงทะเบียนและการเข้าสู่ระบบจะเชื่อมต่อกับ `https://exchange.ivjn.us` ตามค่าเริ่มต้น เพิ่ม `--server` สำหรับบริการที่โฮสต์เอง การเข้าสู่ระบบใช้ที่อยู่อีเมลเป็นข้อมูลประจำตัวของบัญชี ช่องว่างจะถูกลบออกและที่อยู่จะถูกแปลงเป็นตัวพิมพ์เล็ก รูปแบบที่ไม่ถูกต้องจะถูกปฏิเสธทันที ชื่อผู้ใช้คือชื่อพื้นที่ทำงานที่เลือกระหว่างการลงทะเบียน (3–64 ตัวอักษร ตัวเลข หรือ `._-`) รหัสผ่านบัญชีไม่มีข้อจำกัดด้านความยาวหรือรูปแบบอักขระ เซิร์ฟเวอร์จะเก็บเฉพาะแฮชรหัสผ่านเท่านั้น ระบบอัตโนมัติสามารถใช้ `--password-stdin`; อย่าใส่รหัสผ่านในอาร์กิวเมนต์คำสั่ง บัญชีใหม่ไม่สามารถเข้าสู่ระบบได้จนกว่าที่อยู่อีเมลจะได้รับการยืนยัน CLI จะจัดเก็บเฉพาะโทเค็นเซสชันที่ส่งคืนเท่านั้น โดยจะไม่เก็บรหัสผ่าน และเก็บรักษาการเข้าสู่ระบบที่มีอยู่ในขณะที่การลงทะเบียนรอการตรวจสอบ

การลงทะเบียนแต่ละครั้งจะสร้างพื้นที่ทำงานแยกต่างหาก โดยมีบัญชีที่ลงทะเบียนเป็นผู้ดูแลระบบ อุปกรณ์ สมาชิก เซสชันระยะไกล ตัวชี้วัด และบันทึกการตรวจสอบจะถูกแยกออกจากกัน พื้นที่ทำงานที่แตกต่างกันอาจใช้รหัสอุปกรณ์เดียวกัน การอนุมัติรหัสหกหลักจะเพิ่มอุปกรณ์หรือสมาชิกใหม่ไปยัง **พื้นที่ทำงานของผู้อนุมัติ** หากต้องการเข้าร่วมพื้นที่ทำงานที่มีอยู่ ให้ใช้โทเค็นหรือการอนุญาตหกหลักที่ได้รับจากผู้ดูแลระบบ

Android Console ยังรองรับการลงทะเบียน การเข้าสู่ระบบด้วยรหัสผ่าน การเข้าสู่ระบบโทเค็นที่มีอยู่ และการเข้าสู่ระบบด้วยรหัสหกหลัก รหัสผ่านใช้สำหรับคำขอปัจจุบันเท่านั้น ข้อมูลประจำตัวจะถูกเก็บไว้ใน SecureStore

เซสชันการเข้าสู่ระบบด้วยรหัสผ่านมีอายุ 30 วัน โดยมีเซสชันที่ใช้งานได้สูงสุด 32 เซสชันต่อบัญชี การเข้าสู่ระบบอีกครั้งจะไม่ขับไล่ไคลเอนต์อื่น `POST /api/auth/logout` เพิกถอนโทเค็นเซสชัน Bearer ปัจจุบัน และ WebSockets ที่จัดตั้งขึ้นจะปิดภายในไม่เกิน 5 วินาที เข้าสู่ระบบอีกครั้งหลังจากหมดอายุ โทเค็นอุปกรณ์และโทเค็นการดำเนินงานที่มีอยู่จะคงอายุการใช้งานเดิมไว้

ข้อมูลระบุตัวตนแบบโทเค็นเท่านั้นไม่มีบัญชีรหัสผ่านและไม่สามารถกู้คืนการเข้าถึงทางอีเมลได้ การเรียกเก็บเงินและการกำหนดเส้นทางข้ามอินสแตนซ์ WebSocket อยู่นอกขอบเขตของการใช้งานนี้

## การยืนยันอีเมลและการกู้คืนรหัสผ่าน

```powershell
remote-cli resend-verification --email alice@example.com
remote-cli verify-email --username alice
remote-cli forgot-password --email alice@example.com
remote-cli reset-password --email alice@example.com
# 按提示输入邮件验证码、新密码，再重新登录。

# 已登录的旧密码账号绑定或更换邮箱，需要再次验证当前密码。
remote-cli set-email --email alice@example.com
remote-cli verify-email --username alice
```

การตรวจสอบและการกู้คืนจะใช้รหัสแปดหลักเฉพาะวัตถุประสงค์แยกกัน รหัสจะหมดอายุหลังจากผ่านไป 15 นาทีหรือพยายามไม่ถูกต้องติดต่อกันห้าครั้ง การส่งอีเมลใหม่จะทำให้รหัสก่อนหน้าเป็นโมฆะ แต่ละบัญชีอาจขออีเมลหนึ่งฉบับต่อวัตถุประสงค์ต่อนาที คำสั่งการตรวจสอบและรีเซ็ตยอมรับ `--code` สำหรับระบบอัตโนมัติ ตามค่าเริ่มต้น การป้อนรหัสจะถูกซ่อนไว้ การรีเซ็ตสำเร็จจะเพิกถอนทุกเซสชันการเข้าสู่ระบบสำหรับบัญชีนั้น โดยที่ WebSockets ที่สร้างไว้จะถูกตัดการเชื่อมต่อภายในเวลาไม่เกิน 5 วินาที สมาชิกพื้นที่ทำงานและอุปกรณ์อื่นๆ จะไม่ได้รับผลกระทบ

ป้อนที่อยู่อีเมลในหน้าการลงทะเบียน Console จากนั้นดำเนินการตรวจสอบต่อไป หน้าเข้าสู่ระบบจะมีการดำเนินการ **ยืนยันอีเมล** และ **ลืมรหัสผ่าน** เมื่อเปลี่ยนที่อยู่อีเมล ที่อยู่เดิมจะยังคงใช้งานได้จนกว่าการยืนยันจะเสร็จสิ้น คำขอส่งการยืนยันและการกู้คืนอีกครั้งจะส่งคืนข้อความทั่วไปเดียวกัน ไม่ว่าอีเมลนั้นจะลงทะเบียนหรือไม่ก็ตาม

อีเมลต้องมีการโยกย้ายการกำหนดค่า `0004_email.sql` และ SMTP: `SMTP_HOST`, `SMTP_PORT`, `SMTP_FROM`, `SMTP_USERNAME`, `SMTP_PASSWORD` และ `SMTP_SECURITY` STARTTLS เป็นค่าเริ่มต้น นอกจากนี้ยังรองรับ TLS โดยนัยด้วย SMTP ที่ไม่ได้เข้ารหัสจะได้รับอนุญาตเฉพาะกับที่อยู่แบบย้อนกลับสำหรับการทดสอบในเครื่องเท่านั้น เก็บข้อมูลรับรอง SMTP ไว้ในไฟล์สภาพแวดล้อมการบริการและเก็บไว้นอก Git หากไม่มีการกำหนดค่าอีเมล จุดสิ้นสุดการลงทะเบียนและการส่งอีเมลใหม่จะส่งคืน 503 การเข้าสู่ระบบบัญชีที่มีอยู่ยังคงสามารถใช้ได้ กำหนดค่าการส่งอีเมลก่อนเปิดใช้งานการลงทะเบียนการผลิต ความล้มเหลว SMTP ชั่วคราวอาจทำให้บัญชีรอการยืนยัน เมื่อบริการฟื้นตัวแล้ว ให้ส่งอีเมลยืนยันอีกครั้งแทนการลงทะเบียนอีกครั้ง

## API บัญชี Exchange

| วิธีการและเส้นทาง | การรับรองความถูกต้อง | วัตถุประสงค์ |
| --- | --- | --- |
| `POST /api/auth/register` | ไม่มี; อัตราจำกัด | `{username,password,email}` สร้างบัญชีที่รอการตรวจสอบ ส่งคืน 202 และ `verification_required` โดยไม่ต้องออกเซสชัน |
| `POST /api/auth/login` | ไม่มี; อัตราจำกัด | `{email,password}` ออกเซสชันการเข้าสู่ระบบแยกต่างหาก |
| `GET /api/auth/me` | โทเค็นการดำเนินงานหรือเซสชันการเข้าสู่ระบบ | ส่งกลับ `name`, `tenant_id` และ `role` |
| `POST /api/auth/logout` | เซสชันการเข้าสู่ระบบปัจจุบัน | เพิกถอนเซสชันปัจจุบันโดยไม่เพิกถอนไคลเอ็นต์อื่น |
| `POST /api/auth/verify-email` | ไม่มี; อัตราจำกัด | `{username,code}` ใช้รหัสยืนยันอีเมล |
| `POST /api/auth/resend-verification` | ไม่มี; อัตราจำกัด | `{email}` ส่งอีเมลอีกครั้งไปยังที่อยู่ที่รอการตรวจสอบ |
| `POST /api/auth/forgot-password` | ไม่มี; อัตราจำกัด | `{email}` ส่งรหัสกู้คืนไปยังที่อยู่ที่ได้รับการยืนยันแล้ว |
| `POST /api/auth/reset-password` | ไม่มี; อัตราจำกัด | `{email,code,password}` เปลี่ยนรหัสผ่านและเพิกถอนเซสชันเก่า |
| `POST /api/auth/email` | เซสชันการเข้าสู่ระบบปัจจุบันและรหัสผ่านบัญชี | `{email,password}` ขอผูกหรือเปลี่ยนแปลงอีเมล โดยมีผลหลังจากการตรวจสอบแล้ว |

การล็อกอินสำเร็จจะส่งคืน `username`, `email` (ถ้าผูกไว้), `tenant_id`, `token` และ `expires_in` พร้อมด้วย `Cache-Control: no-store` รหัสผ่านบัญชีจะเติม salt แล้วจัดเก็บโดยใช้ Argon2id พร้อมพารามิเตอร์เริ่มต้น คำขอบัญชีถูกจำกัดไว้ที่ 20 ต่อนาทีต่อ IP ต้นทาง TCP และ 10 ต่อนาทีต่อชื่อผู้ใช้ โดยมีแฮชรหัสผ่านพร้อมกันสูงสุดสี่รายการ IP ที่ส่งต่อโดยไคลเอ็นต์ไม่น่าเชื่อถือ ไคลเอ็นต์ที่อยู่ด้านหลังพร็อกซีแบบย้อนกลับจะแชร์โควต้า IP ของตน การใช้งานสาธารณะควรกำหนดค่าขีดจำกัดอัตราเพิ่มเติมที่ทางเข้าที่เชื่อถือได้

Rust Exchange ปิดใช้งานการลงทะเบียนสาธารณะตามค่าเริ่มต้น เปิดใช้งานอย่างชัดเจนด้วย `EXCHANGE_ALLOW_REGISTRATION=true` และกำหนดค่า SMTP `false` ปิดใช้งานการลงทะเบียนใหม่ในขณะที่บัญชีที่มีอยู่ยังสามารถเข้าสู่ระบบได้

## การแสดงรหัสหกหลักบน Agent

Android Remote Agent มีการกรอกที่อยู่เริ่มต้นไว้ล่วงหน้า แตะ **เชื่อมต่อด้วยรหัสหกหลัก** เพื่อแสดงรหัสที่ถูกต้องเป็นเวลา 5 นาที ใน CLI ของผู้ดูแลระบบที่เข้าสู่ระบบแล้ว ให้รัน:

```powershell
remote-cli pair 012345
# 可选：覆盖默认 ID 和显示名称
remote-cli pair 012345 --device-id my-android --name "我的手机"
```

เมื่อดึงรหัสการเชื่อมต่อ CLI จะแสดงชื่ออุปกรณ์ ประเภทข้อมูลระบุตัวตน และ ID อุปกรณ์ที่แนะนำ ตรวจสอบว่าเป็นอุปกรณ์ของคุณก่อนที่จะอนุมัติ ID เริ่มต้นใช้ตัวอักษร ASCII ตัวพิมพ์เล็ก ตัวเลข และ `._-` จากชื่ออุปกรณ์ โดยลบช่องว่างและอักขระอื่นๆ โดยจะกลับไปเป็น `device` เมื่อไม่มีอักขระที่ใช้งานได้ และจำกัดไว้ที่ 64 อักขระ หากใช้ ID ในพื้นที่ทำงานเดียวกัน หมายเลขจะถูกต่อท้าย เช่น `realmev5`, `realmev51` และ `realmev52` รหัสฐานจะสั้นลงเมื่อจำเป็น Exchange จัดการข้อขัดแย้งที่เกิดขึ้นพร้อมกันระหว่างการสร้าง และ CLI จะพิมพ์ ID ที่จัดสรรสุดท้าย รหัสที่ระบุด้วยตนเองยังได้รับส่วนต่อท้ายที่เป็นตัวเลขหากมีข้อขัดแย้ง Android ใช้ชื่ออุปกรณ์ระบบโดยถอยกลับไปที่โมเดล ตัวแทนดั้งเดิมใช้ชื่อโฮสต์ Agent จะได้รับโทเค็นอุปกรณ์แยกต่างหาก จัดเก็บแบบเข้ารหัส และเชื่อมต่อโดยอัตโนมัติ การเข้าถึงและการควบคุมหน้าจอไม่ได้เปิดใช้งานโดยอัตโนมัติ การยกเลิก การหมดอายุ หรือความล้มเหลวในการตรวจสอบสิทธิ์จะคงการกำหนดค่าที่มีอยู่ไว้ หยุด Agent ที่เชื่อมต่ออยู่แล้วก่อนที่จะจับคู่

## การเพิ่มคอมพิวเตอร์ เราเตอร์ และตัวแทน Linux

เอเจนต์ Windows, macOS, OpenWrt และ Linux สามารถใช้วิธีใดวิธีหนึ่งได้โดยไม่ต้องป้อนโทเค็นอุปกรณ์ด้วยตนเอง:

| แพลตฟอร์ม | วิธีที่ 1: รหัสการจับคู่ / รหัส QR ของอุปกรณ์ | วิธีที่ 2: วางคำเชิญ |
| --- | --- | --- |
| Windows / macOS (เดสก์ท็อป `--ui` เปิดใช้งานโดยการดับเบิลคลิก) | บนเพจท้องถิ่น ให้เลือก **เพิ่มอุปกรณ์นี้ → รับรหัสการจับคู่** เพื่อแสดงรหัสหกหลักและรหัส QR | วางลงในกล่องข้อความ **Invite** ของเพจท้องถิ่น แล้วคลิก **เข้าร่วมพร้อมคำเชิญ** |
| OpenWrt (luci-app-รีโมท) | ใน LuCI เลือก **Services → Remote Management → เพิ่มอุปกรณ์ → รับรหัสการจับคู่** เพื่อแสดงรหัสหกหลักและรหัส QR | ในหน้าเดียวกัน ให้วางลงใน **Method 2: Invitation Content** แล้วคลิก **Join** |
| Linux / บรรทัดคำสั่งบนทุกแพลตฟอร์ม | `remote-agent pair` แสดงรหัสหกหลักและรหัส QR แบบข้อความในเทอร์มินัล | `remote-agent join '<邀请内容>'` หรือ `remote-agent join -` เพื่ออ่านจากอินพุตมาตรฐาน |

**Method 1**: Agent ขอรหัสหกหลักที่ถูกต้องเป็นเวลา 5 นาที และแสดงรหัส QR ที่มี `remote://pair?code=012345&server=wss%3A%2F%2Fexchange.ivjn.us` (โดยไม่มีข้อมูลรับรอง) ผู้ดูแลระบบอาจเลือกตัวเลือกใดตัวเลือกหนึ่งเหล่านี้:
Android Console **Add อุปกรณ์ → ป้อนรหัสการจับคู่ → สแกนอุปกรณ์ QR code** (สแกนด้วยกล้อง ตรวจสอบเซิร์ฟเวอร์ที่ตรงกัน จากนั้นค้นหาและอนุมัติคำขอ) ป้อนรหัสหกหลักโดยตรง ใช้เว็บ Console **อนุมัติรหัสจับคู่** เพื่อป้อนรหัสหรือวาง `remote://pair?...`; หรือรัน `remote-cli pair 012345` (ซึ่งยอมรับ URI นั้นด้วย) หลังจากอนุมัติแล้ว Agent จะบันทึกโทเค็นและเชื่อมต่อโดยอัตโนมัติ

**Method 2**: ใน Android Console ผู้ดูแลระบบเลือก **Add อุปกรณ์ → เพิ่มโดยการสแกน** เพื่อสร้างคำเชิญแบบครั้งเดียว จากนั้นแตะ **Copy คำเชิญ (วางบนคอมพิวเตอร์ / เราเตอร์) **; หรือรัน `remote-cli qr --device-id pc-01 --text` คำเชิญคือ JSON ที่ฝังอยู่ในโค้ด QR (`{"type":"remote-enrollment",...}`) ซึ่งใช้ได้ 5 นาทีและใช้งานได้ครั้งเดียว เนื้อหาของรหัส QR โทเค็นอุปกรณ์ (`remote-cli device qr`) ก็เป็นที่ยอมรับเช่นกัน

ตำแหน่งที่เก็บข้อมูลและลักษณะการเชื่อมต่อ:

- UI เดสก์ท็อป: เขียนลงในไฟล์การกำหนดค่าปัจจุบัน (โดยค่าเริ่มต้น `%LOCALAPPDATA%\remote-agent\config.json` / `~/.config/remote-agent/config.json`) และเชื่อมต่อทันที
- OpenWrt: เขียน UCI `remote-agent.main` (เซิร์ฟเวอร์ / device_id / โทเค็น `enabled=1`) จากนั้นรีสตาร์ทบริการ procd
- บรรทัดคำสั่ง: ตั้งค่าเริ่มต้นเป็นพาธการกำหนดค่าเดสก์ท็อป (UCI บน OpenWrt) `--config PATH` เลือกไฟล์ JSON `--uci` บังคับใช้ที่เก็บข้อมูล UCI หลังจากบันทึกแล้ว ให้เชื่อมต่อในเบื้องหน้า (`--no-connect` บันทึกเท่านั้น) เริ่มบริการที่มีอยู่ใหม่โดยใช้การกำหนดค่านั้น

ข้อมูลประจำตัวที่มีอยู่ได้รับการปกป้องจากการแทนที่โดยค่าเริ่มต้น: บรรทัดคำสั่งต้องใช้ `--force` ในขณะที่ UI เดสก์ท็อปและ LuCI ขอการยืนยัน วิธีการที่ใช้โทเค็นที่มีอยู่ (`--device-id/--token`, ไฟล์การกำหนดค่า และการตั้งค่า LuCI) ยังคงใช้งานได้

```sh
remote-agent pair                       # 显示六位码 + 二维码，批准后保存并连接
remote-agent pair --server wss://your-exchange.example.com --config ./agent.json
remote-agent join '{"type":"remote-enrollment","version":1,...}'
remote-agent join - < invite.txt --no-connect
```

การจับคู่แบบเนทิฟต้องใช้ `wss://` `ws://` อนุญาตให้ใช้กับลูปแบ็คสำหรับการทดสอบเท่านั้น การจับคู่ Android และ Console ต้องใช้ HTTPS/WSS

## Console เข้าสู่ระบบด้วยรหัสหกหลัก

ในหน้าเข้าสู่ระบบ Android Remote Console ให้แตะ **เข้าสู่ระบบด้วยรหัสหกหลัก** ในเว็บ Console (`/console`) ให้เลือกแท็บ **Six-digit code** ในการ์ดเข้าสู่ระบบและขอรหัสเข้าสู่ระบบ ผู้ดูแลระบบสามารถอนุมัติได้โดยใช้วิธีใดวิธีหนึ่ง:

```powershell
remote-cli pair 012345 --operator-name mobile-alice
# 只读客户端：追加 --role readonly
```

อีกทางหนึ่ง ในเวิร์กสเปซ **Web Console** ที่ได้รับการรับรองความถูกต้องแล้ว ให้คลิก **อนุมัติรหัสการจับคู่** (มองเห็นได้เฉพาะผู้ดูแลระบบเท่านั้น ตัวดำเนินการแบบอ่านอย่างเดียวไม่มีการดำเนินการดังกล่าว) ป้อนรหัสที่แสดงบนหน้าจอของลูกค้ารายอื่น ตรวจสอบประเภทและป้ายกำกับ และอนุมัติ

ตามค่าเริ่มต้น สิ่งนี้จะสร้างบัญชี `operator` แยกต่างหากแทนที่จะคัดลอกโทเค็นของผู้ดูแลระบบ ผู้ดูแลระบบอาจระบุ `--role admin` หรือ `--role readonly` อย่างชัดเจน หลังจากได้รับการอนุญาตแล้ว Android Console จะตรวจสอบข้อมูลประจำตัวอีกครั้ง บันทึกลงใน SecureStore และเปิดรายการอุปกรณ์ เว็บ Console จะเก็บข้อมูลประจำตัวของผู้ปฏิบัติงานไว้ในหน่วยความจำของหน้าปัจจุบัน (เช่นเดียวกับการเข้าสู่ระบบบัญชี/โทเค็น) และเปิดรายการอุปกรณ์ หากยกเลิกหรือไม่สำเร็จ บัญชีที่มีอยู่หรือเข้าสู่ระบบโทเค็นจะยังคงใช้งานได้ และอินพุตที่ป้อนในภายหลังสำหรับวิธีการเข้าสู่ระบบอื่นจะยังคงอยู่

## การสแกนรหัส CLI ด้วย Remote Agent

```powershell
remote-cli qr --device-id my-phone
# 输出 SVG 供手机扫描：
remote-cli qr --device-id my-phone --output ./phone-login.svg
```

สร้างรหัส QR จาก CLI ผู้ดูแลระบบที่ได้รับการรับรองความถูกต้อง บนโทรศัพท์ ให้เปิด Remote Agent แล้วแตะ **สแกนการเชื่อมต่อ QR code** ตรวจสอบเซิร์ฟเวอร์และ ID อุปกรณ์ จากนั้นแตะ **Connect** รหัส QR มีเพียงตั๋วชั่วคราว 256 บิตแบบสุ่ม ใช้ได้ 5 นาทีและผูกเข้ากับอุปกรณ์เครื่องเดียวได้ ไม่มีโทเค็นอุปกรณ์ที่มีอายุการใช้งานยาวนาน หลังจากการสแกน Exchange จะออกโทเค็นอุปกรณ์ที่โทรศัพท์จัดเก็บไว้ใน Keystore ก่อนทำการเชื่อมต่อ รหัส QR ต้องตั้งชื่อรหัสอุปกรณ์ใหม่ มันไม่ได้แทนที่อุปกรณ์ที่มีอยู่หรือหมุนโทเค็นของมัน

การอ้างสิทธิ์จากโทรศัพท์เครื่องเดียวกันจะใช้ `claim_id` แบบสุ่มที่เสถียร ดังนั้นการลองใหม่อีกครั้งหลังจากการเชื่อมต่อล้มเหลวจึงสามารถดึงผลลัพธ์เดียวกันได้ `claim_id` อื่นไม่สามารถรับตั๋วได้อีก หลังจากบันทึกแล้ว โทรศัพท์จะรับทราบว่าตั๋วอาจถูกล้างแล้ว ตั๋วชั่วคราวอยู่ในหน่วยความจำกระบวนการ และกลายเป็นไม่ถูกต้องเมื่อรีสตาร์ท Exchange ผลการอ้างสิทธิ์ที่ถูกเรียกค้นแล้วจะถูกเก็บไว้อีก 5 นาที เพื่อให้ไคลเอ็นต์เดิมสามารถลองอีกครั้งได้

| วิธีการและเส้นทาง | การรับรองความถูกต้อง | วัตถุประสงค์ |
| --- | --- | --- |
| `POST /api/pairing/invite` | ผู้ดูแลระบบ | `{device_id,name?}` สร้างตั๋ว จำกัดไว้ที่ 10 ต่อนาทีต่อผู้ดูแลระบบและ 256 ทั่วโลก |
| `POST /api/pairing/claim` | `Bearer <ticket>` | `{claim_id}` ส่งคืนข้อมูลรับรองอุปกรณ์แยกต่างหาก การลองใหม่ต้องใช้ `claim_id` เลขฐานสิบหก 32 อักขระเดิมซ้ำ |
| `POST /api/pairing/claim/complete` | เช่นเดียวกับข้างต้น | รับทราบการจัดเก็บสำเร็จและล้างตั๋ว |

## การสร้างรหัส QR ของอุปกรณ์

```powershell
# 创建设备，同时在终端显示二维码
remote-cli device add my-android --qr
# 新建 SVG 文件，可在电脑打开后供手机扫描
remote-cli device add another-phone --qr-output ./another-phone.svg
# 使用手里已有的设备令牌，不创建或轮换设备
remote-cli device qr my-android --output ./my-android.svg
# 明确轮换令牌并生成二维码；原令牌立即失效
remote-cli device rotate-token my-android --qr
```

`device qr` อ่านโทเค็นอุปกรณ์ผ่านอินพุตที่ซ่อนอยู่ และยังรองรับ `--token-stdin` อีกด้วย รหัส QR ของอุปกรณ์มีโทเค็นอุปกรณ์เท่านั้น ไม่สามารถใช้โทเค็นการดำเนินงานได้ ไฟล์เอาท์พุตปฏิเสธที่จะเขียนทับไฟล์ที่มีอยู่และมีข้อมูลรับรอง: ปกป้องและลบทิ้งหลังการใช้งาน รหัส QR ต้องใช้ HTTPS/WSS

Android Console จะแสดงโค้ด QR ของอุปกรณ์ทันทีหลังจากสร้างอุปกรณ์ ในรายละเอียดอุปกรณ์ **หมุนโทเค็นและสร้างโค้ด QR** อธิบายผลกระทบจากการขาดการเชื่อมต่อและขอการยืนยันก่อน เซิร์ฟเวอร์จะจัดเก็บเฉพาะแฮชโทเค็นและไม่สามารถกู้คืนโค้ด QR เก่าจากบันทึกอุปกรณ์ที่มีอยู่ได้ ดังนั้นการดูโค้ด QR จะไม่หมุนโทเค็นอย่างเงียบ ๆ

## API การจับคู่ Exchange

| วิธีการและเส้นทาง | การรับรองความถูกต้อง | วัตถุประสงค์ |
| --- | --- | --- |
| `POST /api/pairing/start` | ไม่มี; อัตราจำกัด | ส่ง `kind: device/operator` และ `label`; รับ `code`, `poll_token`, `expires_in: 300` และ `interval: 3` |
| `GET /api/pairing/{code}` | โทเค็นการดำเนินการของผู้ดูแลระบบ | ตรวจสอบประเภทคำขอ ป้ายกำกับ และอายุการใช้งานที่เหลืออยู่ ไม่ส่งคืนข้อมูลประจำตัว |
| `POST /api/pairing/approve` | โทเค็นการดำเนินการของผู้ดูแลระบบ | ส่ง `code`, `kind`, `identity`, ตัวเลือก `name` และ `role` เพื่อสร้างอุปกรณ์หรือบัญชีแยกต่างหาก |
| `POST /api/pairing/poll` | `Authorization: Bearer <poll_token>` | ส่งกลับ `pending` หรือ `approved`; ผลลัพธ์ที่ได้รับอนุมัติประกอบด้วย `credentials.kind/identity/token` |
| `POST /api/pairing/complete` | เช่นเดียวกับข้างต้น | ล้างการอนุญาตชั่วคราวเมื่อไคลเอนต์บันทึกแล้ว ปลอดภัยที่จะโทรซ้ำๆ |
| `GET /ws/pairing` | ไม่มี; อัตราจำกัด | การจับคู่ Agent แบบเนทีฟ WebSocket; รับเหตุการณ์ `code` จากนั้น `approved` หรือ `expired` ส่งข้อความ `complete` หลังจากบันทึก |

รหัสหกหลักช่วยให้ผู้ดูแลระบบที่ได้รับการรับรองความถูกต้องค้นหาและยืนยันคำขอเท่านั้น ไม่สามารถใช้สำรวจหรือรับหนังสือรับรองได้ ข้อมูลรับรองการโพลเป็นความลับแบบสุ่ม 256 บิต และไม่เคยวางไว้ใน URL การอนุมัติที่ซ้ำกันจะถูกปฏิเสธ การสร้างข้อมูลประจำตัวที่ล้มเหลวจะปล่อยการสำรองการอนุมัติเพื่อให้สามารถลองใหม่ได้ ผลลัพธ์ที่ได้รับการอนุมัติสามารถอ่านได้อีกครั้งด้วยข้อมูลรับรองการโพลส่วนตัวเดียวกัน ช่วยป้องกันการสูญเสียข้อมูลประจำตัวอย่างถาวรจากการตอบสนองของเครือข่ายที่ลดลง ลูกค้ารับทราบการหักล้างหลังจากบันทึก

คำขอที่รอการอนุมัติและผลการอนุมัติที่รอการรวบรวมจะถูกเก็บไว้ไม่เกิน 5 นาที หากไม่มี `REDIS_URL` เซสชันชั่วคราวจะคงอยู่ในหน่วยความจำของกระบวนการ Exchange ปัจจุบันเท่านั้น หลังจากรีสตาร์ท ให้ขอรหัสใหม่ และกำหนดเส้นทางคำขอจับคู่ไปยังอินสแตนซ์เดียวกันในการปรับใช้หลายอินสแตนซ์ เมื่อกำหนดค่า Redis รายการจับคู่และตัวนับขีดจำกัดอัตราจะถูกจัดเก็บไว้ใน Redis (สอดคล้องกับ TTL 5 นาที) ทำให้คำขอสามารถเข้าถึงอินสแตนซ์ใดๆ ก็ตามที่จำเป็นต้องมีความสัมพันธ์ของเซสชัน **no** IP ต้นทาง TCP จริงแต่ละรายการอาจขอรหัสได้สูงสุด 10 รหัสต่อนาที ผู้ดูแลระบบอาจดำเนินการค้นหาหรืออนุมัติได้สูงสุด 20 รายการต่อนาที โหมดหน่วยความจำยังมีขีดจำกัดทั่วโลกที่ 256 เซสชันที่รอดำเนินการ IP ไคลเอ็นต์ที่ส่งต่อพร็อกซีไม่ได้รับความเชื่อถือสำหรับการจำกัดอัตรา ผู้ใช้ที่อยู่ด้านหลังพร็อกซีย้อนกลับเดียวกันจะแชร์โควต้าต้นทางของตน การหมดอายุของ TTL และการล้างข้อมูลตามกำหนดเวลาจะลบข้อมูลที่หมดอายุ การตอบสนองตั้งค่า `Cache-Control: no-store` และทั้งความลับในการจับคู่หรือโทเค็นข้อความธรรมดาที่ออกจะไม่ถูกบันทึก

รหัสอุปกรณ์/บัญชีแบ็กเอนด์ที่มีอยู่ไม่สามารถเขียนทับโดยคำขอจับคู่ได้ ผู้ดูแลระบบควรตรวจสอบทั้งรหัสและไคลเอนต์ที่ร้องขอ ไม่อนุมัติรหัสเข้าสู่ระบบที่มาจากการจัดการของบุคคลอื่น

API โค้ดการเชื่อมต่อ: `POST /api/pairing/start` ยอมรับ `device_name` เสริมและส่งคืนชื่อนั้น การค้นหาผู้ดูแลระบบ `GET /api/pairing/{code}` ส่งคืน `device_name` และ `suggested_device_id` ของเวิร์กสเปซปัจจุบัน การค้นหามันไม่ได้จอง ID อุปกรณ์ `identity` ใน `POST /api/pairing/approve` อาจถูกละเว้น ความสำเร็จส่งคืน 200 ด้วย `{identity}` (ID สุดท้าย โดยไม่มีโทเค็น) Native WebSocket `/ws/pairing?device_name=...` รองรับชื่ออุปกรณ์ที่เข้ารหัส URL
