Skip to content

feat(data): zero-config dev auth for GraphQLResolver via everywhere view#68

Merged
mackenziemcclaskey merged 11 commits intomainfrom
feat/trident-dev-auth-proxy
May 4, 2026
Merged

feat(data): zero-config dev auth for GraphQLResolver via everywhere view#68
mackenziemcclaskey merged 11 commits intomainfrom
feat/trident-dev-auth-proxy

Conversation

@mackenziemcclaskey
Copy link
Copy Markdown
Collaborator

@mackenziemcclaskey mackenziemcclaskey commented Apr 30, 2026

Summary

  • Renamed TridentResolver to GraphQLResolver — same interface, cleaner name that reflects what it actually does
  • GraphQLResolver accepts an optional endpoint argument; when omitted it defaults to /api/data/graphql on the current origin (safe in both browser and Node/SSR environments)
  • everywhere view now proxies /api/data/graphql to the real API server and injects the stored bearer token only when the incoming request carries no existing auth (no Authorization header and no we_session cookie) — so the WE-NEXT shell's session is respected and never overwritten
  • --mock-data flag default flipped to false — real API is used by default when credentials are present; mock mode is opt-in
  • Removed the old /_we/trident proxy middleware
  • README updated to reference GraphQLResolver throughout and document auth login as step 1 of the data connection flow
  • Fixed cli/package.json name field (@workday/wdcli-plugin-everywhere@workday/everywhere) so npx @workday/everywhere init resolves correctly — oclif was failing to find the plugin because the name didn't match what's installed

Test plan

  • just test — all 306 tests pass
  • just check — typecheck + lint clean
  • everywhere auth login, then everywhere view in a plugin directory — confirm requests reach the real GraphQL endpoint with the bearer token injected
  • With an active WE-NEXT shell session (we_session cookie present), confirm the stored token is NOT injected (existing auth is preserved)
  • Confirm no Authorization header is sent when no token is configured
  • npx @workday/everywhere init — confirm the command resolves without "command everywhere:init not found"

🤖 Generated with Claude Code

Mackenzie Fernandez and others added 6 commits April 30, 2026 10:19
During local development, TridentResolver now defaults to posting
through a /_we/trident proxy instead of calling Trident directly.
The dev proxy (added to the Vite plugin in 'everywhere view') reads
gateway and token from the auth login config at request time, so no
credentials are needed in plugin source code.

- TridentResolver constructor is now (referenceId, schemas, options?)
  where options.endpoint and options.bearerToken are optional overrides
- Explicit endpoint/bearerToken still accepted for production use
- /_we/trident middleware proxies to the configured gateway, returning
  a 401 with a login instruction if no token is stored
- Updated README to document auth login as step 1 of the data flow
- Auth error messages now direct users to run auth login instead of
  editing plugin source

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…via view

When `everywhere view` starts the dev server, it reads the auth config
written by `everywhere auth login` and injects __WE_TRIDENT_ENDPOINT__ and
__WE_TRIDENT_TOKEN__ into the HTML as inline globals via transformIndexHtml.
TridentResolver picks these up at construction time so developers no longer
need to hardcode credentials in their plugin source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- view.ts: adopt updated EverywhereBaseCommand import path from lib/command.js
- README: include `route` in TridentResolver example import

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…proxy

When everywhere view proxies requests to the real Trident API, respect any
Authorization header or session cookie already on the incoming request (e.g.
from WE-NEXT) instead of unconditionally overwriting with the stored config
token. Falls back to the stored token only when no auth is present.

Also removes the now-dead /_we/trident proxy path — TridentResolver sends
requests directly to /api/data/graphql which is handled by the Vite proxy
in non-mock mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The WIP commit dropped node_modules/tokens/theme.css from the
css-node-import-plugin fixture, breaking the bundler test that checks
@import resolution from node_modules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@jheddings jheddings left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posting the critical findings from a thorough review here as inline comments. There are also several non-blocking concerns and suggestions (e.g. PR description vs. implementation drift, mock-data default, import type consistency, globalThis.window test teardown, window.location.origin baked at construction, missing integration test for the proxy hook) — happy to follow up with those separately if useful.

Comment thread cli/tests/build/fixtures/css-node-import-plugin/package-lock.json Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
- Remove fixture package-lock.json that contained private Workday
  Artifactory registry URLs, violating the public OSS guardrail
- Fix README prose: resolver uses window.location.origin/api/data/graphql,
  not /_we/trident (that proxy path was removed in f42949c)
- Remove README production-override example that passed a third options
  argument to TridentResolver, which only accepts two parameters

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread cli/src/commands/everywhere/view.ts Outdated
Comment thread tests/data/TridentResolver.test.ts Outdated
(globalThis as Record<string, unknown>)['window'] = {
location: { origin: 'https://tenant.workday.com' },
};
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This beforeEach overwrites globalThis.window for every test in the file, but there's no matching afterEach to restore it. Vitest doesn't isolate global-object mutations across files in the same worker by default, so if any later test file relies on happy-dom's real window, behavior becomes order-dependent.

