feat(gateway): attribute prompts to authenticated users#111207
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1e9af6588
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ...(params.client?.authenticatedUserId | ||
| ? { sender: { id: params.client.authenticatedUserId } } | ||
| : {}), |
There was a problem hiding this comment.
Persist the attributed recorder in agent runtimes
When an authenticated client invokes the agent RPC, this attributed recorder is only forwarded through ingressOpts.userTurnTranscriptRecorder; the normal embedded runtime unconditionally creates a different recorder in src/agents/command/run-embedded-attempt.ts:151, while the ACP path constructs its own userInput in src/agents/command/acp-execution.ts:198, so neither persists this senderId. Consequently agent-RPC prompts remain unattributed in actual transcripts—the added test only verifies the mocked ingress argument. Please make both runtime persistence paths consume the prepared recorder or otherwise carry its sender metadata through.
Useful? React with 👍 / 👎.
|
Merged via squash.
|
What Problem This Solves
On a shared gateway, prompts from different teammates are indistinguishable in session transcripts — everything reads as one anonymous operator. The persisted user-turn store already supports durable, opt-in
senderattribution (built for channel senders like Telegram), but gateway clients never populate it.Part of the multiplayer-identity program: #111133 (PR "attribution" of the train; builds on #111179).
Why This Change Was Made
When an identified gateway client (trusted-proxy/Tailscale-authenticated) submits a prompt, the gateway now stamps the existing
UserTurnInput.senderfield with the connection's identity (sender: { id: authenticatedUserId }) on both the chat and agent execution paths. The Control UI renders a small attribution label on prompt bubbles via a newformatSenderLabelhelper (display name → username → email local part → opaque id), so labels upgrade automatically once durable profile ids replace emails.Scope lines held deliberately:
senderIsOwnersemantics untouched (admin-scope-derived, verified before changing nothing).User Impact
Shared-gateway teams see who asked what in session transcripts. Single-user and token/password gateways see zero change.
Evidence
node scripts/run-vitest.mjs src/gateway/server.chat.gateway-server-chat-b.test.ts— 87 tests, incl. two identified senders + one unidentified in a single session.node scripts/run-vitest.mjs src/gateway/server-methods/agent.test.ts— 246 tests (agent-path attribution).node scripts/run-vitest.mjs src/sessions/user-turn-transcript.test.ts— 36 tests (durable persistence unchanged semantics).node scripts/run-vitest.mjs ui/src/lib/chat/message-normalizer.test.ts ui/src/pages/chat/components/chat-message.test.ts— 138 tests (label precedence + rendering).Production diff is 42 insertions / 1 deletion; the rest is tests.