[feat] Starter credits: minimal web changes (hidden managed connection, replace-only secrets, add-your-key on exhaustion) - #6174
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe change propagates run-error codes, adds write-only and managed secret handling, merges stored provider credentials for probing, wires a shared runtime key, and updates starter-credits seeding, generated clients, UI, deployment config, and tests. ChangesSecret visibility and runtime grants
Estimated code review effort: 5 (Critical) | ~120 minutes Merge Risk: 🟠 High · up to This PR changes secret handling, provider probing, credential resolution, and deployment defaults, but the current head still permits stored credentials to be sent to a different provider, exposes credential material through caching or representations, and includes credential-resolution and startup-failure paths. These are high-impact security, correctness, and deployment risks, so the PR is not merge-ready until fixed. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
e207a29 to
4496dcc
Compare
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/packages/agenta-entities/src/secret/core/connections.ts (1)
681-698: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftPreserve custom-provider credentials during updates.
VaultService.update_secretcarries over onlymodelsandharnesses, while the DAO replacessecrets_dbe.datawith the submitted data. A write-only edit therefore sends emptyprovider.extrasand erases stored credentials. Merge omitted secret fields server-side or omitprovider.extrasfrom partial updates, and add regression tests.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: e34ceaa0-41be-4d85-8b54-c08670bae659
📒 Files selected for processing (47)
web/oss/src/components/AgentChatSlice/components/AgentMessage.runError.test.tsxweb/oss/src/components/AgentChatSlice/components/AgentMessage.tsxweb/oss/src/components/AgentChatSlice/components/ConnectModelBanner.tsxweb/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsxweb/oss/src/components/AgentChatSlice/hooks/useOnboardingProviderSetup.tsweb/oss/src/components/pages/settings/Vault/ConfigureSecretModal/index.tsxweb/packages/agenta-chat/src/assets/trace.tsweb/packages/agenta-chat/src/assets/transcriptToMessages.tsweb/packages/agenta-chat/src/hooks/useAgentModelKeyStatus.tsweb/packages/agenta-chat/src/model/turnStatus.tsweb/packages/agenta-chat/src/model/turnViewModel.tsweb/packages/agenta-chat/tests/unit/assets/trace.test.tsweb/packages/agenta-chat/tests/unit/assets/transcriptToMessages.test.tsweb/packages/agenta-chat/tests/unit/model/turnStatus.test.tsweb/packages/agenta-entities/src/secret/api/probe.tsweb/packages/agenta-entities/src/secret/core/connections.tsweb/packages/agenta-entities/src/secret/core/index.tsweb/packages/agenta-entities/src/secret/core/transforms.tsweb/packages/agenta-entities/src/secret/core/types.tsweb/packages/agenta-entities/src/secret/index.tsweb/packages/agenta-entities/src/secret/state/atoms.tsweb/packages/agenta-entities/src/secret/state/connections.tsweb/packages/agenta-entities/src/secret/state/persistence.tsweb/packages/agenta-entities/src/workflow/state/agentCreationPrefs.tsweb/packages/agenta-entities/src/workflow/state/appUtils.tsweb/packages/agenta-entities/tests/unit/agent-creation-prefs.test.tsweb/packages/agenta-entities/tests/unit/provider-connections.test.tsweb/packages/agenta-entities/tests/unit/secret-transforms.test.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/AgentTemplateControl.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/ProviderCredentialsSectionView.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/ProviderKeyField.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionPicker.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionUtils.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.tsweb/packages/agenta-entity-ui/src/DrillInView/index.tsweb/packages/agenta-entity-ui/src/secretProvider/ProviderConnectionCard.tsxweb/packages/agenta-entity-ui/src/secretProvider/ProviderDrawer.tsxweb/packages/agenta-entity-ui/tests/unit/connectionPicker.test.tsweb/packages/agenta-entity-ui/tests/unit/connectionUtils.test.tsweb/packages/agenta-settings-ui/src/providers/AIProvidersPage.tsxweb/packages/agenta-shared/src/state/index.tsweb/packages/agenta-shared/src/state/openProviderDrawer.tsweb/packages/agenta-shared/src/types/llmProvider.tsweb/packages/agenta-ui/src/LLMIcons/assets/Agenta.tsxweb/packages/agenta-ui/src/LLMIcons/index.tsweb/packages/agenta-ui/src/SelectLLMProvider/utils.ts
Included review availability: Your plan provides up to 8 included reviews per hour; 4 remain after this review.
Railway Preview Environment
Updated at 2026-08-23T20:48:15.703Z |
4496dcc to
27b0abd
Compare
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
hosting/docker-compose/oss/docker-compose.gh.local.yml (1)
3-18: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winThis filename matches the operator-local override pattern, but the file is committed.
The coding guidelines state that
hosting/docker-compose/**/docker-compose.*.local.ymlfiles are operator-local and gitignored. This file matches that pattern and contains full service definitions rather than an override. Committing it meansrun.shwill auto-include it for every operator and will also silently merge with any operator's own*.local.yml. Confirm the intended filename, or add the file to the ignore list and move the shared content into a tracked, non-.localcompose file.As per coding guidelines: "Local compose override files are operator-local, gitignored, automatically included by
run.sh, sorted lexicographically, and should be preserved during normal and targeted rebuilds."Source: Coding guidelines
🧹 Nitpick comments (9)
api/oss/src/utils/env.py (1)
578-586: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThe
"replace-me"placeholder rule is declared in three files._services_internal_key_from_environmentalready maps a blank or"replace-me"value toNone, so both consumers re-check a condition that the sharedenvobject cannot produce. The literal is duplicated, and a change to the placeholder inenv.pywould leave the two copies stale.
api/oss/src/utils/env.py#L578-L586: export the placeholder rule, for example a module-levelUNCONFIGURED_KEY_PLACEHOLDERconstant, so consumers reuse one definition.api/oss/src/apis/fastapi/access/router.py#L101-L127: drop_UNCONFIGURED_KEYand theexpected == _UNCONFIGURED_KEYbranch, and keep only thenot expectedguard.api/ee/src/core/starter_credits_bridge/service.py#L440-L448: drop_UNCONFIGURED_RUNTIME_KEYand reduce_platform_runtime_key_configuredto a truthiness check onenv.agenta.services_internal_key.clients/python/agenta_client/__init__.py (1)
422-423: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low valueRename the remaining local TypeScript alias to
PublicSecretResponseDto.types.ts,transforms.ts, and the tests still useSecretResponseDto, although the Python generated client and services use the replacement.api/oss/src/dbs/postgres/secrets/dao.py (1)
137-139: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUpdate the stale comment.
The comment describes "the one-way write_only check below". No
write_onlycheck exists in this method. The lock now protects theresolve_updatecallback, which the comment at Line 154 already explains.♻️ Proposed comment fix
- # FOR UPDATE serializes concurrent updates so the one-way write_only check - # below always sees the latest committed flag — two racing updates cannot - # both observe False and let a stale explicit False win. + # FOR UPDATE serializes concurrent updates so `resolve_update` below always + # reads the latest committed row.api/oss/src/dbs/postgres/secrets/mappings.py (1)
90-101: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAlign the update dump with the create dump.
map_secrets_dto_to_dbeserializes data withmodel_dump(exclude_none=True)at Line 57. The update path callsupdate_secret_dto.secret.data.model_dump()withoutexclude_none. An update therefore persists explicit nulls, for example{"provider": {"key": null}}or"harnesses": null, where a create of the same secret stores no key at all.Two rows with identical logical content then differ on disk depending on the write path. Downstream helpers such as
_value_statusand_carry_over_saved_extrasread these fields withnot in (None, "")checks, so the divergence is easy to reintroduce as a behavior difference later.♻️ Proposed fix
- secrets_dbe.data = _data_payload( - update_secret_dto.secret.data.model_dump(), + secrets_dbe.data = _data_payload( + update_secret_dto.secret.data.model_dump(exclude_none=True), write_only=write_only, management=management, ).gitleaks.toml (1)
45-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTwo conflicting exemption strategies land in the same change.
This block exempts fixture strings by value and states that fingerprints are deliberately avoided because "a fingerprint names the commit it was seen in, so it goes stale every time a lane below is rebased."
.gitleaksignorelines 295-303 then adds four commit-anchored fingerprints for the same class of fixture and asks maintainers to regenerate them after any history rewrite.Both files describe the same rebase hazard, and one of them accepts it. Pick one strategy for these fixtures. Value-based exemption survives the rebases this stack expects.
web/packages/agenta-entity-ui/src/secretProvider/ProviderConnectionCard.tsx (1)
167-172: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReduce the new explanatory comments to one short line.
web/packages/agenta-entity-ui/src/secretProvider/ProviderConnectionCard.tsx#L167-L172: replace the multi-line state explanation with one short comment.web/packages/agenta-entity-ui/src/secretProvider/ProviderDrawer.tsx#L134-L139: remove or reduce the multi-line filtering explanation.web/packages/agenta-settings-ui/src/providers/AIProvidersPage.tsx#L76-L79: remove or reduce the multi-line filtering explanation.As per coding guidelines, “Keep in-code comments to at most one short line; use longer comments only for genuinely surprising constraints such as bugs, races, or ordering requirements.”
Source: Coding guidelines
api/ee/tests/pytest/unit/test_starter_credits_bridge_seeding.py (1)
103-118: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueClass-level mutable state on
FakeProxyClientcouples tests to fixture ordering.
records,generate_failures, andinstancesare class attributes. Only theseeding_envfixture resets them. Any future test in this module that instantiatesFakeProxyClientwithoutseeding_envinherits state from a previous test. Consider moving the reset into an autouse fixture, or making the registry instance-scoped and passing it through the factory.Also applies to: 184-199
api/oss/tests/pytest/unit/vault/test_write_only_routes.py (1)
36-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMake the fake DAO store
datain one shape.
createstoresdataas a dict (model_dump(exclude_none=True)), andupdatestores it as the typed DTO object (update_secret_dto.secret.data). The router path then reads two different representations depending on whether a record was created or updated. Aligningupdatewithcreatekeeps the fake faithful to the postgres mapping and prevents a future assertion from passing for the wrong reason.♻️ Proposed alignment
if update_secret_dto.secret is not None: updated.kind = update_secret_dto.secret.kind - updated.data = update_secret_dto.secret.data + updated.data = update_secret_dto.secret.data.model_dump(exclude_none=True)Also applies to: 78-88
hosting/kubernetes/helm/tests/test_runner_secret_absence.py (1)
166-169: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReuse one rendered document set.
Line 166 renders the chart with
DEFAULT_TOKEN_ARGS, and line 169 renders the same arguments again. Eachrendercall spawns ahelm templatesubprocess. Render once and derive both results from the same documents.♻️ Single render
- names = runner_container_env_names(render(DEFAULT_TOKEN_ARGS)) + docs = render(DEFAULT_TOKEN_ARGS) + names = runner_container_env_names(docs) failures += check(names) - - docs = render(DEFAULT_TOKEN_ARGS)
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 2502a529-0a02-4c7d-bf7a-80d7b6db3294
⛔ Files ignored due to path filters (24)
web/packages/agenta-api-client/src/generated/api/resources/secrets/client/Client.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/secrets/client/requests/CreateSecretDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/secrets/client/requests/ProbeProviderRequest.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/secrets/client/requests/UpdateSecretDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/resources/secrets/client/requests/index.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CredentialResult.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CredentialStatus.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CustomProviderDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/CustomSecretSettingsDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/DiscoveryResult.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/DiscoveryStatus.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/ProbeProviderResponse.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/ProviderCredentials.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/PublicSecretManagementDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/PublicSecretResponseDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SecretDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SecretManagementPolicy.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SecretValueStatus.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/SsoProviderSettingsDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/StandardProviderDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/StandardProviderSettingsDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/UpdateSecretPayloadDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/WebhookProviderSettingsDto.tsis excluded by!**/generated/**web/packages/agenta-api-client/src/generated/api/types/index.tsis excluded by!**/generated/**
📒 Files selected for processing (127)
.gitleaks.toml.gitleaksignoreapi/ee/src/core/organizations/service.pyapi/ee/src/core/starter_credits_bridge/__init__.pyapi/ee/src/core/starter_credits_bridge/client.pyapi/ee/src/core/starter_credits_bridge/service.pyapi/ee/src/core/starter_credits_bridge/types.pyapi/ee/src/main.pyapi/ee/tests/pytest/unit/test_starter_credits_bridge_client.pyapi/ee/tests/pytest/unit/test_starter_credits_bridge_seeding.pyapi/ee/tests/pytest/unit/test_write_only_provider_settings.pyapi/entrypoints/routers.pyapi/oss/src/apis/fastapi/access/router.pyapi/oss/src/apis/fastapi/providers/models.pyapi/oss/src/apis/fastapi/providers/router.pyapi/oss/src/apis/fastapi/vault/router.pyapi/oss/src/core/secrets/dtos.pyapi/oss/src/core/secrets/interfaces.pyapi/oss/src/core/secrets/managed.pyapi/oss/src/core/secrets/redaction.pyapi/oss/src/core/secrets/services.pyapi/oss/src/core/webhooks/service.pyapi/oss/src/core/workflows/service.pyapi/oss/src/dbs/postgres/secrets/dao.pyapi/oss/src/dbs/postgres/secrets/mappings.pyapi/oss/src/middlewares/auth.pyapi/oss/src/utils/env.pyapi/oss/src/utils/helpers.pyapi/oss/tests/pytest/unit/access/test_grant_exchange.pyapi/oss/tests/pytest/unit/middlewares/test_auth_grants.pyapi/oss/tests/pytest/unit/providers/test_provider_probe.pyapi/oss/tests/pytest/unit/secrets/test_dtos.pyapi/oss/tests/pytest/unit/secrets/test_managed_secrets.pyapi/oss/tests/pytest/unit/secrets/test_services.pyapi/oss/tests/pytest/unit/secrets/test_write_only.pyapi/oss/tests/pytest/unit/utils/test_env_helpers.pyapi/oss/tests/pytest/unit/vault/test_managed_routes.pyapi/oss/tests/pytest/unit/vault/test_write_only_routes.pyapi/oss/tests/pytest/unit/webhooks/test_write_only_outward.pyclients/python/agenta_client/__init__.pyclients/python/agenta_client/secrets/client.pyclients/python/agenta_client/secrets/raw_client.pyclients/python/agenta_client/types/__init__.pyclients/python/agenta_client/types/credential_result.pyclients/python/agenta_client/types/credential_status.pyclients/python/agenta_client/types/custom_provider_dto.pyclients/python/agenta_client/types/custom_secret_settings_dto.pyclients/python/agenta_client/types/discovery_result.pyclients/python/agenta_client/types/discovery_status.pyclients/python/agenta_client/types/probe_provider_response.pyclients/python/agenta_client/types/provider_credentials.pyclients/python/agenta_client/types/public_secret_management_dto.pyclients/python/agenta_client/types/public_secret_response_dto.pyclients/python/agenta_client/types/public_secret_response_dto_data.pyclients/python/agenta_client/types/secret_dto.pyclients/python/agenta_client/types/secret_management_policy.pyclients/python/agenta_client/types/secret_value_status.pyclients/python/agenta_client/types/sso_provider_settings_dto.pyclients/python/agenta_client/types/standard_provider_dto.pyclients/python/agenta_client/types/standard_provider_settings_dto.pyclients/python/agenta_client/types/update_secret_payload_dto.pyclients/python/agenta_client/types/update_secret_payload_dto_data.pyclients/python/agenta_client/types/webhook_provider_settings_dto.pydocs/design/managed-secrets/README.mddocs/design/provider-connections-models/provider-discovery.mddocs/design/starter-credits-seeding/README.mddocs/design/write-only-secrets/README.mddocs/design/write-only-secrets/context.mddocs/design/write-only-secrets/implementation-report.mddocs/design/write-only-secrets/plan.mddocs/design/write-only-secrets/qa.mddocs/design/write-only-secrets/research.mddocs/design/write-only-secrets/review.mddocs/design/write-only-secrets/status.mdhosting/docker-compose/ee/docker-compose.dev.ymlhosting/docker-compose/ee/docker-compose.gh.local.ymlhosting/docker-compose/ee/docker-compose.gh.ymlhosting/docker-compose/ee/env.ee.dev.examplehosting/docker-compose/ee/env.ee.gh.examplehosting/docker-compose/oss/docker-compose.dev.ymlhosting/docker-compose/oss/docker-compose.gh.local.ymlhosting/docker-compose/oss/docker-compose.gh.ssl.ymlhosting/docker-compose/oss/docker-compose.gh.ymlhosting/docker-compose/oss/env.oss.dev.examplehosting/docker-compose/oss/env.oss.gh.examplehosting/kubernetes/ee/values.ee.example.yamlhosting/kubernetes/helm/templates/NOTES.txthosting/kubernetes/helm/templates/_helpers.tplhosting/kubernetes/helm/templates/_validations.tplhosting/kubernetes/helm/templates/api-deployment.yamlhosting/kubernetes/helm/templates/secrets.yamlhosting/kubernetes/helm/templates/services-deployment.yamlhosting/kubernetes/helm/tests/test_runner_secret_absence.pyhosting/kubernetes/helm/values.schema.jsonhosting/kubernetes/helm/values.yamlhosting/kubernetes/oss/values.oss.example.yamlhosting/railway/oss/README.mdhosting/railway/oss/scripts/configure.shhosting/railway/oss/template/template.jsonsdks/python/agenta/sdk/agents/connections/__init__.pysdks/python/agenta/sdk/agents/connections/credentials.pysdks/python/agenta/sdk/agents/connections/errors.pysdks/python/agenta/sdk/agents/platform/connections.pysdks/python/agenta/sdk/agents/platform/secrets.pysdks/python/agenta/sdk/middlewares/routing/auth.pysdks/python/agenta/sdk/middlewares/running/vault.pysdks/python/oss/tests/pytest/unit/agents/connections/test_credentials_parity.pysdks/python/oss/tests/pytest/unit/agents/platform/test_write_only_secrets.pysdks/python/oss/tests/pytest/unit/test_auth_middleware_credentials.pyservices/oss/tests/pytest/unit/agent/test_credential_exchange.pyweb/packages/agenta-entities/src/secret/api/probe.tsweb/packages/agenta-entities/src/secret/core/connections.tsweb/packages/agenta-entities/src/secret/core/index.tsweb/packages/agenta-entities/src/secret/core/transforms.tsweb/packages/agenta-entities/src/secret/core/types.tsweb/packages/agenta-entities/src/secret/index.tsweb/packages/agenta-entities/src/secret/state/atoms.tsweb/packages/agenta-entities/src/workflow/state/agentCreationPrefs.tsweb/packages/agenta-entities/tests/unit/agent-creation-prefs.test.tsweb/packages/agenta-entities/tests/unit/provider-connections.test.tsweb/packages/agenta-entities/tests/unit/secret-transforms.test.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionPicker.tsweb/packages/agenta-entity-ui/src/secretProvider/ProviderConnectionCard.tsxweb/packages/agenta-entity-ui/src/secretProvider/ProviderDrawer.tsxweb/packages/agenta-entity-ui/tests/unit/connectionPicker.test.tsweb/packages/agenta-settings-ui/src/providers/AIProvidersPage.tsxweb/packages/agenta-shared/src/types/llmProvider.ts
💤 Files with no reviewable changes (1)
- api/ee/src/main.py
🚧 Files skipped from review as they are similar to previous changes (1)
- web/packages/agenta-entity-ui/tests/unit/connectionPicker.test.ts
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.
27b0abd to
1145d25
Compare
8dd9a93 to
7d78428
Compare
e2a625c to
39d7ea2
Compare
448b21c to
7f0a740
Compare
|
Implemented the final frontend/review handoff in
Local gates: 100 focused entity tests and the — Codex |
7f0a740 to
ac68d75
Compare
39d7ea2 to
c86dcf2
Compare
|
🤖 The AI agent says: Final verification records are current at
|
c86dcf2 to
ea5c766
Compare
37b21bb to
3a2bc61
Compare
ea5c766 to
3879267
Compare
3a2bc61 to
32ae3dc
Compare
Context
The frontend previously copied backend fields by hand and called the provider probe through raw Axios. It also made managed behavior depend on the internal
managed_bycomponent string. That duplicated the contract and made the UI responsible for backend implementation details.Changes
Fern is regenerated from the final EE OpenAPI contract for Python and TypeScript. The secret entity now consumes
PublicSecretResponseDto,SecretValueStatus,SecretManagementPolicy, and the generated provider-probe request and response.Before:
After:
The UI maps
value_status.configuredandvalue_status.previewinto its provider-connection view model. It checks the exactmanagement.policy === "manager_only"policy rather than a manager-name string.Update payloads omit a provider credential when the user leaves it untouched. They do not send an empty string as a keep signal: the backend rejects an explicit blank. The backend, generated clients, SDK, and frontend ship in the same release, so there is no legacy
has_keyor blank-value compatibility path.Manager-only rows are hidden from Settings and edit drawers. They remain in the shared connection atom, agent creation defaults, model picker, and key-status checks, so seeded credentials still power agents.
The probe uses the Fern secrets client and project-scoped request options. Independent Zod validation remains at the frontend boundary for drift detection.
Tests / notes
@agenta/entitiestests passed.@agenta/entitiesbuild/type-check passed.@agenta/entity-uitests passed.@agenta/entities,@agenta/entity-ui, and@agenta/settings-ui.pnpm lint-fixpassed. It reported four existing mobile hook warnings and no errors.docs/design/write-only-secrets/implementation-report.md.docs/design/write-only-secrets/qa.md.What to QA
secret_idthrough Fern and refresh models without exposing the key.This PR is stacked on #6195 (
fix/provider-probe-stored-key), whose chain is rooted inrelease/v0.114.0. Merge the stack in order: #6164, #6165, #6138, #6195, then #6174.