Finding
The canonical corporate-entity catalog path correctly delays its explicit PostgreSQL transaction and pg_advisory_xact_lock until after hierarchy inference / external corroboration. However, get_or_create_corporate_entity(...) still receives a borrowed asyncpg.Connection and retains that pool lease while it performs potentially long asyncio.to_thread(...) inference and relation-verification calls, including recursive parent resolution.
The process pool is currently bounded at max_size=10. With enough concurrent catalog misses, provider latency can therefore consume all DB pool slots even though no transaction or explicit lock is held, delaying unrelated buyer read/write paths. #1055 adds Customer Master as another online caller of the same catalog owner, in addition to existing Keyman/post-summary ingestion paths, so this is now a buyer-visible resilience/performance boundary rather than a leaf implementation detail.
This is not a request to move catalog semantics into Customer Master, copy contextual-orchestrator routing, or weaken ADR 0010/0012/0160. The corporate-entity catalog remains the single canonical owner.
Realistic RED
Add a deterministic concurrency regression using the real pool contract or an equivalent integration harness:
- configure the pool at its production bound (
max_size=10) or a proportionally equivalent explicit test bound;
- start enough unresolved organization resolutions to occupy every catalog path while inference/verification is deliberately blocked on a controllable provider barrier;
- while those provider calls are blocked, issue an unrelated DB-only read through the same pool;
- RED if the unrelated DB operation cannot obtain a connection within a bounded local latency solely because catalog calls retain idle leases during provider I/O.
Do not fake success by enlarging the pool, shortening the provider barrier, excluding the wait from measurement, or warming a cache that bypasses the miss path.
Causal architecture
Refactor the canonical catalog service boundary so database ownership is short-lived:
- acquire briefly to load candidate/alias snapshots required for deterministic matching;
- release the DB lease before hierarchy inference, search corroboration, or other network/provider I/O;
- preserve tie fail-closed behavior, SKOS alias handling, recursion/cycle/depth invariants and parent corroboration outside an explicit transaction;
- reacquire only for the fresh candidate/alias re-check, named
pg_advisory_xact_lock, idempotent creation/update, and commit;
- on recursion, do not retain a parent connection while child/parent provider work executes;
- cancellation, timeout and provider exceptions must return every lease and leave no open transaction.
If a versioned repository/service abstraction is needed to express snapshot → external decision → short commit safely, keep that abstraction in the corporate-entity catalog bounded context. Callers consume it; they must not reproduce matching/creation SQL or provider selection.
Acceptance
- the concurrency RED above becomes GREEN without increasing the pool bound;
- no provider/network call executes while a DB connection is retained solely for later mutation, and no provider/network call executes inside an explicit transaction/advisory-lock scope;
- the final write still performs a fresh under-lock catalog check so concurrent duplicate creation remains prevented;
- existing ADR 0010/0012/0160 tie, alias, hierarchy, cycle/depth and idempotency tests remain GREEN;
- Keyman, post-summary and Customer Master callers preserve their current domain contracts and consume the same canonical catalog service;
- connection cleanup is proven for success, provider timeout/error and task cancellation;
- add an async buyer-path measurement (deterministic integration test and, where practical, k6/API evidence) showing an unrelated DB-only path remains serviceable while catalog provider calls are blocked;
- record the connection-ownership decision in ARCHITECTURE/ADR/OPERABILITY/TEST_STRATEGY as appropriate.
Serialization
Do not modify #1055 merely to start this follow-on while its current exact-head Strix admission is still running. Preserve single-writer/evidence boundaries: settle #1055 first, then implement this owner-level catalog repair on the then-current protected ancestry or through an already-existing verified successor if one appears.
No pool-size workaround, provider/model override, cross-service SQL, source-neutral validation commit, warning suppression, force push, destructive rebase, or gate weakening.
Finding
The canonical corporate-entity catalog path correctly delays its explicit PostgreSQL transaction and
pg_advisory_xact_lockuntil after hierarchy inference / external corroboration. However,get_or_create_corporate_entity(...)still receives a borrowedasyncpg.Connectionand retains that pool lease while it performs potentially longasyncio.to_thread(...)inference and relation-verification calls, including recursive parent resolution.The process pool is currently bounded at
max_size=10. With enough concurrent catalog misses, provider latency can therefore consume all DB pool slots even though no transaction or explicit lock is held, delaying unrelated buyer read/write paths. #1055 adds Customer Master as another online caller of the same catalog owner, in addition to existing Keyman/post-summary ingestion paths, so this is now a buyer-visible resilience/performance boundary rather than a leaf implementation detail.This is not a request to move catalog semantics into Customer Master, copy contextual-orchestrator routing, or weaken ADR 0010/0012/0160. The corporate-entity catalog remains the single canonical owner.
Realistic RED
Add a deterministic concurrency regression using the real pool contract or an equivalent integration harness:
max_size=10) or a proportionally equivalent explicit test bound;Do not fake success by enlarging the pool, shortening the provider barrier, excluding the wait from measurement, or warming a cache that bypasses the miss path.
Causal architecture
Refactor the canonical catalog service boundary so database ownership is short-lived:
pg_advisory_xact_lock, idempotent creation/update, and commit;If a versioned repository/service abstraction is needed to express snapshot → external decision → short commit safely, keep that abstraction in the corporate-entity catalog bounded context. Callers consume it; they must not reproduce matching/creation SQL or provider selection.
Acceptance
Serialization
Do not modify #1055 merely to start this follow-on while its current exact-head Strix admission is still running. Preserve single-writer/evidence boundaries: settle #1055 first, then implement this owner-level catalog repair on the then-current protected ancestry or through an already-existing verified successor if one appears.
No pool-size workaround, provider/model override, cross-service SQL, source-neutral validation commit, warning suppression, force push, destructive rebase, or gate weakening.