Small fix using vitest's stub helpers:

beforeEach(() => {
  vi.stubGlobal('window', { location: { origin: 'https://tenant.workday.com' } });
});
afterEach(() => {
  vi.unstubAllGlobals();
});

or stash and restore the original explicitly.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we could drop the explicit dependency on the window global in the TridentResolver class and accept host as a constructor argument instead. This way, you don't have to worry about managing state in the tests, making them less brittle.

- Use vi.stubGlobal/vi.unstubAllGlobals in TridentResolver tests to
  prevent globalThis.window leaking across test files in the same worker
- Flip --mock-data default to false so everywhere view hits the real API
  after auth login, matching README docs and developer expectations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread cli/src/data/proxy-auth.ts Outdated
Comment thread cli/src/commands/everywhere/view.ts Outdated
Comment thread src/data/TridentResolver.ts Outdated
Comment thread src/data/TridentResolver.ts Outdated
Comment thread src/data/TridentResolver.ts Outdated
Comment thread tests/data/TridentResolver.test.ts Outdated
(globalThis as Record<string, unknown>)['window'] = {
location: { origin: 'https://tenant.workday.com' },
};
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we could drop the explicit dependency on the window global in the TridentResolver class and accept host as a constructor argument instead. This way, you don't have to worry about managing state in the tests, making them less brittle.

Comment thread src/data/TridentResolver.ts Outdated
this.endpoint = `${endpoint}${path}`;
this.bearerToken = bearerToken; // look at config file for bearer token
constructor(referenceId: string, schemas: Record<string, ModelSchema>) {
this.endpoint = `${window.location.origin}/api/data/graphql`;
this.referenceId = referenceId;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concern — browser-only assumption baked at construction. window.location.origin is referenced unconditionally in the constructor, so:

  • Importing/instantiating this class in any non-DOM context (Node test runner without happy-dom, SSR, a Worker without location, a build-time codegen step) throws ReferenceError: window is not defined before the caller can do anything about it.
  • The endpoint is frozen at construction. A consumer that wants to point at a different gateway in production (different region, multi-tenant routing, an embedded sandbox) has no escape hatch — the README/PR description claim TridentResolverOptions provides one, but it doesn't exist.

Accepting an optional endpoint (or host) on the constructor — defaulting to globalThis.window?.location.origin + '/api/data/graphql' resolved lazily inside execute() — would address both, and dovetails with @mpfilbin's suggestion on the test file.

Comment thread cli/src/data/proxy-auth.ts Outdated
Comment thread cli/tests/data/proxy-auth.test.ts
Mackenzie Fernandez and others added 2 commits May 4, 2026 11:41
Proxy auth:
- Replace resolveProxyAuth with isUnauthenticated predicate for clarity
- Check specifically for we_session cookie instead of any cookie, to avoid
  unrelated localhost cookies suppressing bearer token injection
- Add precedence test and unrelated-cookie test to proxy-auth suite

GraphQLResolver (renamed from TridentResolver):
- Rename class to GraphQLResolver — Trident is an internal codename
- Accept optional endpoint constructor arg so non-browser environments and
  tests don't need to mock window; defaults to window.location.origin at
  runtime via globalThis.window?.location.origin
- Remove wd-graphql-developer-info and x-api-gateway-originator headers
- Export deprecated TridentResolver alias for backwards compat

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The CLI package was named @workday/wdcli-plugin-everywhere (a legacy
internal wdcli identity). oclif resolves command IDs by looking for the
plugin name in node_modules. Because only @workday/everywhere is
installed, every command lookup failed with "command everywhere:X not
found". Renaming the package to @workday/everywhere fixes the resolution
path and removes spurious hidden:true flags from the regenerated manifest.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread cli/package.json
{
"name": "@workday/wdcli-plugin-everywhere",
"description": "wdcli plugin for managing Workday Everywhere plugins",
"name": "@workday/everywhere",
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BUG FIX: This was previously "@workday/wdcli-plugin-everywhere" (a legacy internal identity). oclif resolves command IDs by searching node_modules for the plugin name at runtime. Because only "@workday/everywhere" is installed, every command lookup failed with "command everywhere:X not found". Correcting the name here also removes spurious hidden flags from all user facing commands in the regenerated manifest.

@mackenziemcclaskey mackenziemcclaskey changed the title feat(data): zero-config dev auth for TridentResolver via everywhere view feat(data): zero-config dev auth for GraphQLResolver via everywhere view May 4, 2026
Drops the deprecated TridentResolver re-export entirely and updates all
README references to use GraphQLResolver instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mackenziemcclaskey mackenziemcclaskey merged commit 8a5e8fc into main May 4, 2026
2 checks passed
@mackenziemcclaskey mackenziemcclaskey deleted the feat/trident-dev-auth-proxy branch May 4, 2026 20:22
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.

3 participants