Skip to content

feat: add incremental OAuth service consent - #1683

Closed
AbigailDeng wants to merge 2 commits into
ChronoAIProject:mainfrom
AbigailDeng:codex/incremental-service-consent-1682
Closed

AbigailDeng wants to merge 2 commits into
ChronoAIProject:mainfrom
AbigailDeng:codex/incremental-service-consent-1682

Conversation

@AbigailDeng

@AbigailDeng AbigailDeng commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Applications that need additional NyxID services can currently replace or narrow the user's existing grant when requesting only the missing services. This adds explicit incremental consent: existing A/B plus approved C/D yields A/B/C/D in the authorization code, refresh chain, and broker binding, while an optional resource=C narrows only the access token.

  • Add service_access_mode=incremental and repeated exact requested_service_ids to authorize/PAR, preserving them through login and signed consent. Support ordinary account authorization without an external subject and updates to a selected binding using its validated hash. Ordinary review behavior remains available.
  • Add the Update service access page with required additions, optional additions, immutable Already authorized services, personal/organization identity, accurate action counts, and blocked states for unavailable or expired requests. Security-relevant display fields come from the signed request; submission verifies the signature and live authority.
  • Preserve existing scopes and all-services semantics without permitting wildcard escalation. Consent revisions/fingerprints and binding versions reject stale updates. Transactional consent/refresh revocation, a post-insertion consent write, and atomic binding/refresh replacement prevent overlapping issuance from restoring revoked access.

Refs #1682. The NyxID implementation is complete in this PR. The issue remains open for the separate Aevatar Services button, callback/draft restoration, and cross-application integration acceptance (aevatarAI/aevatar#3678). The API, architecture, and OAuth guide document the caller contract and require the new backend/UI to be deployed before callers enable incremental mode.

Design reference

Approved prototype from #1682 (illustrative service data; not a production authorization screenshot):

Incremental consent prototype: additional services and retained authorization

Open original prototype

Test Plan

Backend tests use a dedicated MongoDB 8 replica set at mongodb://127.0.0.1:27182/?directConnection=true; CARGO_TARGET_DIR reuses the existing local Cargo cache. Exact test commands from the repository root:

export NYXID_TEST_DATABASE_URL='mongodb://127.0.0.1:27182/?directConnection=true'
export CARGO_TARGET_DIR=/Users/abigaildeng/Documents/work/NyxID/target
cargo test -p nyxid handlers::oauth:: --offline -- --nocapture
cargo test -p nyxid services::consent_service:: --offline -- --nocapture
cargo test -p nyxid services::oauth_service:: --offline -- --nocapture
cargo test -p nyxid services::oauth_broker_service:: --offline -- --nocapture
cargo test -p nyxid services::par_service:: --offline -- --nocapture
cargo test -p nyxid models::consent:: --offline -- --nocapture
cargo test -p nyxid models::authorization_code:: --offline -- --nocapture
cargo clippy -p nyxid --tests --offline -- -D warnings

Backend results: 156 passed across the seven filters (72 + 7 + 14 + 38 + 5 + 7 + 13); Clippy passed with warnings denied.

Coverage includes accumulated A/B/C/D refresh and binding authority with narrowed access, no-subject bindings, legacy records, existing all-services grants, optional additions, concurrent decisions, revoke/issuance overlap, binding rotation, tampered requests, expiry/cancel, and live organization membership with same-slug services.

Dependency-focused frontend validation, from frontend/:

npx vitest related src/pages/oauth-consent.tsx src/pages/oauth-incremental-consent.tsx src/schemas/oauth-consent.ts --run
npx vitest run src/pages/oauth-incremental-consent.test.tsx
npx eslint src/pages/oauth-consent.tsx src/pages/oauth-incremental-consent.tsx src/pages/oauth-incremental-consent.test.tsx src/schemas/oauth-consent.ts
npx prettier --check src/pages/oauth-consent.tsx src/pages/oauth-incremental-consent.tsx src/pages/oauth-incremental-consent.test.tsx src/schemas/oauth-consent.ts

Related frontend tests: 51 passed in 5 files. New test file explicitly run: 14 passed (also included in the related run). ESLint and Prettier passed. Scope selected with:

python3 /Users/abigaildeng/.codex/skills/frontend-incremental-pr/scripts/frontend_change_scope.py --repo . --base upstream/main

Changed Rust files passed:

rustfmt --edition 2024 --config skip_children=true --check backend/src/handlers/admin.rs backend/src/handlers/consent.rs backend/src/handlers/oauth.rs backend/src/handlers/oauth_incremental_tests.rs backend/src/models/authorization_code.rs backend/src/models/consent.rs backend/src/models/pushed_authorization_request.rs backend/src/services/consent_service.rs backend/src/services/incremental_consent_service.rs backend/src/services/mod.rs backend/src/services/oauth_broker_service.rs backend/src/services/oauth_client_service.rs backend/src/services/oauth_service.rs backend/src/services/par_service.rs backend/src/services/proxy_service.rs
git diff --cached --check

The actual React page was rendered in the existing Chrome browser with local fixture data; its accessible content, sections, counts, and controls were inspected. No production authorization was submitted. Aevatar ↔ NyxID deployment/integration verification remains outstanding.

Full frontend test suite, lint, typecheck, and production build are delegated to GitHub CI by personal local-validation policy. The repository has no reliable affected typecheck target, so no local full typecheck was run.

Checklist

  • Focused backend and frontend regression tests added and existing related behavior checked
  • Handler/service/model boundaries retained
  • No hardcoded secrets or credentials; binding handles stay out of browser URLs
  • Documentation updated, including Aevatar integration and deployment requirements
  • Full GitHub CI verification
  • Aevatar callback and draft-restoration integration in its own repository

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

📊 Code coverage

Component Lines Threshold Status Δ vs base
Frontend (vitest) 71.14% 15% ✅ 🔺 +0.39

Gate: line coverage must stay at or above the threshold. Ratchet plan (W21): Backend → 55%, CLI → 50%, Frontend → 30% by quarter end.

@ctkm-aelf

Copy link
Copy Markdown
Collaborator

superseded by #1718

@ctkm-aelf ctkm-aelf closed this Sep 30, 2026
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.

2 participants