Skip to content

fix(versa_azure): the public Azure OpenAI card's keys no longer steer Versa - #238

Merged
Broccolito merged 10 commits into
fix/versa-azure-per-model-deploymentfrom
fix/versa-azure-no-public-azure-deployment
Sep 11, 2026
Merged

fix(versa_azure): the public Azure OpenAI card's keys no longer steer Versa#238
Broccolito merged 10 commits into
fix/versa-azure-per-model-deploymentfrom
fix/versa-azure-no-public-azure-deployment

Conversation

@Broccolito

@Broccolito Broccolito commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #230, with base fix/versa-azure-per-model-deployment. This repo deletes head branches on merge, and GitHub closes a PR whose base branch disappears. Retarget this PR to main (gh pr edit 238 --base main) before merging #230.

This fixes a pre-existing bug that #230 listed under "not changed". versa_azure fell back to the public azure_openai provider's own config keys whenever its VERSA_AZURE_* twins were blank. So whatever a user set that card up with steered every Versa request. After this PR, Versa reads only its own namespace.

What was wrong

Each row is a Versa chat on gpt-4.1-2025-04-14, with VERSA_AZURE_* blank and the public Azure OpenAI card holding the value shown.

Public Azure OpenAI card holds What Versa did Now
AZURE_OPENAI_DEPLOYMENT_NAME=my-gpt4o (or gpt-4o, Azure's habit of naming a deployment after its model) Posted every turn to …/openai/deployments/my-gpt4o/… and got DeploymentNotFound Posts to gpt-4.1-2025-04-14
AZURE_OPENAI_DEPLOYMENT_NAME=gpt-5-mini-2025-08-07 (a real UCSF deployment the catalog does not offer) gpt-5-mini answered, and nothing said so. This is F1 again, through the other card. Same
Either value above, with a model no deployment serves Posted to the public card's deployment instead of refusing Refused before anything is sent
AZURE_OPENAI_ENDPOINT=https://contoso.openai.azure.com Sent the transcript and VERSA_AZURE_API_KEY to contoso, which refused the key. The instance turned Public, so a private chat could not bind it. UCSF gateway, Private
AZURE_OPENAI_API_VERSION=2024-10-21 Sent api-version=2024-10-21 on every Versa request 2025-01-01-preview

AZURE_OPENAI_DEPLOYMENT_NAME is the one key the public card requires with no default, so anyone who configured Azure OpenAI typed their own deployment into it. They almost always changed the endpoint too. A deployment-only fix would therefore not repair that user's Versa, which is why this PR also covers the endpoint and API version (see Commits).

Who was exposed. Every install whose Versa was not set up through the onboarding card after 2026-09-03. That card is the only surface that writes VERSA_AZURE_*; the Settings form and biorouter configure write only the declared API key. Also, #234 stops that card writing the deployment. Without this PR, every fresh install would then fall through to the public card's key for it.

Reproduced before each fix

Both new tests assert the correct routing. Each was run against the code before its fix:

  • the_public_azure_cards_deployment_never_routes_a_versa_request, against fix(versa_azure): each model posts to its own deployment; an unmapped model is refused before it is sent (F1) #230's head faf52596:
    assertion `left == right` failed: the public azure_openai card's deployment `my-gpt4o` routed a Versa request for gpt-4.1-2025-04-14
      left: "/openai/deployments/my-gpt4o/chat/completions"
     right: "/openai/deployments/gpt-4.1-2025-04-14/chat/completions"
    
  • the_public_azure_cards_endpoint_and_api_version_never_reach_versa, against commit 1:
    assertion `left == right` failed: the public azure_openai card's endpoint or API version reached a Versa chat
      left: (String("https://contoso.openai.azure.com"), Public, String("2024-10-21"))
     right: (String("https://unified-api.ucsf.edu/general"), Private, String("2025-01-01-preview"))
    

Commits

  1. 967b2149: deployment (the suspected bug). from_env reads only VERSA_AZURE_DEPLOYMENT_NAME.
  2. d122b125: endpoint and API version. The same defect in the other two legacy reads; resolve_override loses its legacy argument. This commit is separable, so drop it if you'd rather decide those two keys separately.

Migration consequences

  • Deployment. The old Versa forms (the onboarding card and the Settings form) prefilled the shipped default: gpt-5.2-2025-12-11 until 2026-07-02, then gpt-5.5-2026-04-24. Both are catalog deployments, which fix(versa_azure): each model posts to its own deployment; an unmapped model is refused before it is sent (F1) #230 already ignores, so nothing changes for those installs. What's dropped is a value someone typed over the prefill. Those chats now post to each model's own deployment, and setting VERSA_AZURE_DEPLOYMENT_NAME restores the override.
  • Stored routes. A session row written while the fallback was live may carry the public card's deployment as its route. Nothing in the row distinguishes it from a deliberate override, so a restore honours it. That lasts until the chat's model is picked again, which rebuilds through from_env (update_agent_providercreate).
  • Endpoint. Every Versa setup surface prefilled the shipped endpoint, which hasn't changed since 2026-05-07. The only endpoints dropped are ones typed over the prefill, or ones carried in from the public card (which is the bug).
  • API version: the one real migration. From 2026-05-30 to 2026-07-02 the onboarding card prefilled 2024-10-21 into AZURE_OPENAI_API_VERSION. (The Settings form's backend default, 2025-01-01-preview, won there.) Installs onboarded in that window and not reconnected since 2026-09-03 move from 2024-10-21 to 2025-01-01-preview, the version every other install already sends. I did not measure this against the gateway.

Privacy key scan (privacy/config_keys.rs)

Of the five TIER_INPUT_FILES, only versa_azure.rs read any of the three AZURE_OPENAI_* keys. factory.rs never read them, and azure.rs isn't scanned. So the scanned surface drops 26 → 25 → 23. Each key's row is deleted along with its read, rather than left classifying a key nothing reads.

I also added a reverse assertion: every classified key must still be read by a tier-input file. Without it, someone could edit the count and leave a dead row behind with no test objecting. I checked that it fails when it should: putting back the deleted AZURE_OPENAI_DEPLOYMENT_NAME row fails with … is classified but no tier-input file reads it; delete its row.

The net privacy effect is that fewer keys can move Versa's tier. Before, the public card's endpoint could demote it, and deleting that key could promote it back. Now only VERSA_AZURE_ENDPOINT can, and tier() still follows the endpoint the instance resolved.

Other callers updated

  • Server and subagent tests. The server test a_new_private_provider_chat_requires_user_action_before_first_bind and subagent_tool's ucsf_child_overrides pinned the AZURE_OPENAI_* keys to isolate Versa from the machine's config. They now pin VERSA_AZURE_*, which actually does isolate it; a developer's VERSA_AZURE_ENDPOINT got past the old pins.
  • Manual stream probe. tests/versa_gpt_stream_probe.rs now requires VERSA_AZURE_DEPLOYMENT_NAME and VERSA_AZURE_ENDPOINT.
  • Key names in comments. factory.rs's affiliation table and a tier_tests.rs comment now name the right key.
  • Agent Drafter runbook. It no longer says the AZURE_OPENAI_* keys configure Versa.
  • Privacy design doc. privacy-tiers.md §5.1 gains a dated note: the shared-key hazard behind the demotion rule is now closed at the source.
  • Old-behaviour test. The one assertion of the old behaviour ("the legacy key still overrides where Versa's own is unset") is replaced by its opposite.

Tests

  • BIOROUTER_DISABLE_KEYRING=true cargo test -p biorouter --lib -- providers::versa_azure privacy::config_keys: 28 passed
  • BIOROUTER_DISABLE_KEYRING=true cargo test -p biorouter --lib: 3807 passed, 0 failed, 2 ignored
  • BIOROUTER_DISABLE_KEYRING=true cargo test -p biorouter-server --lib -- routes::agent::new_session_provider_binding_tests: 4 passed, including the edited a_new_private_provider_chat_requires_user_action_before_first_bind
  • BIOROUTER_DISABLE_KEYRING=true cargo test -p biorouter --test versa_gpt_stream_probe: 2 passed, 1 ignored (the manual network probe)
  • cargo fmt --all -- --check: clean
  • ./scripts/clippy-lint.sh: clean (strict pass, too_many_lines baseline, banned-TLS-crate check)

Not changed (noticed, out of scope)

  • versa_bedrock has the same shared-namespace problem, in both directions. It declares and reads the public aws_bedrock provider's AWS_REGION and AWS_ENDPOINT_URL_BEDROCK. It also falls back to AWS_ENDPOINT_URL_BEDROCK_RUNTIME, which bedrock.rs sets process-wide from every AWS_* config value and secret. That deserves its own PR.
  • config_keys.rs gives a stale reason for classifying the endpoint rows. It says they "cannot RAISE a tier: Task 5 name-keys versa_azure and versa_bedrock Private regardless of endpoint". That has been false since e2e4eb9d: tier() follows the resolved endpoint. The classification may still be right for a different reason (no value anyone writes can make an off-site endpoint look Private), but that is a DR-16 decision, so I left the text alone.

🤖 Generated with Claude Code

… Versa requests

`VersaAzureProvider::from_env` fell back to `AZURE_OPENAI_DEPLOYMENT_NAME`
whenever `VERSA_AZURE_DEPLOYMENT_NAME` was blank. That key is not Versa's: it
is the one key the PUBLIC `azure_openai` card requires and ships no default
for, so it names a deployment on whatever Azure resource the user set THAT
card up with. A name the catalog does not know is an override serving every
Versa request, so a user who configured Azure OpenAI with `my-gpt4o` (or
`gpt-4o`, Azure's habit of naming a deployment after its model) had every
Versa turn posted to

    https://unified-api.ucsf.edu/general/openai/deployments/my-gpt4o/...

and got DeploymentNotFound back, whatever model the chat named. Where the name
is a real UCSF deployment the catalog does not offer (gpt-5-mini-2025-08-07
answers at the gateway), the wrong model replied and nothing said so: F1
again, through the other provider's card. This predates #230 — the fallback
used to pin the deployment outright; #230 narrowed it to non-catalog names.

Reproduced before fixing: the new routing test, run against faf5259, fails
with

    left:  "/openai/deployments/my-gpt4o/chat/completions"
    right: "/openai/deployments/gpt-4.1-2025-04-14/chat/completions"

Exposed: every install whose Versa was not set up through the onboarding card
after 2026-09-03, the only surface that writes VERSA_AZURE_DEPLOYMENT_NAME.
The Settings form and `biorouter configure` write only the declared API key.

The fix: read Versa's own key and nothing else.

Migration. The fallback was kept for installs whose pre-2026-09-03 Versa
forms wrote the legacy key. Those forms PREFILLED the shipped default
(gpt-5.2-2025-12-11 until 2026-07-02, gpt-5.5-2026-04-24 since), and both name
catalog deployments, which are not overrides — for those installs nothing
changes. What is dropped is a value someone typed over the prefill in the
onboarding card's Advanced panel or the Settings form's collapsed options:
that install's chats now post to each model's own deployment, a model the
catalog does not map is refused before anything is sent, and setting
VERSA_AZURE_DEPLOYMENT_NAME restores the override. A session row written
while the fallback was live may store the public card's deployment as its
route; nothing in the row tells it from a chosen override, so a restore
honours it until the chat's model is picked again, which rebuilds through
`from_env`.

Privacy key scan. Of the five tier-input files only versa_azure.rs read
AZURE_OPENAI_DEPLOYMENT_NAME (factory.rs never did; azure.rs is not scanned),
so the scanned surface drops 26 -> 25 and the key's "deployment selection"
row is deleted rather than left classifying nothing. The test now also
asserts the reverse direction — every classified key is still read by a
tier-input file — so the next removed read cannot be absorbed by editing the
count alone.

The one assertion of the old behaviour ("the legacy key still overrides
where Versa's own is unset") is replaced by its opposite: Versa's own key
wins, and the public key beside it changes nothing. The server test that
pinned the legacy key to isolate a private first bind now pins
VERSA_AZURE_DEPLOYMENT_NAME, and the manual stream probe requires it.
… longer steer Versa

The deployment was not the only key Versa borrowed from the PUBLIC
`azure_openai` card. `from_env` also fell back to its AZURE_OPENAI_ENDPOINT
and AZURE_OPENAI_API_VERSION whenever the VERSA_AZURE_* twins were blank —
the same population as the previous commit's. Whoever configures Azure
OpenAI for a company resource changes the endpoint along with the
deployment, so the previous commit alone does not repair their Versa:

  - Endpoint. Every Versa request posted to the company resource, carrying
    the transcript and VERSA_AZURE_API_KEY in its `api-key` header. The
    resource refused the key, and because `tier()` follows the resolved
    endpoint the instance became Public — a private chat could no longer
    bind UCSF's own model, for a reason set on a different card, and the
    UCSF key had gone to a host that is not UCSF's.
  - API version. The public card's version rode along on every request to
    the UCSF gateway.

Reproduced on the previous commit: with the public card set to a company
resource, the new routing test resolves a Versa chat to

    ("https://contoso.openai.azure.com", Public, "2024-10-21")
    instead of
    ("https://unified-api.ucsf.edu/general", Private, "2025-01-01-preview")

The fix: Versa reads only VERSA_AZURE_ENDPOINT and VERSA_AZURE_API_VERSION,
and `resolve_override` loses its legacy argument.

Migration. Every Versa setup surface prefilled the endpoint with the shipped
constant, unchanged since 2026-05-07, so an endpoint this drops was typed
over that prefill or carried in from the public card — the bug itself. The
API version is the one real migration: the onboarding card of 2026-05-30 to
2026-07-02 prefilled `2024-10-21` into AZURE_OPENAI_API_VERSION (in the
Settings form the backend default, 2025-01-01-preview, won), so installs
onboarded in that window and not reconnected since 2026-09-03 move from
2024-10-21 to 2025-01-01-preview — the version every other install already
sends. Anyone who set either key deliberately for Versa sets its
VERSA_AZURE_* twin.

Privacy. This only shrinks what can move Versa's tier: the public card's
endpoint could demote it, and deleting that key could promote it back; now
only VERSA_AZURE_ENDPOINT can, and `tier()` still follows the endpoint the
instance resolved. The key scan drops 25 -> 23 and both AZURE_OPENAI_* rows
go with their reads — the reverse check added in the previous commit fails
if either is left behind. azure.rs still reads all three and is not a
tier-input file; azure_openai is Public wherever it points.

Callers that pinned the public keys to isolate a Versa instance from the
machine's config — the server's private-first-bind test and subagent_tool's
UCSF child — now pin VERSA_AZURE_ENDPOINT / _API_VERSION, the keys that
actually isolate it (a developer's VERSA_AZURE_ENDPOINT leaked past the old
pins). The manual stream probe requires VERSA_AZURE_ENDPOINT, the
Agent Drafter runbook stops saying the AZURE_OPENAI_* keys configure Versa,
and privacy-tiers.md §5.1 notes that the shared-key hazard behind the
demotion rule is closed at the source.
These rows FAIL at this commit, on purpose: they assert the routing the next
commits establish, and this is the code they were run against.

Versa Bedrock (Private, UCSF) and the public Amazon Bedrock card shared the
AWS_* namespace, and it went wrong in both directions:

- The public card's AWS_REGION, and an AWS_ENDPOINT_URL_BEDROCK in config or
  the process environment, became Versa's region and endpoint. The instance
  turned Public and signed with UCSF-issued keys for someone's AWS region.
- AWS_BEARER_TOKEN_BEDROCK in the environment (the AWS SDK's own variable for
  a Bedrock API key) made the SDK authenticate Versa's requests with that
  bearer token instead of signing them, so a Versa chat that looked entirely
  right (UCSF gateway, us-west-2, Private) sent the public card's API key to
  UCSF, and Versa's own keys signed nothing.
- The AWS_ENDPOINT_URL_BEDROCK Versa's setup persisted became the PUBLIC
  provider's endpoint once bedrock.rs exported and promoted it, so the user's
  own AWS-signed requests went to UCSF's gateway.
- Versa declared AWS_REGION, which the public card declares too, so a Versa
  setup marked that card Configured; the onboarding card wrote both AWS keys.

Each provider is built through from_env and only its HTTP transport is then
swapped for the SDK's capture client, so every assertion is on the request
production would have sent, and nothing leaves the process. Environment rows
run in a re-executed child process that starts with the scenario's
environment and its own config root, because set_var in the test binary is
unsound and the public provider's own set_var is part of what is measured.
…espace

Versa Bedrock read the public Amazon Bedrock card's AWS_REGION and an
AWS_ENDPOINT_URL_BEDROCK key, then fell back to AWS_ENDPOINT_URL_BEDROCK and
AWS_ENDPOINT_URL_BEDROCK_RUNTIME in the process environment. bedrock.rs
exports every AWS_* config value into that environment, and a shell holds
them for the AWS CLI, so whatever the public side was set up with steered
Versa: UCSF-issued keys signed requests for someone's own AWS region, which
refused them, and the instance turned Public.

It reads VERSA_BEDROCK_ENDPOINT and VERSA_BEDROCK_REGION now, and nothing
else; blank is absent, absent is the UCSF gateway and us-west-2. It also
stops declaring the two AWS keys. AWS_REGION is one of the two keys the
public card declares, both defaulted, so check_provider_configured called
that card Configured as soon as a Versa setup persisted it.

Privacy key scan (privacy/config_keys.rs): the scanned count stays 23, with
two rows swapped rather than added. AWS_ENDPOINT_URL_BEDROCK and AWS_REGION
are deleted, since no tier-input file reads them now, and the reverse check
insists on that. VERSA_BEDROCK_ENDPOINT keeps its predecessor's
classification, NOT a capability key. The stated reason was false: tier()
has followed the resolved endpoint since e2e4eb9, so deleting an off-site
value does raise the tier. What holds instead is that only the UCSF
gateway's own host reads Private, so no write can forge the badge. Whether
that raise should still be a user act is left as an open DR-16 question in
the comment. VERSA_BEDROCK_REGION is the SigV4 signing region; the
endpoint, not the region, decides where a request goes.

The manual versa_stream_wire_probe mirrors from_env and reads the same keys.

At this commit the environment rows still fail, on the bearer token alone:
renaming the keys does not stop the AWS SDK reading AWS_BEARER_TOKEN_BEDROCK.
That is the next commit.
…API key

The AWS SDK reads AWS_BEARER_TOKEN_BEDROCK from the process environment by
itself. Unless the auth scheme was chosen in code, it then authenticates
with that bearer token instead of signing. That variable is where AWS tells
a user to put a Bedrock API key, i.e. the PUBLIC card's credential. So a
Versa chat that looked entirely right, with the UCSF gateway, us-west-2 and a
Private tier, sent the public card's API key to UCSF in its Authorization
header, and Versa's own keys signed nothing. Measured through the real
from_env with the SDK's capture client:

  authorization: "Bearer public-bedrock-api-key"   (host unified-api.ucsf.edu)

Versa's loader now prefers SigV4 explicitly. A preference set on the loader
counts as chosen in code (Origin::is_client_config), so the SDK's env branch
leaves it alone, and the request is signed with VERSA_BEDROCK_* for the
gateway's region. from_resolved is the one constructor, so a restored chat
gets the same pin.

The endpoint was never exposed this way, and that was checked rather than
assumed: an endpoint set on the loader is also chosen in code, so
AWS_ENDPOINT_URL_BEDROCK_RUNTIME in the environment does not re-aim the
client. nothing_in_the_process_environment_steers_versa pins both.
…he public provider

Versa Bedrock's setup persisted AWS_ENDPOINT_URL_BEDROCK pointing at UCSF's
gateway: its onboarding card on every connect, its Settings form on every
save. bedrock.rs exports every AWS_* config value into the process
environment and then promoted AWS_ENDPOINT_URL_BEDROCK to
AWS_ENDPOINT_URL_BEDROCK_RUNTIME, the variable the AWS SDK aims Bedrock
Runtime at. So once the PUBLIC Amazon Bedrock provider was built on an
install that had set up Versa, the user's own AWS-signed requests went to
UCSF's gateway:

  host: "unified-api.ucsf.edu"
  authorization: "AWS4-HMAC-SHA256 Credential=PUBLICTESTACCESSKEY/.../us-west-2/bedrock/..."

The promotion is gone. Commit ac7def8 added it on 2026-04-12, a month
before Versa Bedrock existed, for "configs and setup scripts" that used the
short name. Every Biorouter surface that has written the key since wrote it
for Versa. The previous commits stop new writes, but installs keep the key,
so this provider has to ignore it, not merely stop receiving it. The short
name is also not Bedrock Runtime's: the SDK derives AWS_ENDPOINT_URL_BEDROCK
for the Bedrock control plane.

The public provider still follows the SDK's own mechanisms, which is how a
VPC endpoint or a proxy is meant to be set: AWS_ENDPOINT_URL_BEDROCK_RUNTIME
in the environment, the same key in config.yaml via the export, or an AWS
profile's services section. the_public_provider_still_follows_the_sdks_
endpoint_variable is the positive control, and it passes before and after.

This also removes one of the unlocked read-then-write set_var sites that
docs/testing/process-global-state.md lists.
…S keys

The onboarding card upserted AWS_ENDPOINT_URL_BEDROCK and AWS_REGION on every
Versa Bedrock connect, with the prefilled UCSF gateway and us-west-2, from an
Advanced panel that also offered them for editing. Both belong to the public
Amazon Bedrock card: AWS_REGION marked that card Configured and replaced its
region, and the public provider took the gateway as its endpoint. The card
now writes VERSA_BEDROCK_ENDPOINT and VERSA_BEDROCK_REGION, the only keys
versa_bedrock.rs reads, and labels the Advanced fields with those names.

The Settings form's versa_bedrock entry in PROVIDER_KEY_DEFAULTS is dead now:
a default only reaches a key the provider declares, and versa_bedrock
declares its key and secret alone. It is deleted rather than renamed.
Persisted values are not touched; the provider no longer reads them.
- privacy-tiers.md 5.1: a dated Bedrock note beside the Azure one. It says
  what closed, and names the crossing no endpoint check could see: the SDK's
  own read of AWS_BEARER_TOKEN_BEDROCK put the public card's API key on
  Versa requests to the gateway. The demotion rule stays, because
  VERSA_BEDROCK_ENDPOINT is user-writable.
- process-global-state.md: the promotion at bedrock.rs:90-92 leaves the
  table of production env writers (five sites become four, with a note
  saying what the fifth did), and the ledger gains a row for
  AWS_BEARER_TOKEN_BEDROCK. That reader lives inside a dependency, which is
  why no env::var scan in the document could have found it.
- providers/mod.rs and tier_tests.rs: the reason given for the demotion
  named both shared-key hazards as current. The reason that holds now is
  that each Versa endpoint is user-writable config.
The helper waited for checkProvider, so a write the card makes after it,
such as BIOROUTER_PROVIDER, landed after the assertions ran. A late AWS_*
write would have slipped past the rule the first test states. It now waits
for onSuccess('versa_bedrock'), as #234 does for the Azure flavour, and the
second test pins the exact write sequence: key, secret, the two
VERSA_BEDROCK_* overrides with the shipped defaults, then the provider.

Run against the pre-fix card (778381d4), both fail, and the diff shows what
it wrote: the same shipped defaults, under AWS_ENDPOINT_URL_BEDROCK and
AWS_REGION.
…pace

fix(versa_bedrock): Versa Bedrock and the public Amazon Bedrock card stop steering each other
@Broccolito
Broccolito merged commit 35f2133 into fix/versa-azure-per-model-deployment Sep 11, 2026
16 checks passed
@Broccolito
Broccolito deleted the fix/versa-azure-no-public-azure-deployment branch September 11, 2026 20:47
Broccolito added a commit that referenced this pull request Sep 11, 2026
…e-onboarding-no-deployment-write

Brings in the two sibling fixes that landed on the shared base: Versa no
longer reads the public Azure OpenAI card's keys (#238), and Versa Bedrock
and the public Amazon Bedrock card no longer share config keys (#248).

Both conflicts were unions:
- DefaultProviderSetupForm.tsx: each side deleted a different dead
  PROVIDER_KEY_DEFAULTS entry (this branch versa_azure, the base
  versa_bedrock). Both stay deleted, and the comment beside the table now
  names both providers: each declares only its credentials.
- InstitutionalSetupCard.test.tsx: each side added a helper next to the
  Azure connect helper (this branch writtenKeys, the base
  connectVersaBedrock). Both kept; the file now carries the five Azure
  tests from this branch and the two Bedrock tests from the base.
Broccolito added a commit that referenced this pull request Sep 11, 2026
The rest of the stack is on main now: per-model Versa deployments (#230), which carried #238 and #248, merged there, and this PR was retargeted to main. No conflicts; main has not touched this PR's three files since the stack's merge-base.
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