Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/mobile
Steps to reproduce
- Access a T3 environment from the iOS app using a saved Tailscale connection.
- On the host, run
t3 connect link --publish-onlyand complete authorization. - Start/restart T3 to provision the publish-only link.
- Run
t3 connect status: the environment link is provisioned and agent activity publishing is enabled (output below). - In the mobile app, open Settings → Notifications. Device Notifications is enabled.
- Turn on Live Activity Updates.
The intention is to use Tailscale for environment access and T3 Connect only for activity publishing, without a managed tunnel.
Expected behavior
Live Activity Updates can be enabled for an environment already linked in publish-only mode, without requiring a managed tunnel. The CLI explicitly describes --publish-only as publishing agent activity with no managed tunnel, with Tailscale as an example of out-of-band access.
Actual behavior
The app shows a dialog titled “Live Activities unavailable”:
“Could not obtain environment link proof: Invalid managed endpoint origin.”
Live Activity Updates remains off, despite the environment link being provisioned and agent activity publishing enabled.
Impact
Minor bug or occasional failure
Version or commit
Server/CLI: t3 v0.1.7; iOS app: 2.2.0
Environment
iPhone with T3 Code mobile 2.2.0; environment accessed over Tailscale. Host CLI: t3 v0.1.7. Publish-only Connect link; no managed tunnel requested. Exact iOS version not recorded.
Logs or stack traces
t3 connect status
T3 Connect
Exposure: enabled
Authorization: stored credential
Environment link: provisioned
Relay: https://relay.t3.codes
Publish agent activity: enabled
Relay client: not installedScreenshots, recordings, or supporting files
f92ffff5-ed20-4d72-92d5-f980d0b000af-3f9ed1b4-c8f3-45bc-af2e-a50a006f036d.jpg
Workaround
No verified workaround preserving the publish-only/Tailscale setup.
Possible cause (source inspection only; not confirmed against the installed app): enabling Live Activities calls linkEnvironmentToCloudWithPreference, which requests managedTunnelsEnabled: true and obtains a link proof through the saved connection URL. The server validates loopback origins for this proof. This may explain the origin error over Tailscale instead of reusing the existing publish-only link.
Source references at 4b87a45:
- CLI:
t3code/apps/server/src/cli/connect.ts
Lines 631 to 634 in 4b87a45
publishOnly: Flag.Boolean("publish-only").pipe( Flag.withDescription( "Link to publish agent activity only, with no managed tunnel. Reach this environment out of band (e.g. Tailscale).", ), - Mobile preference update: https://github.com/pingdotgg/t3code/blob/4b87a45770d24a47f7e6bc40e3f19011e41c7724/apps/mobile/src/features/agent-awareness/liveActivityPreferences.ts
- Mobile linking:
t3code/apps/mobile/src/features/cloud/linkEnvironment.ts
Lines 174 to 215 in 4b87a45
const challenge = yield* relayClient .createEnvironmentLinkChallenge({ clerkToken: input.clerkToken, payload: { notificationsEnabled: true, liveActivitiesEnabled, managedTunnelsEnabled: true, }, }) .pipe( Effect.mapError( decodedRelayClientError(`${relayUrl}/v1/client/environment-link-challenges failed`), ), ); const environmentClient = yield* makeEnvironmentHttpApiClient(input.connection.httpBaseUrl); const proof = yield* environmentClient.connect .linkProof({ headers: { authorization: `Bearer ${localBearerToken}` }, payload: { challenge: challenge.challenge, relayIssuer: relayUrl, endpoint: { httpBaseUrl: input.connection.httpBaseUrl, wsBaseUrl: input.connection.wsBaseUrl, providerKind: MANAGED_ENDPOINT_PROVIDER_KIND, }, origin: endpointOrigin(input.connection.httpBaseUrl), }, }) .pipe(Effect.mapError(cloudEnvironmentLinkError("Could not obtain environment link proof."))); const link = yield* relayClient .linkEnvironment({ clerkToken: input.clerkToken, payload: { deviceId, proof, notificationsEnabled: true, liveActivitiesEnabled, managedTunnelsEnabled: true, }, }) .pipe( - Origin validation:
t3code/apps/server/src/cloud/linkChecks.ts
Lines 82 to 99 in 4b87a45
export function isAllowedEndpointOrigin(input: { readonly origin: RelayManagedEndpointOrigin; readonly requestUrl: string; readonly allowNonLoopbackRequestHost?: boolean; }): boolean { if (!isLoopbackHostname(input.origin.localHttpHost)) { return false; } const url = new URL(input.requestUrl); if (!input.allowNonLoopbackRequestHost && !isLoopbackHostname(url.hostname)) { return false; } return input.origin.localHttpPort === endpointRequestPort(url); } export function isSupportedLinkProviderKind(request: RelayLinkProofRequest): boolean {
Activity