Skip to content

Add scope owner NyxID schedule auth#2253

Open
louis4li wants to merge 17 commits into
feature/integratefrom
fix/2026-06-18-owner-nyxid-schedule-auth
Open

Add scope owner NyxID schedule auth#2253
louis4li wants to merge 17 commits into
feature/integratefrom
fix/2026-06-18-owner-nyxid-schedule-auth

Conversation

@louis4li

@louis4li louis4li commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add backend-owned Studio NyxID login finalization so Aevatar exchanges the authorization code, receives the real binding_id, and queues durable nyxid::<userId> -> binding_id persistence through Channel.Identity.
  • Return honest binding dispatch ACK semantics (bindingDispatchAccepted) from finalization; binding readmodel visibility remains eventually consistent and schedule create/update validates the durable binding readmodel.
  • Change scope-owner schedule create/update to validate an existing durable owner binding and persist only scopeOwnerNyxId.OwnerSubject; schedule APIs no longer derive or commit bindings from bearer-token claims.
  • Preserve scheduled dispatch behavior: owner schedules exchange owner credentials per fire, Lark/channel schedules keep sender NyxID binding flow, and durable sender bearer-token schedules do not broker-exchange per fire.
  • Expose backend NyxID login config for the frontend to start OAuth with the backend broker client id.

Fixes #2250

Follow-up

  • Frontend callback integration is intentionally out of this backend PR and tracked in Align Console NyxID login client with backend finalization #2303. The frontend should consume /api/auth/nyxid/config and finalize login through /api/auth/nyxid/finalize so the OAuth authorize client id matches backend token exchange.
  • Because finalization returns accepted-dispatch semantics, frontend schedule creation should handle brief eventual-consistency lag if the binding readmodel is not visible immediately after login finalization.

Test plan

  • dotnet test test/Aevatar.Studio.Tests/Aevatar.Studio.Tests.csproj --nologo --filter NyxId --consoleLoggerParameters:ErrorsOnly — passed, 47 tests
  • dotnet test test/Aevatar.GAgentService.Tests/Aevatar.GAgentService.Tests.csproj --nologo --filter \"ScheduledDispatchApplicationServiceTests|ScheduledDispatchServiceInvocationTests\" --consoleLoggerParameters:ErrorsOnly — passed, 69 tests
  • dotnet test test/Aevatar.GAgentService.Integration.Tests/Aevatar.GAgentService.Integration.Tests.csproj --nologo --filter GAgentServiceHostingServiceCollectionExtensionsTests --consoleLoggerParameters:ErrorsOnly — passed, 22 tests
  • dotnet test test/Aevatar.GAgentService.Integration.Tests/Aevatar.GAgentService.Integration.Tests.csproj --nologo --filter FullyQualifiedName~ScheduledDispatchEndpointsTests --consoleLoggerParameters:ErrorsOnly — passed, 33 tests
  • bash tools/ci/test_stability_guards.sh — passed
  • bash tools/ci/coverage_quality_guard.sh — passed, filtered coverage line 89.8% / branch 73.1%
  • pnpm --dir apps/aevatar-console-web install --frozen-lockfile and pnpm --dir apps/aevatar-console-web tsc — passed before frontend changes were removed from this PR

🤖 Generated with Claude Code

Allow scheduled workflow service invocations to mint NyxID tokens from the authoritative scope owner identity while preserving explicit delegated sender auth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0920a24ae9

ℹ️ 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".

