Hi @atripp,
to be honest, I am still confused. Let me explain my approach in more detail:
So I created a test project which does not contain any builds yet:

I want to add build 1.0.0 to this project. To do so, I upload an SBOM file containing the information about version 1.0.0. I also promote this version to the stage "Release":

Now the worst case scenario happens. After months someone uploads a different sbom with version 1.0.0 to this project. I can confirm that the information from the "new" sbom gets added. But the build is also moved back to the stage "Build":

I would expect that the build remains in its stage. But maybe you have a valid reason to do it like this?
So now I used "Create Build" from the dropdown to manually create version 1.0.0 again, which leads to two versions 1.0.0:

If I now upload a SBOM for version 1.0.0 only the first version 1.0.0 gets modified. The second, manually created version 1.0.0 remains unchanged.
Further, I created a version 2.0.0 manually using "Create Build". Then I uploaded a SBOM for version 2.0.0, which again results in two builds with version 2.0.0:

As far as I understood your explanation, uploading a SBOM should have added the information to the already existing build 2.0.0 instead of creating a new build?
You also said that the constraint for duplicates is <Project_Id, Release_Number, Build_Number>
.
So for versions 1.0.0 the Project_Id as well as the Build_Number are the same. The Release_Number is empty for both builds (or not set):

Maybe that's a problem leading to having a build twice? But this seems to be the default when using pgutil to create and upload a SBOM. I am not really sure how this Release_Number property should be used and how it is set using pgutil.
But if this behavior is on purpose maybe you can again explain to me why?
Thanks
Caterina