merge: candidate fav-staging-uuid fix into local_dev
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
|
||||
| owner | task | branch | worktree | mutex | status |
|
||||
|---|---|---|---|---|---|
|
||||
| Cursor | fix-fav-staging-uuid-2026-09-24 | fix/fix-fav-staging-uuid-2026-09-24 | .worktrees/fix-fav-staging-uuid-2026-09-24 | artifactvault | done |
|
||||
| Cursor | gate-e1a-unique-project-name-2026-09-24 | fix/gate-e1a-unique-project-name-2026-09-24 | .worktrees/gate-e1a-unique-project-name-2026-09-24 | docnotify | in_progress |
|
||||
| Cursor | gate-unhook-docquery-2026-09-24 | fix/gate-unhook-docquery-2026-09-24 | .worktrees/gate-unhook-docquery-2026-09-24 | server+docquery | in_progress |
|
||||
| Cursor | integrate-jev-assist-land-2026-09-24 | feature/integrate-jev-assist-land-2026-09-24 | .worktrees/integrate-jev-assist-land-2026-09-24 | git:dev | done |
|
||||
|
||||
@@ -249,12 +249,14 @@ func requestTX(ctx context.Context, tx pgx.Tx, facts Facts, req PublishRequest)
|
||||
st := &Staging{SourceEventID: req.SourceEventID, PayloadSHA256: sha, Payload: req.Payload}
|
||||
return &Artifact{UUID: existing, IdempotencyKey: key, PublicationStatus: StatusRequested}, st, nil
|
||||
}
|
||||
uuid := "art-" + sha[:16]
|
||||
// Derive UUIDs from the full idempotency key (includes source_event_id + sha).
|
||||
// Using payload sha alone collides when two events share identical bytes.
|
||||
uuid, stgUUID := artifactIDsFromKey(key)
|
||||
_, err = tx.Exec(ctx, `
|
||||
INSERT INTO artifact_payload_staging (staging_uuid, project_id, source_event_id, payload_sha256, encrypted_payload, classification)
|
||||
VALUES ($1,$2,$3,$4,$5,$6)
|
||||
ON CONFLICT (source_event_id, payload_sha256) DO NOTHING
|
||||
`, "stg-"+uuid, req.ProjectID, req.SourceEventID, sha, req.Payload, ClassificationOK)
|
||||
`, stgUUID, req.ProjectID, req.SourceEventID, sha, req.Payload, ClassificationOK)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -277,6 +279,11 @@ func requestTX(ctx context.Context, tx pgx.Tx, facts Facts, req PublishRequest)
|
||||
PayloadSHA256: sha, PublicationStatus: StatusRequested, TerminalState: req.TerminalState}, &Staging{Payload: req.Payload, PayloadSHA256: sha, SourceEventID: req.SourceEventID}, nil
|
||||
}
|
||||
|
||||
func artifactIDsFromKey(key string) (artUUID, stgUUID string) {
|
||||
idHash := SHA256Hex([]byte(key))[:16]
|
||||
return "art-" + idHash, "stg-" + idHash
|
||||
}
|
||||
|
||||
func nullInt(v int64) any {
|
||||
if v == 0 {
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package artifactvault
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestArtifactIDsFromKeyDifferForSamePayloadDifferentEvents(t *testing.T) {
|
||||
payload := []byte("# same body\n")
|
||||
sha := SHA256Hex(payload)
|
||||
reqA := PublishRequest{
|
||||
ArtifactType: "agent_commit", Environment: "dev", ProjectExternalKey: "p1",
|
||||
LogicalResourceID: "doc1", SourceEventKind: "taskrun", SourceEventID: "taskrun:runA:completed",
|
||||
}
|
||||
reqB := PublishRequest{
|
||||
ArtifactType: "agent_commit", Environment: "dev", ProjectExternalKey: "p1",
|
||||
LogicalResourceID: "doc1", SourceEventKind: "taskrun", SourceEventID: "taskrun:runB:completed",
|
||||
}
|
||||
keyA := IdempotencyKey(reqA, sha)
|
||||
keyB := IdempotencyKey(reqB, sha)
|
||||
if keyA == keyB {
|
||||
t.Fatal("idempotency keys must differ across source events")
|
||||
}
|
||||
artA, stgA := artifactIDsFromKey(keyA)
|
||||
artB, stgB := artifactIDsFromKey(keyB)
|
||||
if artA == artB || stgA == stgB {
|
||||
t.Fatalf("same-payload different events must not share UUIDs: art=%q/%q stg=%q/%q", artA, artB, stgA, stgB)
|
||||
}
|
||||
if artA == "art-"+sha[:16] || stgA == "stg-art-"+sha[:16] {
|
||||
t.Fatal("UUIDs must not be derived from payload sha alone")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user