chore: close yonexus pairing follow-ups
This commit is contained in:
@@ -22,9 +22,9 @@ This document defines the systematic test coverage for pairing and authenticatio
|
||||
| PF-05 | Empty pairing code | Client submits empty string | `pair_failed(invalid_code)` | ✅ |
|
||||
| PF-06 | Malformed pair_confirm payload | Missing required fields | Protocol error, no state change | ✅ |
|
||||
| PF-07 | Double pairing attempt | Client calls pair_confirm twice | Second attempt rejected if already paired | ✅ |
|
||||
| PF-08 | Pairing during active session | Paired client tries to pair again | Reject, maintain existing trust | ⬜ |
|
||||
| PF-08 | Pairing during active session | Paired client tries to pair again | Reject, maintain existing trust | ✅ |
|
||||
| PF-09 | Server restart during pairing | Server restarts before confirm | Pairing state preserved, code still valid | ✅ |
|
||||
| PF-10 | Client restart during pairing | Client restarts before submit | Client must restart pairing flow | ⬜ |
|
||||
| PF-10 | Client restart during pairing | Client restarts before submit | Client must restart pairing flow | ✅ |
|
||||
|
||||
---
|
||||
|
||||
@@ -134,7 +134,7 @@ npm test -- failure-paths
|
||||
|
||||
- AF-04 (`invalid_secret`) 仍未单独覆盖:现有实现把“错误 secret 导致的验签失败”统一落到 `invalid_signature`,是否拆分错误码仍待确认。
|
||||
- RP-04(key rotation)当前仍视为 v2+ 议题;v1 尚未承诺“无重配对换 key”语义,因此暂不强行补测试。
|
||||
- 本轮已补齐 AF-01/02/03/05/06/09/10/11、RP-01/02、CF-01/02/03/04/05/07、HF-01/02、PF-09、SR-01/02/03/04/05/06。
|
||||
- 本轮已补齐 AF-01/02/03/05/06/09/10/11、RP-01/02、CF-01/02/03/04/05/07、HF-01/02、PF-08/09/10、SR-01/02/03/04/05/06。
|
||||
|
||||
### Adding New Test Cases
|
||||
|
||||
|
||||
@@ -528,6 +528,56 @@ describe("YNX-1105b: Pairing Failure Paths", () => {
|
||||
});
|
||||
|
||||
describe("Edge Cases", () => {
|
||||
it("PF-08: pairing attempt during an active paired session is rejected without losing trust", async () => {
|
||||
const store = createMockStore([{
|
||||
identifier: "client-a",
|
||||
pairingStatus: "paired",
|
||||
publicKey: "existing-key",
|
||||
secret: "existing-secret",
|
||||
status: "online",
|
||||
recentNonces: [],
|
||||
recentHandshakeAttempts: [],
|
||||
createdAt: now - 1000,
|
||||
updatedAt: now - 10,
|
||||
pairedAt: now - 500,
|
||||
lastAuthenticatedAt: now - 5,
|
||||
lastHeartbeatAt: now - 5
|
||||
}]);
|
||||
const { transport, sent } = createMockTransport();
|
||||
const runtime = createYonexusServerRuntime({
|
||||
config: {
|
||||
followerIdentifiers: ["client-a"],
|
||||
notifyBotToken: "test-token",
|
||||
adminUserId: "admin",
|
||||
listenHost: "127.0.0.1",
|
||||
listenPort: 8787
|
||||
},
|
||||
store,
|
||||
transport,
|
||||
now: () => now
|
||||
});
|
||||
|
||||
await runtime.start();
|
||||
|
||||
const conn = createConnection("client-a");
|
||||
await runtime.handleMessage(conn, encodeBuiltin(buildPairConfirm(
|
||||
{ identifier: "client-a", pairingCode: "NEW-PAIR-CODE" },
|
||||
{ timestamp: now }
|
||||
)));
|
||||
|
||||
const lastMessage = decodeBuiltin(sent.at(-1)!.message);
|
||||
expect(lastMessage.type).toBe("pair_failed");
|
||||
expect((lastMessage.payload as PairFailedPayload).reason).toBe("internal_error");
|
||||
|
||||
const record = runtime.state.registry.clients.get("client-a");
|
||||
expect(record).toMatchObject({
|
||||
pairingStatus: "paired",
|
||||
secret: "existing-secret",
|
||||
publicKey: "existing-key",
|
||||
status: "online"
|
||||
});
|
||||
});
|
||||
|
||||
it("handles concurrent pair_confirm from different connections with same identifier", async () => {
|
||||
const store = createMockStore();
|
||||
const { transport, sent } = createMockTransport();
|
||||
|
||||
Reference in New Issue
Block a user