#22312: Fix legacy paired metadata handling for reconnect scope compatibility
gateway
size: S
Cluster:
Device Pairing and Gateway Fixes
## Summary
- Problem: `sessions_history` can fail with `pairing required` for already paired devices when reconnect metadata is partially missing from older pair records.
- Why it matters: cross-agent workflows are blocked even though the session token is valid and role/scope capability is effectively unchanged.
- What changed: treat paired entries with missing `roles` **or** missing `scopes` as legacy metadata during handshake upgrades, so they are repaired on reconnect instead of forcing pairing.
- What did NOT change: normal role/scope upgrade enforcement for fully populated pair metadata.
## Change Type
- [x] Bug fix
## Scope
- [x] Gateway / orchestration
- [x] Auth / tokens
## Linked Issue/PR
- Closes #22160
## User-visible / Behavior Changes
Paired devices with incomplete historical metadata reconnect successfully on role/scope-compatible calls without prompting for re-pairing.
## Security Impact
- New permissions/capabilities? `No`
- Secrets/tokens handling changed? `No`
- New/changed network calls? `No`
- Command/tool execution surface changed? `No`
- Data access scope changed? `No`
- If any `Yes`, explain risk + mitigation: `Not applicable`
## Repro + Verification
### Environment
- Runtime/container: local macOS dev
- OS: local
- Model/provider: not applicable
- Integration/channel (if any): gateway auth/e2e
### Steps
1. Connect first time with a device and record paired metadata.
2. Remove one metadata field (either `roles` or `scopes`) from stored pair record.
3. Reconnect with valid token and compatible role/scope.
4. Confirm reconnect succeeds and metadata is repaired.
### Expected
Reconnect succeeds without pairing prompt.
### Actual
When partial metadata was missing, reconnect previously forced pairing.
## Evidence
- [x] Passing tests: `pnpm test:e2e src/gateway/server.auth.e2e.test.ts`
## Human Verification (required)
- Verified scenarios:
- Existing paired device with `scopes` removed from metadata reconnects successfully.
- Edge cases checked:
- Existing e2e coverage for fully missing role+scope metadata still passes.
- What you did not verify:
- Real-device production reconnection in an active multi-agent deployment.
## Compatibility / Migration
- Backward compatible? `Yes`
- Config/env changes? `No`
- Migration needed? `No`
## Risks and Mitigations
- Risk: legacy detection is intentionally conservative and applies only when metadata is incomplete.
- Mitigation: full metadata paths still enforce current role/scope upgrade checks; only repairs are applied for partial legacy compatibility.
## Confidence Score
- **5/5**
- The change is narrowly scoped and aligns with existing legacy-repair behavior already exercised by e2e tests. It restores backwards compatibility for pre-change pair records, with minimal behavioral surface area and no permission-model changes.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Changes the legacy paired metadata detection from requiring **both** `roles` and `scopes` to be missing (using `&&`) to detecting when **either** is missing (using `||`). This allows devices with partial historical metadata to reconnect and have their metadata repaired automatically instead of being forced to re-pair. The fix aligns with the existing legacy repair behavior at line 765-773 where `updatePairedDeviceMetadata` repairs missing metadata on reconnect. A new test validates reconnection with only `scopes` removed, complementing the existing test that removes both fields.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The change is a one-character operator modification (`&&` to `||`) with clear intent and comprehensive test coverage. The logic change expands the legacy detection condition conservatively - it still requires metadata incompleteness to trigger repair mode, and the subsequent `updatePairedDeviceMetadata` call (line 765-773) repairs the missing fields. The new test specifically validates the partial-metadata scenario (missing `scopes` only), and existing tests confirm the both-missing case still works correctly
- No files require special attention
<sub>Last reviewed commit: 34d52ca</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#21664: fix(gateway): require re-pairing for legacy devices that lack scope...
by AI-Reviewer-QS · 2026-02-20
87.1%
#23690: fix(gateway): subagent sessions fail with pairing required on loopb...
by yinghaosang · 2026-02-22
79.1%
#22280: fix(gateway): silently auto-approve local paired-device scope upgrades
by abhishekp76 · 2026-02-21
78.9%
#16827: fix: allow device tokens with empty scopes to accept requested scopes
by MisterGuy420 · 2026-02-15
78.8%
#23503: fix: preserve pairing state on device token mismatch + migrate lega...
by dorukardahan · 2026-02-22
78.6%
#17425: fix(gateway): auto-approve scope/role upgrades for already-paired d...
by sauerdaniel · 2026-02-15
78.2%
#23708: fix(gateway): auto-approve scope upgrades for loopback clients
by widingmarcus-cyber · 2026-02-22
78.0%
#6846: fix: bridge node.pair.* tools to device pairing store
by cortexuvula · 2026-02-02
75.9%
#22587: fix(gateway): silently auto-approve local paired-device scope upgrades
by abhishekp76 · 2026-02-21
75.3%
#22081: [Bug]: Preserve approved scope baseline through token rotation
by AIflow-Labs · 2026-02-20
75.3%