Skip to content

Fix agent credential authorization and add guided recovery - #1924

Merged
Paul Lizer (paullizer) merged 4 commits into
Developmentfrom
paullizer-action-secret-authorization
Nov 11, 2026
Merged

Paul Lizer (paullizer) merged 4 commits into
Developmentfrom
paullizer-action-secret-authorization

Conversation

@paullizer

@paullizer Paul Lizer (paullizer) commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Agent-level credentials need to stay bound to the actual owner and connection destination, rather than following an agent ID or a partially configured endpoint. This hardens that boundary and gives affected users an actionable, permission-aware recovery flow.

  • Bind embedded credentials to scope, owner, agent, field and destination. Validate inactive fields, resolve only authorized stored credentials, and remove unsafe custom-connection fallback to application credentials.
  • Require explicit re-entry for legacy embedded credentials without reading old Key Vault values to manufacture ownership. Preserve masked edits, explicit replacements, Foundry authentication modes and classic/native save round-trips.
  • Add Guided recovery to classic and native chat, including JSON/SSE errors and failed retries. Authorized editors can open the exact agent's connection section in an isolated tab; others receive group-owner or site-administrator guidance. Requests are never replayed automatically, and viewer-specific recovery controls are not broadcast to shared conversations.
  • Align the comfortable message/composer column at 45rem with matching mobile margins; preserve explicit Wide mode. Add SDK, authorization, compatibility and responsive browser coverage, documentation and renewed Cosmos reviews.

Upgrade consideration: Existing embedded agent Azure OpenAI/APIM keys and Foundry service-principal client secrets must be re-entered before use. Restart the application and workers when deploying. Saved model connections, reusable workspace identities and MCP/action credentials are not blanket-reset. Re-entry does not rotate provider credentials or mass-delete legacy Key Vault secrets.

Scope: This PR covers agent runtime/Key Vault authorization and recovery. Development's shared response-redaction and signed-catalog implementations are retained and integrated, not replaced. Merge commits 63f626bab and fa21a0dc4 preserve the shared editor/readiness contracts and catalog snapshot pinning around background chat work.

Linked issue

N/A - no linked issue.

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

The compatibility change is mandatory re-entry for existing embedded agent credentials. Release notes remain unchanged pending approval; the upgrade requirements are documented in the fix notes and user guide.

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

Version bump

  • application/single_app/config.py VERSION third segment bumped, or not needed because this is docs-only
  • deployers/version.txt bumped, or not needed because deployers/ was not changed

Application version: 0.261.433. No deployer files changed. The credential binding revision is independent of ordinary application version bumps.

Testing / validation

Tests use synthetic credentials and blocked/stubbed external I/O. Python runs include the application and functional test directories on PYTHONPATH; browser runs also include the repository root and ui_tests\fixtures, with local Chromium.

Latest-base integration (09d3787a2):

  • python -m pip install --quiet -r .\scripts\requirements-model-catalog-tests.txt - completed, restoring the newly declared catalog pins, including pytest 8.4.2 and cryptography 46.0.7. Pip reported conflicts with unrelated globally installed packages; the validation below passed.
  • python -m pytest -p no:cacheprovider -p test_support.cosmos_network_guard .\functional_tests\test_model_catalog_signed_updates.py .\functional_tests\test_model_catalog_publication_lifecycle.py .\functional_tests\test_workflow_chat_delivery_loop.py .\functional_tests\test_agent_credential_recovery_links.py .\functional_tests\test_shared_agent_secret_responses.py -q --tb=short --disable-warnings - 183 passed.
  • python .\scripts\check_cosmos_response_boundaries.py --run-contracts - 1,601 passed under the declared pytest 8.4.2 environment, with 1,104 owners, 430 doubles and zero review gaps. The combined chat-module reviews retain both branches' runtime witnesses; storage-owner bodies are AST-identical to the previously reviewed implementations.
  • python -m pytest -p no:cacheprovider .\ui_tests\test_model_catalog_update_controls.py .\ui_tests\test_model_catalog_management.py .\ui_tests\test_agent_credential_reentry.py .\ui_tests\test_v2_chat_retry.py -q --tb=short --disable-warnings - 59 passed.
  • npm --prefix .\application\v2_ui run typecheck - passed.
  • npm --prefix .\application\v2_ui run build - passed; existing bundle-size advisory remains.
  • npm --prefix .\application\v2_ui run build -- --outDir ..\..\ui_tests\artifacts\orchestration-plan-editor - passed.
  • python .\functional_tests\route_tests\test_route_blueprint_policy_inventory.py - 15/15 passed.
  • python .\functional_tests\route_tests\test_route_unauthenticated_policy_contract.py - 10/10 passed.
  • python .\functional_tests\route_tests\test_route_policy_test_coverage.py - 4/4 passed.
  • python .\functional_tests\test_docs_app_surface_coverage.py - 7/7 checks passed.
  • python .\functional_tests\test_docs_site_quality.py - 6/6 checks passed.
  • git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol --no-pager diff --cached --check - passed before the merge commit.

