fix(registry): catalog import derives vendor-doubled api_name; warn on unmatched credential scope - #1067
Open
ren-jentic wants to merge 4 commits into
Open
fix(registry): catalog import derives vendor-doubled api_name; warn on unmatched credential scope#1067ren-jentic wants to merge 4 commits into
ren-jentic wants to merge 4 commits into
Conversation
…1020) Co-authored-by: Cursor <cursoragent@cursor.com>
…o imported API (#1020) Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Review follow-ups on the credential-create advisory and the catalog identity guard: - time-bound the best-effort registry probe (asyncio.timeout 2s) so a hung registry DB cannot stall POST /credentials; gate on has_db so a never-connected context skips instead of logging on every create - type the guard's refusal as CatalogIdentityConflictError, take the guard read FOR UPDATE (closes the READ COMMITTED backfill race), and map uq_apis_vendor_name_version to a readable job error - keep the unmatched-api event summary short and bounded; move the remedy + sibling-identity hint to detail and carry credential_id in data; name both remedies (import vs delete-and-re-create) in the warning; fix the emit-failure log misattribution - tests: e2e catalog import lands the clean identity through the real _to_import_source -> ImportHandler seam; the conflict surfaces as a readable job failure; POST /credentials web tests for the warnings field; version-only wildcard, standalone-skip and registry-error probe branches; promote the shared SQLite apis fixture to conftest Co-authored-by: Cursor <cursoragent@cursor.com>
This was referenced Aug 18, 2026
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.
Summary
A plain
jentic catalog import <domain/sub>seeded the ingestapi_namewith the full catalog id, which slugification collapsed into a vendor-doubled workspace identity (posthog-com/posthog-com-posthog-api) that no other surface agrees with — and since credential creation accepts an unvalidated API reference, a credential bound to the expected clean name silently never matched and every execute 403'd withno_toolkit_binding. This fixes the identity derivation at import time and surfaces the credential-scope mismatch at create time instead of at execute time.Plan:
jentic-one-plans/issues/issue-1020-catalog-import-vendor-doubled-api-name.md.Changes
_to_import_sourceseedsapi_namefrom the catalog id's sub segment (posthog.com/posthog-api→posthog-api), so the workspace identity matches the catalog path, repo layout, and broker upstream registration. Bare-domain entries (coincap.io) keep their established identity.ResolveApiStage— two distinct catalog entries that collapse to the same registry identity (stripe.com/xvsapi.stripe.com/x, possible now that names are clean) refuse the import with a readablecatalog identity conflicterror instead of silently stacking a foreign spec as a new revision. Same-id re-imports and NULL backfills (Persist the catalog identity (api_id) at import and expose it on credential/binding/API DTOs #910 semantics) are unchanged.CredentialService.createnow checks (best-effort) whether the canonical scope covers any imported registry API, via a new raw-SQLRegistryApiLookupRepositoryfollowing the broker's cross-tier pattern (no cross-imports). On a miss it warns, never rejects:warningsfield on the create response, a new warning-severitycredential.unmatched_apievent, and a structured log — with a nearest-identity hint naming the vendor's imported APIs. Skipped on standalone control deployments (no registry DB) and on registry read errors.make openapi).Risk & rollback
warnings, nullable) onPOST /credentials— additive, no client breakage.credential.unmatched_api— UI event rail falls back to the generic credential icon for unknowncredential.*types.domain/subentries; existing workspace rows are untouched (re-importing one after upgrade creates the clean identity alongside the old doubled row — resolved properly by the follow-up migration).Test plan
make lint(ruff + mypy) clean;tests/arch274 passedmake test-fast,make test-integration(Postgres),make test-integration-sqlite— all greentests/unit/registry/ingest/test_extract_api_catalog_conflict.py(collision guard, real SQLite DB),tests/integration/control/test_credential_unmatched_api_warning.py(cross-DB: registry seed → control create → admin event), updatedtests/web/registry/test_catalog.pyto pin the sub-segment derivationmaincheckout):test_spec_is_valid[broker](needs network for a remote$ref),make score(private npm package 404)Review follow-ups (8-lens deep review)
Hardening applied in this PR after review:
asyncio.timeout(2s)and gated onhas_db("registry")— a hung or never-connected registry DB can neither stallPOST /credentialsnor log-spam; timeouts land in the existing best-effort fallback.CatalogIdentityConflictErrornaming both catalog ids and the next step; the guard read takesFOR UPDATE(closes the READ COMMITTED backfill race where two colliding imports could both pass);uq_apis_vendor_name_versionmaps to a readable job error for the insert race.credential.unmatched_apinow carries a short bounded summary (fits the 512-char column and one-line UI rows), the remedy + sibling-identity hint indetail, andcredential_idindata; warning text names both remedies (import the API, or delete + re-create the immutable-scope credential); emit-failure log no longer misattributes an event type._to_import_source→ImportHandlerseam asserting the clean identity lands; conflict surfacing as a readable job failure;POST /credentialsweb tests for thewarningsfield (present + null); version-only wildcard, standalone-control skip, and registry-error probe branches; shared SQLiteapisfixture promoted totests/unit/registry/conftest.py.Ticketed follow-ups: #1076 (UI surfaces
warnings), #1077 (unmatched-api event race with the import job), #1078 (A4b transition edge over doubled rows), #1079 (Phase 3 migration of existing doubled identities).Closes #1020
Made with Cursor