Comment on lines +78 to +83
if (dispatch.Auth.ScopeOwnerNyxId != null)
{
return ExchangeScopeOwnerNyxIdAsync(
dispatch.Auth.ScopeOwnerNyxId,
dispatch.Request.Identity,
ct);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route scope-owner tokens into owner credential fields

When ScopeOwnerNyxId is selected here, the owner token is fed into the same enrichment path as SenderNyxId and is later written only to ChatRequestEvent.LlmControl.SenderNyxIdAccessToken unless the schedule kind is Workflow. For generic service-invocation schedules created via /api/schedules, this means scope-owner auth never populates LlmControl.NyxIdAccessToken/NyxIdOrgToken, which downstream tool context treats as the owner credential, so scheduled service invocations that request scope-owner auth still run without owner NyxID credentials. Preserve the credential source kind through enrichment and put scope-owner tokens in the owner credential fields.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in db14b52 and covered by the follow-up tests in 2abc411. Scope-owner NyxID exchanges now route the token into owner credential fields (LlmControl.NyxIdAccessToken / NyxIdOrgToken) instead of SenderNyxIdAccessToken, while workflow caller projection still uses the exchanged token for connector authorization.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Follow-up pushed in 31dd50c after re-review. In addition to the earlier dispatch fix (scope-owner tokens now populate LlmControl.NyxIdAccessToken / NyxIdOrgToken instead of sender credentials), scope-owner schedules now require a persisted owner subject at the application/workflow boundary, and the HTTP owner resolver no longer treats scope_id as a NyxID user subject. Added regression coverage for distinct scope_id vs uid/sub claims and missing owner subject rejection.

@codecov

codecov Bot commented Jun 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.28358% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.07%. Comparing base (90ea572) to head (754b5ed).
⚠️ Report is 261 commits behind head on feature/integrate.

Files with missing lines Patch % Lines
.../Endpoints/Schedules/ScheduledDispatchEndpoints.cs 92.00% 2 Missing and 4 partials ⚠️
...tService.Core/Schedules/ScheduledDispatchGAgent.cs 86.11% 0 Missing and 5 partials ⚠️
...chedules/ScheduledServiceInvocationDispatchPort.cs 95.31% 1 Missing and 2 partials ⚠️
...astructure/Schedules/ScheduledDispatchActorPort.cs 88.88% 0 Missing and 2 partials ⚠️
...n/Schedules/WorkflowScheduleConfigurationMapper.cs 90.00% 1 Missing and 1 partial ⚠️
@@                  Coverage Diff                  @@
##           feature/integrate    #2253      +/-   ##
=====================================================
- Coverage              84.08%   84.07%   -0.02%     
=====================================================
  Files                   1139     1207      +68     
  Lines                  82320    91770    +9450     
  Branches               10705    12024    +1319     
=====================================================
+ Hits                   69219    77154    +7935     
- Misses                  8414     9293     +879     
- Partials                4687     5323     +636     
Flag Coverage Δ
ci 84.07% <93.28%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
....Abstractions/Schedules/ScheduledDispatchModels.cs 98.55% <100.00%> (+0.06%) ⬆️
...cheduledServiceInvocationCredentialExchangePort.cs 100.00% <100.00%> (ø)
...n/Schedules/ScheduledDispatchApplicationService.cs 91.25% <100.00%> (+1.89%) ⬆️
...cheduledServiceInvocationCredentialExchangePort.cs 96.55% <100.00%> (+1.09%) ⬆️
...n.Abstractions/Schedules/WorkflowScheduleModels.cs 64.77% <100.00%> (+1.67%) ⬆️
...astructure/Schedules/ScheduledDispatchActorPort.cs 88.78% <88.88%> (-5.96%) ⬇️
...n/Schedules/WorkflowScheduleConfigurationMapper.cs 96.42% <90.00%> (-2.19%) ⬇️
...chedules/ScheduledServiceInvocationDispatchPort.cs 94.35% <95.31%> (+0.84%) ⬆️
...tService.Core/Schedules/ScheduledDispatchGAgent.cs 81.04% <86.11%> (+3.59%) ⬆️
.../Endpoints/Schedules/ScheduledDispatchEndpoints.cs 93.87% <92.00%> (-2.00%) ⬇️

... and 197 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

louis4li and others added 11 commits June 18, 2026 11:48
Keep the scope-owner schedule auth plumbing but prevent owner tokens from masquerading as sender credentials during scheduled invocation dispatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cover scope-owner NyxID auth validation, mapping, noop exchange, and GAgent fire-time propagation so the patch coverage gate exercises the new scheduled auth paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bind scope-owner schedule auth to the authenticated HTTP owner at create/update time so scheduled fires no longer infer the owner from service tenant ids.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Account for upstream voice-presence changes merged from feature/integrate so the guard baseline matches current line locations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensure scope-owner schedules persist an explicit owner subject instead of accepting scope or tenant identity as a late-bound credential source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Route Studio login code exchange through the backend so NyxID can return a broker binding id, then keep schedule create/update as read-only validation of the durable owner binding instead of deriving bindings from bearer claims.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
louis4li and others added 5 commits June 22, 2026 14:33
Ensure backend-owned NyxID login finalization can publish the broker OAuth client configuration that must be used to generate authorization codes, and cover the endpoint/error branches for CI coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update schedule and hosting tests to match current service invocation auth and off-grain LLM run execution registrations so the coverage quality gate can complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep this PR backend-only and leave frontend NyxID callback integration to the follow-up issue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Return accepted-dispatch semantics from Studio login finalization instead of implying the binding read model is already committed and visible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve the GAgentService hosting test conflict by keeping current off-grain LLM execution registration assertions from both branches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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