Fix TGK store conflict error mapping and add regression test

This commit is contained in:
Carl Niklas Rydberg 2025-12-22 11:50:00 +01:00
parent 222fe2f84e
commit d0005e54c3
3 changed files with 131 additions and 2 deletions

View file

@ -40,7 +40,7 @@ Status legend: ✅ completed, ⬜ pending.
12. ✅ `tier1/enc-pel-trace-dag-1.md`
13. ✅ `tier1/tgk-1-core.md`
14. ✅ `tier1/enc-tgk1-edge-1.md`
15. `tier1/tgk-store-1.md`
15. `tier1/tgk-store-1.md`
16. ⬜ `tier1/tgk-prov-1.md`
17. ⬜ `tier1/opreg-pel1-kernel.md`
18. ⬜ `tier1/opreg-pel1-kernel-params-1.md`
@ -214,3 +214,14 @@ Status legend: ✅ completed, ⬜ pending.
edge references.
- Tests: command not provided — pass (user reported “100% tests passed, 0 tests
failed out of 14”).
## 2025-12-22 — TGK/STORE/1 (`tier1/tgk-store-1.md`)
- Scope: graph store configuration, edge resolution error mapping, adjacency
ordering, scan/pagination, and neighbor semantics for TGK store adapters.
- Findings: `resolve_edge` maps conflicting artifacts (same `EdgeRef` with
different bytes) to `GS_ERR_INTEGRITY`, but the spec requires artifact-layer
integrity conflicts from `resolve_artifact` to surface as
`GS_ERR_ARTIFACT_ERROR`.
- Resolution: mapped conflicting artifacts during `resolve_edge` to
`GS_ERR_ARTIFACT_ERROR` to match artifact-level integrity error handling.
- Tests: user reported “100% tests passed, 0 tests failed out of 14”.

View file

@ -977,7 +977,7 @@ static amduat_tgk_graph_error_t amduat_tgk_store_mem_resolve_edge(
}
entry = amduat_tgk_store_mem_lookup_artifact(mem, ref, &conflict);
if (conflict) {
return GS_ERR_INTEGRITY;
return GS_ERR_ARTIFACT_ERROR;
}
if (entry == NULL) {
return GS_ERR_ARTIFACT_ERROR;

View file

@ -640,6 +640,123 @@ static int test_duplicate_edge_ref_conflict(void) {
return 0;
}
static int test_resolve_edge_conflict_maps_artifact_error(void) {
amduat_tgk_store_mem_t mem;
amduat_tgk_store_t store;
amduat_tgk_store_config_t config;
amduat_tgk_identity_domain_t domains[1];
uint32_t edge_tags[1];
amduat_tgk_edge_type_id_t edge_types[1];
amduat_asl_encoding_profile_id_t encodings[1];
amduat_tgk_store_mem_artifact_t artifacts[2];
amduat_tgk_edge_body_t edge_a;
amduat_tgk_edge_body_t edge_b;
amduat_reference_t from_refs[1];
amduat_reference_t to_refs[1];
amduat_reference_t ref_edge;
amduat_reference_t node_a;
amduat_reference_t node_b;
amduat_reference_t payload_a;
amduat_reference_t payload_b;
amduat_octets_t bytes_a;
amduat_octets_t bytes_b;
amduat_tgk_graph_error_t err;
uint8_t digest_edge[32];
uint8_t digest_a[32];
uint8_t digest_b[32];
uint8_t digest_payload_a[32];
uint8_t digest_payload_b[32];
int exit_code = 1;
memset(&mem, 0, sizeof(mem));
memset(&store, 0, sizeof(store));
memset(&config, 0, sizeof(config));
memset(&edge_a, 0, sizeof(edge_a));
memset(&edge_b, 0, sizeof(edge_b));
bytes_a = amduat_octets(NULL, 0);
bytes_b = amduat_octets(NULL, 0);
domains[0].encoding_profile = AMDUAT_ENC_ASL1_CORE_V1;
domains[0].hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
edge_tags[0] = TYPE_TAG_TGK1_EDGE_V1;
edge_types[0] = 0x10;
encodings[0] = TGK1_EDGE_ENC_V1;
config.id_space.domains = domains;
config.id_space.domains_len = 1;
config.tgk_profiles.edge_tags = edge_tags;
config.tgk_profiles.edge_tags_len = 1;
config.tgk_profiles.edge_types = edge_types;
config.tgk_profiles.edge_types_len = 1;
config.tgk_profiles.encodings = encodings;
config.tgk_profiles.encodings_len = 1;
if (!amduat_tgk_store_mem_init(&mem, config, NULL, 0)) {
fprintf(stderr, "conflict resolve init failed\n");
return 1;
}
ref_edge = make_ref(0x72, digest_edge);
node_a = make_ref(0xa1, digest_a);
node_b = make_ref(0xb1, digest_b);
payload_a = make_ref(0xe1, digest_payload_a);
payload_b = make_ref(0xe2, digest_payload_b);
edge_a.type = 0x10;
from_refs[0] = node_a;
edge_a.from = from_refs;
edge_a.from_len = 1;
to_refs[0] = node_b;
edge_a.to = to_refs;
edge_a.to_len = 1;
edge_a.payload = payload_a;
edge_b.type = 0x10;
edge_b.from = from_refs;
edge_b.from_len = 1;
edge_b.to = to_refs;
edge_b.to_len = 1;
edge_b.payload = payload_b;
if (!amduat_enc_tgk1_edge_encode_v1(&edge_a, &bytes_a) ||
!amduat_enc_tgk1_edge_encode_v1(&edge_b, &bytes_b)) {
fprintf(stderr, "conflict resolve encode failed\n");
goto cleanup_mem;
}
artifacts[0].ref = ref_edge;
artifacts[0].artifact =
amduat_artifact_with_type(bytes_a,
amduat_type_tag(TYPE_TAG_TGK1_EDGE_V1));
artifacts[1].ref = ref_edge;
artifacts[1].artifact =
amduat_artifact_with_type(bytes_b,
amduat_type_tag(TYPE_TAG_TGK1_EDGE_V1));
mem.artifacts = artifacts;
mem.artifacts_len = 2;
mem.artifacts_cap = 2;
amduat_tgk_store_init(&store, config, amduat_tgk_store_mem_ops(), &mem);
err = amduat_tgk_store_resolve_edge(&store, ref_edge, &edge_a);
if (err != GS_ERR_ARTIFACT_ERROR) {
fprintf(stderr, "resolve_edge conflict error mismatch: %d\n", err);
goto cleanup_mem;
}
exit_code = 0;
cleanup_mem:
mem.artifacts = NULL;
mem.artifacts_len = 0;
mem.artifacts_cap = 0;
amduat_tgk_store_mem_free(&mem);
free((void *)bytes_a.data);
free((void *)bytes_b.data);
return exit_code;
}
static int ref_cmp(const void *a, const void *b) {
const amduat_reference_t *ref_a = (const amduat_reference_t *)a;
const amduat_reference_t *ref_b = (const amduat_reference_t *)b;
@ -1437,6 +1554,7 @@ int main(void) {
test_init_rejects_invalid_profile_config() != 0 ||
test_duplicate_edge_ref_same_artifact() != 0 ||
test_duplicate_edge_ref_conflict() != 0 ||
test_resolve_edge_conflict_maps_artifact_error() != 0 ||
test_scan_edges_pagination() != 0 ||
test_ingest_remove_epoch() != 0 ||
test_ingest_batch_epoch() != 0 ||