fix(team): compare the family's values, not its variable names

Comparing per variable rejected a credential written under its other spelling:
langfuse_secret and langfuse_secret_key are one key, so repeating the stored
secret under the other name read as a new value.

Ask instead whether the value is one the owning entries already carry. A
destination the caller controls is by definition not, so the redirect stays
closed, and no alias table has to stay complete for that to hold.
This commit is contained in:
Yucheng Zhu 2026-09-01 14:28:02 -07:00
parent bf29ecf115
commit c0282621c7
2 changed files with 21 additions and 13 deletions

View file

@ -77,7 +77,7 @@ def cross_entry_family_error(
callback_vars: Mapping[str, str] | None,
stored_vars_by_entry: Sequence[Mapping[str, str]],
) -> str | None:
"""Reject an entry that changes a credential family another entry already holds.
"""Reject an entry that brings a new value to a family another entry holds.
Every stored entry's variables are flattened into one dict before a request
reads them, and the flattened dict is what the exporter authenticates and
@ -86,12 +86,14 @@ def cross_entry_family_error(
with the key from the first, and the request carries that key to the new
host.
Requiring one entry to own a family end to end removes the pairing. Repeating
a value the holding entry already stores is allowed, because flattening then
produces the same dict either way -- that is how the same integration gets
registered for both the success and the failure event. A team admin who does
want to move a family deletes the entry holding it first, which reveals
nothing.
A destination the caller controls is by definition a value the owning entries
do not already carry, so requiring every value to be one of theirs removes
the pairing. Repeating what they carry is allowed: that is how the same
integration gets registered for both the success and the failure event, and
it holds for the spellings the same credential has (``langfuse_secret`` and
``langfuse_secret_key`` are one key) without anything here having to list
them. A team admin who does want to move a family deletes the entry holding
it first, which reveals nothing.
Only the writers this endpoint newly admits are held to this, because a proxy
admin already holds every credential the proxy has.
@ -101,16 +103,20 @@ def cross_entry_family_error(
"""
if not callback_vars:
return None
stored: Final = { # mutable-ok: local view of the stored entries, never stored
var: value for entry in stored_vars_by_entry for var, value in entry.items() if _family_of(var) is not None
}
held: Final = {_family_of(var) for var in stored} # mutable-ok: local index, never stored
stored: Final = tuple(
(family, value)
for entry in stored_vars_by_entry
for var, value in entry.items()
if (family := _family_of(var)) is not None
)
held_values: Final = frozenset(stored)
held_families: Final = frozenset(family for family, _ in stored)
return next(
(
f"{family} is already configured by another callback entry on this team. "
f"Remove that entry before setting {var} here."
f"Remove that entry before setting {var} to a new value here."
for var, value, family in ((v, callback_vars[v], _family_of(v)) for v in callback_vars)
if family in held and stored.get(var) != value
if family in held_families and (family, value) not in held_values
),
None,
)

View file

@ -1541,6 +1541,8 @@ async def test_proxy_admin_still_told_the_team_is_unknown():
# the same integration registered for a second event: identical values
# flatten to the identical dict, so there is nothing to redirect
({"langfuse_host": "https://us.cloud.langfuse.com", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}, [{"langfuse_host": "https://us.cloud.langfuse.com", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}], False),
# the same credential under its other spelling is the same credential
({"langfuse_secret": "sk"}, [{"langfuse_public_key": "pk", "langfuse_secret_key": "sk"}], False),
# the same shape with one value moved is the redirect again
({"langfuse_host": "http://attacker.invalid", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}, [{"langfuse_host": "https://us.cloud.langfuse.com", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}], True),
],