Previous shared-response integration verification:

  • python -m pytest -p no:cacheprovider -p test_support.cosmos_network_guard .\functional_tests\test_agent_credential_security.py .\functional_tests\test_agent_credential_reentry.py .\functional_tests\test_agent_credential_owner_runtime.py .\functional_tests\test_agent_credential_recovery_links.py .\functional_tests\test_shared_action_secret_responses.py .\functional_tests\test_shared_agent_secret_responses.py .\functional_tests\test_workspace_authoring_sdk_boundaries.py -q --tb=short --disable-warnings - 198 passed.
  • python .\scripts\check_cosmos_response_boundaries.py --run-contracts - 2,074 passed, 431 subtests passed in the earlier local test environment. Changed editor-module reviews and the shared SDK fixture review were explicitly renewed.
  • python -m pytest -p no:cacheprovider .\ui_tests\test_shared_workspace_secret_editing.py .\ui_tests\test_agent_credential_reentry.py .\ui_tests\test_v2_chat_retry.py -q --tb=short --disable-warnings - 65 passed.
  • node --check .\application\single_app\static\js\agent_modal_stepper.js and node --check .\application\single_app\static\js\shared-credential-editor.js - passed.
  • python .\scripts\check_xss_sinks.py --base-sha e601e6ffdbbc6e15af724f603215b5b5b74950f5 --head-sha HEAD application\single_app\static\js\agent_modal_stepper.js application\single_app\static\js\shared-credential-editor.js - passed on actual PR additions. The unchanged full-file stepper warning also occurs on Development; no suppression was added.

Earlier scope-specific verification also passed: the reading-width/recovery contract command completed 42 cases, and python -m pytest -p no:cacheprovider .\ui_tests\test_agent_credential_reentry.py .\ui_tests\test_v2_chat_retry.py .\ui_tests\test_v2_mobile_chat_layout.py .\ui_tests\test_v2_chat_table_layout.py -q --tb=short --disable-warnings completed 61 cases before the base updates.

Actual desktop/mobile UI captures were inspected with synthetic data; session-only screenshots and prototype artifacts are not committed. This is not a claim that every legacy suite is green: pre-existing MCP authorization-context, assigned-knowledge fixture and chat sanitization source-pattern failures, plus an unchanged full-file access-control heuristic finding, are recorded in the fix documentation. No suppressions were added for those baseline findings.

Documentation

  • Release notes updated, or not needed
  • Feature documentation updated, or not needed
  • Fix documentation updated, or not needed

Updated the workspace agent guide, V2 authoring feature notes and chat-control reference. AGENT_CREDENTIAL_AUTHORIZATION_FIX.md records upgrade behavior, validation evidence, baseline limitations and the distinction between re-entry and provider-side rotation. The generated application-surface inventory is current after the merges.

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security())
  • Settings sent to non-admin frontends use sanitize_settings_for_user()
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS
  • No secrets, keys, connection strings, or local-only artifacts are included

No Flask routes or raw frontend settings payloads were added by this PR. Recovery rechecks existing editor authorization and exposes no secret values or internal credential bindings. Test credentials are synthetic.

Bind embedded agent credentials to their actual owner, field, scope, and connection target. Require explicit re-entry for legacy credentials and reject unsafe fallback and reference reuse.

Add permission-aware two-step recovery to classic and native chat, preserve masked save round-trips, and cover runtime, SDK, role, and responsive layout contracts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve shared write-only response projection, canonical owner-bound credential readiness, and both classic editor controls. Update isolated shared-response fixtures and verify the combined SDK and browser contracts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Retain signed-catalog worker pinning alongside agent credential recovery. Resolve the version and inventory conflicts, renew the combined chat-module owner reviews, and record the passing integration validation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Run SSE terminal-field normalization outside the assert so optimized Python preserves the mutation. Consolidate the UI fixture module import while retaining the original pytest fixtures and constants.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit 24f90d9 into Development Nov 11, 2026
13 checks passed
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