Repository navigation
feat(secrets): registration API for secret_dependencies (#10088 Task 8.2) - #13065
Merged
Merged
Conversation
…ncies (#10088) Task 8.2 of umbrella #10088 already shipped the model/migration/service (061, PR #10375/#10381 under the umbrella's earlier numbering) plus a read-only GET /{secret_id}/dependencies query. The registration half never got an HTTP surface: SecretDependencyService.register/unregister were only callable in-process. Adds SecretsCoordinator.register_dependency/unregister_dependency (same write-authority gate as create/rotate/delete) and POST/DELETE /api/v2/secrets/{secret_id}/dependencies so 8.3's seed scanners and admins have something to call.
#10088) Register/read-back, idempotency through the coordinator (not just the service), unauthorized-caller rejection, and unknown-secret 404 for the new register_dependency/unregister_dependency methods.
Contributor
✅ SSOT Configuration Compliance: Passing🎉 No hardcoded values detected that have SSOT config equivalents! |
9 of 21 tasks
Auto-regenerated (py3.14) to match the backend schema so the required verify-generated-types gate passes. Triggered by auto-fix-generated-types.yml.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #13064
Thinking Path
Audited the whole of Task 8 (umbrella #10088) before touching anything, per the
FIFO-backlog instruction, because the umbrella still shows Task 8 entirely
unchecked and Task 9 flagged as a dependency-edge prerequisite.
Task 9 blocker check (does NOT block 8.2):
secrets_authz.authorize()hasan explicit marker —
# agent / service principals are refined in Task 9.2; default closed(autobot-backend/services/secrets_authz.py:117) — confirmingTask 9.2 (agent/service → effective principal for RBAC) is genuinely
incomplete for the access side of the graph. But
secret_dependenciesdoes not need an authenticated agent/service principal:
dependent_kind/dependent_idare descriptive strings naming what depends on a secret(
models/secret_dependency.py:44-54), not a vault/principal to authorizeagainst. The only identity the registration API needs is the caller doing
the registering, and that's already solved —
principal(user RBAC,api/envelope_secrets.py:60) and, separately,service_principal(HMAC /X-Internal-API-Key,api/envelope_secrets.py:72, landed via #10478) alreadyresolve callers today. Task 9 does not block 8.2.
8.1 audit (already done):
secret_grants.granteestores aVaultRefstring (
kind:id) — migration20260614_057_secrets_envelope_store.py:86-97— so every grant already carries grantee principal-type/id (folded into Task
2's schema exactly as the PRD says).
services/secrets_access_audit.py(
describe_secret_access, merged PR #10344) expandsteam:/role:/company:grants through the membership tables into effective member users —the RBAC-expansion the PRD calls for. Org coords concretely present: only
company_id(LLC company) — noproject_id/sprint_id/team_idcolumnsexist on any secrets table today;
agent_id/service_idare folded into thegeneric
dependent_kind/dependent_idpair rather than separate columns.8.2 audit (mostly already done, one real gap): grep found the model,
migration 061, and
SecretDependencyService(register/what_depends_on/secrets_for_dependent/unregister) already merged — under the umbrella's
earlier task numbering, PRs #10375/#10381 built exactly what current 8.2
describes, plus a
GET /{secret_id}/dependenciesquery endpoint (arguably8.4 scope, shipped early). Gap: no HTTP path to register a dependency —
SecretDependencyService.register/unregisterwere only callablein-process. Filed and closed by this PR: #13064.
Designed against real seed shapes rather than an imagined one: checked
AGENT_SECRET_MAPPINGS(services/agent_secrets_integration.py:53, keyed byagent_typestring like"interactive_terminal") and the workflow${secrets.NAME}reference format (services/workflow_secret_service.py,services/workflow_automation/executor.py) — both fitdependent_kind/dependent_idas plain strings, so 8.3's future seeders need no model change.No migration in this PR — 061 already has everything 8.2's model needs
(FK CASCADE, unique constraint for idempotency, optional
company_id).Adding new schema for the reason above would be speculative ahead of 8.3.
What Changed
SecretsCoordinator.register_dependency/.unregister_dependency(
autobot-backend/services/secrets_coordinator.py) — samewrite-authoritygate on the secret's owner vault as
create/rotate/delete(registering adependency is secret metadata, not a grant, so it doesn't need
share).POST /api/v2/secrets/{secret_id}/dependenciesandDELETE /api/v2/secrets/{secret_id}/dependencies/{dependent_kind}/{dependent_id}(
autobot-backend/api/envelope_secrets.py) — thin FastAPI shells over thecoordinator, same exception-mapping pattern as every other route in the
router.
Verification
py_compile/flake8 --max-line-length=120/black --check --line-length=120— clean on all 3 changed files.tests/migrations/test_secret_dependencies.py):register → read-back via
describe_dependencies; idempotent through thecoordinator (not just the service); unauthorized caller →
SecretAccessError;unknown secret →
SecretNotFoundError; unregister removes exactly one row.6 passed(was 5 before this PR — pre-existing model/service/migrationtests unaffected).
initdbprivate cluster, port5499) — did not touch the shared host cluster's
pg_hba.conf.cp-swapped baseline diff: reverted the 3 changed files viagit checkout --, rantest_secret_dependencies.py+test_raw_client_session_ceiling_12992.pytest_startup_imports.py→357 passed; restored viacp, reran →358 passed(the one new test). Identical failing set (0) before/after.tests/test_startup_imports.py) and the raw-ClientSessionceiling guard (
tests/test_raw_client_session_ceiling_12992.py) both includedin the before/after run above — unaffected.
Model Used
Claude Sonnet 5