fix(settings): suppress false drift when Infisical unreachable
- Add infisical_available flag to _build_env_var_row - Stabilize error code (no exception text in API response) - Document raw-comparison safety inline
This commit is contained in:
36
web/app.py
36
web/app.py
@@ -2587,7 +2587,7 @@ def _read_infisical_values() -> tuple[dict[str, str], list[str]]:
|
|||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("infisical_read_failed: %s", e)
|
logger.warning("infisical_read_failed: %s", e)
|
||||||
return {}, [f"infisical_read_failed: {e}"]
|
return {}, ["infisical_read_failed"]
|
||||||
values: dict[str, str] = {}
|
values: dict[str, str] = {}
|
||||||
for s in secrets:
|
for s in secrets:
|
||||||
if s.secret_key in ENV_CATALOG:
|
if s.secret_key in ENV_CATALOG:
|
||||||
@@ -2599,18 +2599,36 @@ def _build_env_var_row(
|
|||||||
spec: EnvSpec,
|
spec: EnvSpec,
|
||||||
infisical_value: str | None,
|
infisical_value: str | None,
|
||||||
container_value: str | None,
|
container_value: str | None,
|
||||||
|
infisical_available: bool = True,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Build a single response row for an env var."""
|
"""Build a single response row for an env var.
|
||||||
if spec.is_secret:
|
|
||||||
|
When infisical_available=False and infisical_value=None, drift is forced
|
||||||
|
to False (we cannot detect drift without ground truth — UI shows the
|
||||||
|
'errors' field instead).
|
||||||
|
"""
|
||||||
|
# When Infisical is unreachable, we have no ground truth — don't fabricate drift.
|
||||||
|
if not infisical_available and infisical_value is None:
|
||||||
|
drift = False
|
||||||
|
if spec.is_secret:
|
||||||
|
infisical_display: str | None = None
|
||||||
|
container_display: str | None = (
|
||||||
|
mask_secret(container_value) if container_value else None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
infisical_display = None
|
||||||
|
container_display = container_value
|
||||||
|
elif spec.is_secret:
|
||||||
i_norm = mask_secret(infisical_value) if infisical_value else None
|
i_norm = mask_secret(infisical_value) if infisical_value else None
|
||||||
c_norm = mask_secret(container_value) if container_value else None
|
c_norm = mask_secret(container_value) if container_value else None
|
||||||
# drift: compare raw before masking
|
# Raw comparison (not hash): values stay in server memory only — never
|
||||||
|
# logged or returned in the response. mask_secret is applied to display only.
|
||||||
drift = (
|
drift = (
|
||||||
(infisical_value or "") != (container_value or "")
|
(infisical_value or "") != (container_value or "")
|
||||||
and bool(infisical_value or container_value)
|
and bool(infisical_value or container_value)
|
||||||
)
|
)
|
||||||
infisical_display: str | None = i_norm
|
infisical_display = i_norm
|
||||||
container_display: str | None = c_norm
|
container_display = c_norm
|
||||||
else:
|
else:
|
||||||
infisical_display = infisical_value
|
infisical_display = infisical_value
|
||||||
container_display = container_value
|
container_display = container_value
|
||||||
@@ -2618,7 +2636,6 @@ def _build_env_var_row(
|
|||||||
normalize_for_compare(spec, infisical_value)
|
normalize_for_compare(spec, infisical_value)
|
||||||
!= normalize_for_compare(spec, container_value)
|
!= normalize_for_compare(spec, container_value)
|
||||||
)
|
)
|
||||||
# only count as drift if at least one side is non-null
|
|
||||||
if infisical_value is None and container_value is None:
|
if infisical_value is None and container_value is None:
|
||||||
drift = False
|
drift = False
|
||||||
row = spec.to_public_dict()
|
row = spec.to_public_dict()
|
||||||
@@ -2635,11 +2652,14 @@ async def api_mcp_env():
|
|||||||
"""List all catalog env vars with Infisical + container values."""
|
"""List all catalog env vars with Infisical + container values."""
|
||||||
infisical_values, errors = _read_infisical_values()
|
infisical_values, errors = _read_infisical_values()
|
||||||
project_id, env, path = _infisical_ctx()
|
project_id, env, path = _infisical_ctx()
|
||||||
|
infisical_available = not errors # empty errors list → Infisical reachable
|
||||||
rows = []
|
rows = []
|
||||||
for key, spec in ENV_CATALOG.items():
|
for key, spec in ENV_CATALOG.items():
|
||||||
i_val = infisical_values.get(key)
|
i_val = infisical_values.get(key)
|
||||||
c_val = os.environ.get(key)
|
c_val = os.environ.get(key)
|
||||||
rows.append(_build_env_var_row(spec, i_val, c_val))
|
rows.append(
|
||||||
|
_build_env_var_row(spec, i_val, c_val, infisical_available=infisical_available)
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"vars": rows,
|
"vars": rows,
|
||||||
"infisical_environment": env,
|
"infisical_environment": env,
|
||||||
|
|||||||
Reference in New Issue
Block a user