feat(v2): Connectors page + nav rail entry - #1290
Conversation
Pure wiring over existing routes: GET /api/integrations/user/all, POST /api/integrations (telegram auto-mints connectCode), PATCH /:id (config.liveRelay persists since the schema declared it in #1282). Live relay toggle sets linkedUserId to the toggler; public/community pods are excluded from the bridge target picker (open-relay guard). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pc6nGXRS8mHvrwcXMSRDK
|
UX / design-system pass at Blockers
Nits
|
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pc6nGXRS8mHvrwcXMSRDK
|
Change request at Blocking —
|
… copy, locales Per sprint-review on #1290: PATCH /api/integrations/:id now rejects any client-supplied config.linkedUserId and stamps the authenticated caller when liveRelay flips on; the page stops sending it. Per ux-lead: copy says private chat (matching #1289's gate), connectors.* locale entries added for en + zh-CN, and the pod select reuses .v2-byo__input. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pc6nGXRS8mHvrwcXMSRDK
|
Both blockers addressed at the new head:
|
gated the inbound half Finding 1's amendment said "shouldEscalate plus liveRelay defaulting to false are the whole bound", and the closing section restated it. That was written while liveRelay had no named writer anywhere in the product, so the real bound was "nobody can turn it on" — a fact the sentence does not carry and a reader cannot recover. Both halves have since moved, in opposite directions: - #1290 (e35d89e) ships the Connectors page. V2ConnectorsPage.tsx:117 PATCHes {liveRelay} and integrations.ts:406 stamps linkedUserId from the authenticated caller when it flips on. Mode 4 is now reachable by an ordinary user path. - #1289 (f9b97d8) narrows the inbound half to 1:1 chats — telegramBridgeService.ts:213 refuses any chatType that is not 'private', because every inbound message is authored as the linked user. Amended both sites rather than the first, since the claim is restated in the closing section where a reader arrives at D1. Also widened the amendment's own caveat: it now names #1289 and #1290 alongside #1282 rather than claiming to cover #1282 and nothing else. D1's naming decision is unaffected. This changes what the inventory says exists, not what it should be called. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…user/all (#1299) * fix(integrations): drop unregistered platformIntegration populate in user/all The platformIntegration virtual resolves to the TelegramIntegration model, which isn't registered at boot, so any call to GET /api/integrations/user/all 500s (MissingSchemaError). The Connectors page (#1290) is the first UI to call it. The field is unused by every caller; drop the populate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pc6nGXRS8mHvrwcXMSRDK * fix(integrations): rate-limit the user/all listing (CodeQL js/missing-rate-limiting) Same token-hash/IP keying as routes/messages.ts read limiter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013pc6nGXRS8mHvrwcXMSRDK --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Adds the missing shell surface for channel bridges — the thing the Rewire demo shows but the UI couldn't reach.
/v2/connectorsroute + nav rail item (plug icon, between Community and Settings)/commonly-enable <code>instructionconfig.liveRelayand stampslinkedUserIdto the toggler (bridge attribution identity)4 RTL tests: list render + enable code, PATCH shape on toggle, public-pod exclusion, create POST shape.
🤖 Generated with Claude Code
https://claude.ai/code/session_013pc6nGXRS8mHvrwcXMSRDK