( opts: HttpServerOptions, bearer: string, )
| 308 | * re-probes once the backend recovers. |
| 309 | */ |
| 310 | export async function resolvePrincipal( |
| 311 | opts: HttpServerOptions, |
| 312 | bearer: string, |
| 313 | ): Promise<{ value: ResolvedPrincipal; cacheable: boolean }> { |
| 314 | // The probe only calls whoami; its scope/agent don't matter. Build it bare |
| 315 | // (factory(bearer) with no resolved opts) so the construction is |
| 316 | // distinguishable from the final, resolved client. |
| 317 | const probe = opts.clientFactory |
| 318 | ? opts.clientFactory(bearer) |
| 319 | : new McpClient(new E2AClient({ apiKey: bearer, baseUrl: opts.baseUrl }), "", "account"); |
| 320 | try { |
| 321 | const me = await probe.whoami(); |
| 322 | const scope: Scope = me.scope === "account" ? "account" : "agent"; |
| 323 | const agentEmail = scope === "agent" && me.agentAddress ? me.agentAddress : undefined; |
| 324 | return { value: { scope, ...(agentEmail ? { agentEmail } : {}) }, cacheable: true }; |
| 325 | } catch (err) { |
| 326 | if (isUnauthorizedError(err)) { |
| 327 | throw new InvalidBearerError(); |
| 328 | } |
| 329 | // Fail-closed: least-privilege runtime tier, no default agent, not cached. |
| 330 | return { value: { scope: "agent" }, cacheable: false }; |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | function isUnauthorizedError(err: unknown): boolean { |
| 335 | if (!err || typeof err !== "object") return false; |
no test coverage detected