Skip to content

Let a trusted delegator create a session for the person it names - #150

Draft
Hargun3 wants to merge 1 commit into
TangleML:mainfrom
Hargun3:hargun/session-create-delegation
Draft

Hargun3 wants to merge 1 commit into
TangleML:mainfrom
Hargun3:hargun/session-create-delegation

Conversation

@Hargun3

@Hargun3 Hargun3 commented Nov 4, 2026

Copy link
Copy Markdown

Description

Sessions that River creates from Slack are owned by River's service identity (minerva.river@shopify.com), not by the person who asked. So Prime greets "Minerva", and the requester can't use owner-only features such as Local Agents.

This lets a configured service identity create a session for someone else:

  • SESSION_DELEGATORS lists the trusted callers. SESSION_DELEGATE_EMAIL_HEADER names the header that says who the session is for. Delegation is off unless both are set.
  • If the caller (resolved as today, from the bearer token or cookie) is a delegator and the header holds one valid email, that person becomes the session's user. Every other caller, or a delegator that names nobody, is unchanged.
  • This applies to POST /api/sessions only. On every other request the delegator keeps its own identity, so it never gets the owner's privileges, such as minting remote-environment tokens.

Why the header can be trusted

The header has to be set by infrastructure the delegator can't control. For River, that's Aquifer's credentials proxy: its delegation_attribution rule deletes any value the sandbox sent, then sets X-Shopify-Forward-User-Email to the person driving that River session, using Aquifer's own records. World's Usenet already trusts the same mechanism ("Delegated identity" in areas/tools/usenet/docs/identity.md). Only the proxy holds River's login, so a request authenticated as River has always been through it. A person who sends the header with their own login is ignored.

Rollout order matters: the proxy rule for Oasis has to be live before an instance sets these variables. Until then, River could set the header to any value itself.

Screenshots

N/A

How to test

  1. pnpm --filter @tangent/server test: the new src/auth/identity.test.ts covers a delegator naming a person, non-delegators, missing or invalid or multiple values, the off-by-default config, and anonymous callers.
  2. I checked on staging that the header reaches an instance unchanged. River sent it through its credentials proxy, Minerva and the Oasis HTTP proxy to a header-echo server on my own instance. Minerva also sets x-forwarded-email: minerva.river@shopify.com.
  3. End to end, after the proxy rule ships: set SESSION_DELEGATORS=minerva.river@shopify.com and SESSION_DELEGATE_EMAIL_HEADER=x-shopify-forward-user-email, ask River in Slack to start a Tangent session, and check that the session's user is you and Prime greets you.

Notes

  • Draft until the matching World credentials-proxy rule (delegation_attribution for oasis-staging.shopify.io) is agreed with the Aquifer team.
  • The delegated user has no name claims, so Prime addresses them by email.
  • The Oasis project resource is still created by River. That's River's shared project, so it's expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant