Scope sub-third-parties per parent

Replace the many-to-many junction table with a direct
parent_third_party_id foreign key on third_parties. Each
sub-third-party now belongs to exactly one parent, making
duplicates across parents independent entities.

Replace the firstLevel boolean with an integer level field
(1 = direct, 2+ = parent level + 1) to support arbitrary
nesting depth.

Remove the createThirdPartyThirdPartyMapping and
deleteThirdPartyThirdPartyMapping mutations, the CLI
link/unlink commands, and the corresponding MCP tools.
Creating a child third party now just requires passing
parentThirdPartyId on the existing createThirdParty mutation.

The frontend walks the parentThirdParty chain to build
display names like "Name (Ancestor1/Ancestor2)" and shows
clickable ancestor links on the detail page.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-05-29 16:22:54 +02:00
parent ec858e58df
commit b6781d3de0
36 changed files with 1276 additions and 1192 deletions

View File

@@ -89,9 +89,14 @@ func SaveThirdPartyInfoTool(pc *PersistenceContext) agent.Tool {
}
}
ancestorBaseNames, err := loadAncestorBaseNames(ctx, conn, scope, thirdParty.ID)
if err != nil {
return err
}
applySaveParams(thirdParty, pc.WebsiteURL, saveThirdPartyInfoParams{
saveThirdPartyInfoToolParams: p,
})
}, ancestorBaseNames)
thirdParty.UpdatedAt = time.Now()
if err := thirdParty.Update(ctx, conn, scope); err != nil {
@@ -124,7 +129,20 @@ func LinkSubThirdPartyTool(pc *PersistenceContext) agent.Tool {
err := pc.PG.WithTx(
ctx,
func(ctx context.Context, conn pg.Tx) error {
return linkSubThirdParty(ctx, conn, scope, pc, p)
parent := &coredata.ThirdParty{}
if err := parent.LoadByID(ctx, conn, scope, pc.ThirdPartyID); err != nil {
return fmt.Errorf("cannot load parent third party: %w", err)
}
ancestorBaseNames, err := loadAncestorBaseNames(ctx, conn, scope, pc.ThirdPartyID)
if err != nil {
return err
}
// Child suffix path is the parent's ancestors plus the parent itself.
childNamePath := append(ancestorBaseNames, baseThirdPartyName(parent.Name))
return linkSubThirdParty(ctx, conn, scope, pc, parent.Level, childNamePath, p)
},
)
if err != nil {