Skip to content

security: separate resolved customer identity from source-post tenant ownership #1052

Description

@seonghobae

Protected main@83eba56149eb802cd63642c507c324c9976ec78e has the Customer Master tenant-boundary/domain-model defect reproduced in POST /api/customer-master/resolve-hint: resolved customer identity had been conflated with source_post.corporate_entity_id, which is authorization ownership. Accepted ADR 0042 requires raw customer identifiers to remain evidence and resolved catalog identity/provenance to be stored separately.

#1055 remains the single LineageWeave source repair lane at exact 50c4935eef1029467595f7004818643598b737c9, now Draft. The validation-only Ready admission ended after Strix terminalized. Repository Tests 34746058653 (including full PostgreSQL/frontend), Security 34746058657, SAST 34746058639, and Strix 34746057545 are terminal SUCCESS. Required CodeQL 34746058693, Noema 34746057619, and OpenCode 34746057593 remain terminal FAILURE at their canonical owner boundaries (.github#1929/#2106, contextual-orchestrator#1106, .github#2045 respectively); no leaf workaround or synthetic status is permitted.

Strix job 103694153476 completed Run Strix (quick) successfully and uploaded artifact 10318318320, digest sha256:45c82c7f1f044185a4795b4b4db37d2ce30346e44e516ce027f2bf53fe89581e. Artifact inspection is material: it contains one Medium CWE-862 finding. The post_read-gated GET /api/posts/{post_id}/summary can derive a missing summary and pass live hierarchy/verification clients to persist_post_summary, which can create/update the shared global corporate_entity catalog. Protected main independently contains the same path. This is tracked as #1078 and is a promotion blocker; Strix workflow SUCCESS must not be interpreted as zero findings.

The #1055 Customer Master repair itself preserves source corporate/process authorization ownership, stores resolution in migration 0250, delegates catalog binding to the existing corporate-entity owner, runs external corroboration after releasing source-evidence DB ownership, then reacquires a short transaction to revalidate/share-lock the exact captured source set and idempotently persist the association. Raw source_post.source_customer_code evidence is preserved; request matching is normalized; blank-only input fails 422; tied exact catalog labels fail closed; Customer Master projects one coherent latest resolution row. ADR 0374 remains Proposed until protected integration.

The public response/shared-eligibility contracts remain current. Current exact head includes the minimal fixture repair for qualified source_post.* SQL; production authorization/persistence semantics were not weakened. Real PostgreSQL + Keycloak + Valkey authenticated topology remains #1057's owner and must not be duplicated here.

A separate buyer-path resilience gap remains #1077: canonical corporate-entity resolution can retain a borrowed asyncpg pool lease across hierarchy/provider I/O despite correctly delaying explicit transaction/advisory locking. #1077 controls resource ownership; #1078 controls mutation authorization. They are distinct invariants and neither moves catalog semantics into Customer Master or contextual-orchestrator.

Acceptance remains: caller-scoped evidence only; source tenant/process ownership never rewritten; normalized/idempotent resolution association with raw provenance; canonical catalog-owner consumption; no external network call while source-row transaction/explicit lock is held; stale/concurrent scope changes fail closed; parameter-bound authorization; ordinary-hosted response-shape and shared-eligibility contracts; #1057 real-service authenticated cross-tenant E2E; #1078 RED→GREEN and Strix closure; touched production docstring acceptance; resolved review threads; and one unchanged current product head with repository/PostgreSQL/frontend, Security/SAST/Required CodeQL, terminal acceptable Strix/OpenCode/Noema, and qualifying independent approval GREEN before normal protected integration.

No broad post_admin substitution for summary reads, Keyverse copy, source-field rebinding, local catalog algorithm, cross-service SQL, warning suppression, skipped-E2E-as-GREEN claim, provider/model override, no-op validation churn, lifecycle flip loop, fabricated status, or pool-size workaround.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions