diff --git a/src/amduatd.c b/src/amduatd.c index cae7b09..94ee145 100644 --- a/src/amduatd.c +++ b/src/amduatd.c @@ -8,6 +8,7 @@ #include "amduat/asl/collection_view.h" #include "amduat/asl/none.h" #include "amduat/asl/record.h" +#include "amduat/asl/asl_pointer_fs.h" #include "amduat/asl/asl_store_fs.h" #include "amduat/asl/asl_store_fs_meta.h" #include "amduat/asl/ref_text.h" @@ -86,9 +87,16 @@ static const char *const AMDUATD_DEFAULT_SOCK = "amduatd.sock"; static const char *const AMDUATD_EDGES_FILE = ".amduatd.edges"; static const char *const AMDUATD_EDGE_COLLECTION = "daemon/edges"; static const uint64_t AMDUATD_FED_TICK_MS = 1000u; +static const uint32_t AMDUATD_EDGE_VIEW_BATCH = 1024u; static const uint16_t AMDUATD_EDGE_COLLECTION_KIND = 1u; +typedef struct { + const char *space_id; + bool space_enabled; + bool migrate_unscoped_edges; +} amduatd_cfg_t; + typedef struct { amduat_reference_t record_ref; amduat_reference_t src_ref; @@ -166,6 +174,7 @@ static bool amduatd_edge_list_push(amduatd_edge_list_t *list, typedef struct { const char *root_path; char edges_path[1024]; + char *edge_collection_name; amduat_reference_t rel_aliases_ref; amduat_reference_t rel_materializes_ref; amduat_reference_t rel_represents_ref; @@ -205,6 +214,8 @@ static void amduatd_concepts_free(amduatd_concepts_t *c) { amduat_reference_free(&c->rel_computed_by_ref); amduat_reference_free(&c->rel_has_provenance_ref); amduatd_edge_list_clear(&c->edges); + free(c->edge_collection_name); + c->edge_collection_name = NULL; } enum { @@ -1432,6 +1443,193 @@ static bool amduatd_name_valid(const char *name) { return true; } +static bool amduatd_strdup_cstr(const char *s, char **out) { + size_t len; + char *buf; + + if (out == NULL) { + return false; + } + *out = NULL; + if (s == NULL) { + return false; + } + len = strlen(s); + if (len > SIZE_MAX - 1u) { + return false; + } + buf = (char *)malloc(len + 1u); + if (buf == NULL) { + return false; + } + if (len != 0) { + memcpy(buf, s, len); + } + buf[len] = '\0'; + *out = buf; + return true; +} + +static bool amduatd_space_id_valid(const char *space_id) { + if (space_id == NULL || space_id[0] == '\0') { + return false; + } + if (strchr(space_id, '/') != NULL) { + return false; + } + return amduat_asl_pointer_name_is_valid(space_id); +} + +static void amduatd_log_scoped_name(const amduatd_cfg_t *cfg, + const char *user_name, + const char *scoped_name) { + if (cfg == NULL || !cfg->space_enabled) { + return; + } + if (user_name == NULL || scoped_name == NULL) { + return; + } + amduat_log(AMDUAT_LOG_DEBUG, "%s -> %s", user_name, scoped_name); +} + +static bool amduatd_scope_name(const amduatd_cfg_t *cfg, + const char *user_name, + amduat_octets_t *out_scoped_name) { + char *buf = NULL; + size_t user_len = 0; + size_t space_len = 0; + size_t total_len = 0; + size_t offset = 0; + + if (out_scoped_name != NULL) { + *out_scoped_name = amduat_octets(NULL, 0u); + } + if (user_name == NULL || out_scoped_name == NULL) { + return false; + } + if (cfg == NULL || !cfg->space_enabled || cfg->space_id == NULL) { + if (!amduatd_name_valid(user_name)) { + return false; + } + if (!amduatd_strdup_cstr(user_name, &buf)) { + return false; + } + *out_scoped_name = amduat_octets((const uint8_t *)buf, strlen(buf)); + return true; + } + if (strncmp(user_name, "space/", 6) == 0) { + return false; + } + if (!amduat_asl_pointer_name_is_valid(user_name)) { + return false; + } + if (!amduatd_space_id_valid(cfg->space_id)) { + return false; + } + user_len = strlen(user_name); + space_len = strlen(cfg->space_id); + if (space_len > SIZE_MAX - 7u || + user_len > SIZE_MAX - (7u + space_len)) { + return false; + } + total_len = 6u + space_len + 1u + user_len; + buf = (char *)malloc(total_len + 1u); + if (buf == NULL) { + return false; + } + memcpy(buf + offset, "space/", 6u); + offset += 6u; + memcpy(buf + offset, cfg->space_id, space_len); + offset += space_len; + buf[offset++] = '/'; + if (user_len != 0) { + memcpy(buf + offset, user_name, user_len); + offset += user_len; + } + buf[offset] = '\0'; + if (!amduat_asl_pointer_name_is_valid(buf)) { + free(buf); + return false; + } + *out_scoped_name = amduat_octets((const uint8_t *)buf, total_len); + return true; +} + +static bool amduatd_scope_name_cstr(const amduatd_cfg_t *cfg, + const char *user_name, + char **out_scoped_name) { + amduat_octets_t scoped; + + if (out_scoped_name != NULL) { + *out_scoped_name = NULL; + } + if (out_scoped_name == NULL) { + return false; + } + if (!amduatd_scope_name(cfg, user_name, &scoped)) { + return false; + } + *out_scoped_name = (char *)scoped.data; + return *out_scoped_name != NULL; +} + +static bool amduatd_unscoped_name(const amduatd_cfg_t *cfg, + const char *scoped_name, + char *out, + size_t cap) { + const char *suffix = NULL; + size_t suffix_len = 0; + + if (out != NULL && cap != 0) { + out[0] = '\0'; + } + if (out == NULL || cap == 0 || scoped_name == NULL) { + return false; + } + if (cfg == NULL || !cfg->space_enabled || cfg->space_id == NULL) { + size_t len = strlen(scoped_name); + if (!amduatd_name_valid(scoped_name)) { + return false; + } + if (len >= cap) { + return false; + } + memcpy(out, scoped_name, len); + out[len] = '\0'; + return true; + } + if (!amduatd_space_id_valid(cfg->space_id)) { + return false; + } + { + size_t space_len = strlen(cfg->space_id); + size_t prefix_len = 6u + space_len + 1u; + if (strncmp(scoped_name, "space/", 6u) != 0) { + return false; + } + if (strncmp(scoped_name + 6u, cfg->space_id, space_len) != 0) { + return false; + } + if (scoped_name[6u + space_len] != '/') { + return false; + } + suffix = scoped_name + prefix_len; + } + if (suffix == NULL || suffix[0] == '\0') { + return false; + } + if (!amduat_asl_pointer_name_is_valid(suffix)) { + return false; + } + suffix_len = strlen(suffix); + if (suffix_len >= cap) { + return false; + } + memcpy(out, suffix, suffix_len); + out[suffix_len] = '\0'; + return true; +} + static bool amduatd_build_prefixed_bytes(const char *prefix, const char *text, uint8_t **out, @@ -1470,11 +1668,14 @@ static bool amduatd_build_prefixed_bytes(const char *prefix, static bool amduatd_concepts_seed_relation(amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, + const amduatd_cfg_t *dcfg, const char *relation_name, amduat_reference_t *out_ref) { uint8_t *bytes = NULL; size_t bytes_len = 0; amduat_artifact_t artifact; + char *scoped_name = NULL; + bool ok = false; if (out_ref == NULL) { return false; @@ -1483,32 +1684,45 @@ static bool amduatd_concepts_seed_relation(amduat_asl_store_t *store, if (store == NULL || cfg == NULL || relation_name == NULL) { return false; } - if (!amduatd_build_prefixed_bytes("AMDUATD/RELATION/1", relation_name, &bytes, - &bytes_len)) { + if (dcfg != NULL && dcfg->space_enabled) { + if (!amduatd_scope_name_cstr(dcfg, relation_name, &scoped_name)) { + return false; + } + } else if (!amduatd_strdup_cstr(relation_name, &scoped_name)) { return false; } + if (!amduatd_build_prefixed_bytes("AMDUATD/RELATION/1", scoped_name, &bytes, + &bytes_len)) { + goto seed_cleanup; + } artifact = amduat_artifact(amduat_octets(bytes, bytes_len)); if (!amduat_asl_ref_derive(artifact, cfg->config.encoding_profile_id, cfg->config.hash_id, out_ref, NULL)) { - free(bytes); - return false; + goto seed_cleanup; } (void)amduat_asl_store_put(store, artifact, out_ref); + ok = true; + +seed_cleanup: free(bytes); - return true; + free(scoped_name); + return ok; } static bool amduatd_concepts_ensure_alias(amduatd_concepts_t *c, amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, + const amduatd_cfg_t *dcfg, const char *alias_name, amduat_reference_t concept_ref) { amduat_reference_t existing; amduat_reference_t name_ref; amduat_reference_t edge_ref; + char *scoped_name = NULL; + bool ok = false; memset(&existing, 0, sizeof(existing)); memset(&name_ref, 0, sizeof(name_ref)); @@ -1517,15 +1731,20 @@ static bool amduatd_concepts_ensure_alias(amduatd_concepts_t *c, if (c == NULL || store == NULL || cfg == NULL || alias_name == NULL) { return false; } - if (!amduatd_name_valid(alias_name)) { + if (!amduatd_scope_name_cstr(dcfg, alias_name, &scoped_name)) { + amduat_log(AMDUAT_LOG_ERROR, + "ensure alias: scope failed for %s", alias_name); return false; } - if (amduatd_concepts_lookup_alias(store, cfg, c, alias_name, &existing)) { + if (amduatd_concepts_lookup_alias(store, cfg, c, scoped_name, &existing)) { amduat_reference_free(&existing); - return true; + ok = true; + goto alias_cleanup; } - if (!amduatd_concepts_put_name_artifact(store, alias_name, &name_ref)) { - return false; + if (!amduatd_concepts_put_name_artifact(store, scoped_name, &name_ref)) { + amduat_log(AMDUAT_LOG_ERROR, + "ensure alias: name artifact failed for %s", scoped_name); + goto alias_cleanup; } if (!amduatd_concepts_put_edge(store, c, @@ -1534,18 +1753,23 @@ static bool amduatd_concepts_ensure_alias(amduatd_concepts_t *c, c->rel_aliases_ref, amduat_octets(NULL, 0u), &edge_ref)) { - amduat_reference_free(&name_ref); - amduat_reference_free(&edge_ref); - return false; + amduat_log(AMDUAT_LOG_ERROR, + "ensure alias: put edge failed for %s", scoped_name); + goto alias_cleanup; } + ok = true; + +alias_cleanup: amduat_reference_free(&name_ref); amduat_reference_free(&edge_ref); - return true; + free(scoped_name); + return ok; } static bool amduatd_concepts_load_edges(amduatd_concepts_t *c, amduat_asl_store_t *store) { amduat_asl_collection_view_t view; + uint64_t from = 0u; bool ok = false; if (c == NULL || store == NULL) { @@ -1554,61 +1778,69 @@ static bool amduatd_concepts_load_edges(amduatd_concepts_t *c, amduatd_edge_list_clear(&c->edges); - memset(&view, 0, sizeof(view)); - if (!amduatd_collection_view(store, - c->root_path, - AMDUATD_EDGE_COLLECTION, - 0u, - UINT32_MAX, - &view)) { - return false; - } - - for (size_t i = 0u; i < view.refs_len; ++i) { - amduat_reference_t record_ref = view.refs[i]; - amduat_asl_record_t record; - amduat_reference_t src_ref; - amduat_reference_t dst_ref; - char *rel = NULL; - amduatd_edge_entry_t entry; - amduat_asl_store_error_t err; - bool schema_ok = false; - - memset(&record, 0, sizeof(record)); - err = amduat_asl_record_store_get(store, record_ref, &record); - if (err != AMDUAT_ASL_STORE_OK) { - continue; + while (true) { + memset(&view, 0, sizeof(view)); + if (!amduatd_collection_view(store, + c->root_path, + c->edge_collection_name, + from, + AMDUATD_EDGE_VIEW_BATCH, + &view)) { + return false; } - if (record.schema.len == strlen(AMDUATD_EDGE_SCHEMA) && - memcmp(record.schema.data, AMDUATD_EDGE_SCHEMA, - record.schema.len) == 0) { - schema_ok = true; - } - if (!schema_ok || - !amduatd_edge_payload_decode(record.payload, - &src_ref, - &dst_ref, - &rel)) { + + for (size_t i = 0u; i < view.refs_len; ++i) { + amduat_reference_t record_ref = view.refs[i]; + amduat_asl_record_t record; + amduat_reference_t src_ref; + amduat_reference_t dst_ref; + char *rel = NULL; + amduatd_edge_entry_t entry; + amduat_asl_store_error_t err; + bool schema_ok = false; + + memset(&record, 0, sizeof(record)); + err = amduat_asl_record_store_get(store, record_ref, &record); + if (err != AMDUAT_ASL_STORE_OK) { + continue; + } + if (record.schema.len == strlen(AMDUATD_EDGE_SCHEMA) && + memcmp(record.schema.data, AMDUATD_EDGE_SCHEMA, + record.schema.len) == 0) { + schema_ok = true; + } + if (!schema_ok || + !amduatd_edge_payload_decode(record.payload, + &src_ref, + &dst_ref, + &rel)) { + amduat_asl_record_free(&record); + continue; + } amduat_asl_record_free(&record); - continue; - } - amduat_asl_record_free(&record); - memset(&entry, 0, sizeof(entry)); - if (!amduat_reference_clone(record_ref, &entry.record_ref)) { - amduat_reference_free(&src_ref); - amduat_reference_free(&dst_ref); - free(rel); - goto load_cleanup; - } - entry.src_ref = src_ref; - entry.dst_ref = dst_ref; - entry.rel = rel; - if (!amduatd_edge_list_push(&c->edges, &entry)) { + memset(&entry, 0, sizeof(entry)); + if (!amduat_reference_clone(record_ref, &entry.record_ref)) { + amduat_reference_free(&src_ref); + amduat_reference_free(&dst_ref); + free(rel); + goto load_cleanup; + } + entry.src_ref = src_ref; + entry.dst_ref = dst_ref; + entry.rel = rel; + if (!amduatd_edge_list_push(&c->edges, &entry)) { + amduatd_edge_entry_free(&entry); + goto load_cleanup; + } amduatd_edge_entry_free(&entry); - goto load_cleanup; } - amduatd_edge_entry_free(&entry); + + if (view.refs_len == 0u || view.computed_up_to_offset <= from) { + break; + } + from = view.computed_up_to_offset; + amduat_asl_collection_view_free(&view); } ok = true; @@ -1648,14 +1880,79 @@ static bool amduatd_concepts_append_edge_record(amduatd_concepts_t *c, return false; } free((void *)payload.data); - if (amduat_asl_collection_append(&c->edge_collection, - AMDUATD_EDGE_COLLECTION, - record_ref, - AMDUATD_EDGE_COLLECTION_KIND, - actor, - &offset) != AMDUAT_ASL_COLLECTION_OK) { - amduat_reference_free(&record_ref); - return false; + { + amduat_asl_collection_error_t append_err = + amduat_asl_collection_append(&c->edge_collection, + c->edge_collection_name, + record_ref, + AMDUATD_EDGE_COLLECTION_KIND, + actor, + &offset); + if (append_err != AMDUAT_ASL_COLLECTION_OK) { + if (c->edge_collection_name != NULL && + !amduat_asl_pointer_name_is_valid(c->edge_collection_name)) { + amduat_log(AMDUAT_LOG_ERROR, "edge collection name invalid: %s", + c->edge_collection_name); + } + if (c->edge_collection_name != NULL) { + size_t name_len = strlen(c->edge_collection_name); + size_t total_len = 11u + name_len + 4u + 1u; + char *log_name = (char *)malloc(total_len); + if (log_name != NULL) { + size_t pos = 0u; + memcpy(log_name + pos, "collection/", 11u); + pos += 11u; + memcpy(log_name + pos, c->edge_collection_name, name_len); + pos += name_len; + memcpy(log_name + pos, "/log", 4u); + pos += 4u; + log_name[pos] = '\0'; + if (!amduat_asl_pointer_name_is_valid(log_name)) { + amduat_log(AMDUAT_LOG_ERROR, "edge log name invalid: %s", log_name); + } + { + size_t head_len = 4u + pos + 5u + 1u; + char *head_name = (char *)malloc(head_len); + if (head_name != NULL) { + size_t hpos = 0u; + memcpy(head_name + hpos, "log/", 4u); + hpos += 4u; + memcpy(head_name + hpos, log_name, pos); + hpos += pos; + memcpy(head_name + hpos, "/head", 5u); + hpos += 5u; + head_name[hpos] = '\0'; + if (!amduat_asl_pointer_name_is_valid(head_name)) { + amduat_log(AMDUAT_LOG_ERROR, + "edge log head name invalid: %s", head_name); + } else { + bool head_exists = false; + amduat_reference_t head_ref; + memset(&head_ref, 0, sizeof(head_ref)); + amduat_asl_pointer_error_t ptr_err = + amduat_asl_pointer_get(&c->edge_collection.pointer_store, + head_name, + &head_exists, + &head_ref); + if (ptr_err != AMDUAT_ASL_POINTER_OK) { + amduat_log(AMDUAT_LOG_ERROR, + "edge log head pointer get failed: %d", ptr_err); + } + amduat_reference_free(&head_ref); + } + free(head_name); + } + } + free(log_name); + } + } + amduat_log(AMDUAT_LOG_ERROR, "edge append failed for %s (err=%d)", + c->edge_collection_name != NULL ? c->edge_collection_name + : "?", + (int)append_err); + amduat_reference_free(&record_ref); + return false; + } } memset(&entry, 0, sizeof(entry)); @@ -1673,7 +1970,7 @@ static bool amduatd_concepts_append_edge_record(amduatd_concepts_t *c, bool swapped = false; memset(&snapshot_ref, 0, sizeof(snapshot_ref)); (void)amduat_asl_collection_snapshot(&c->edge_collection, - AMDUATD_EDGE_COLLECTION, + c->edge_collection_name, offset, &snapshot_ref, &swapped); @@ -1789,10 +2086,73 @@ static bool amduatd_concepts_migrate_edges(amduatd_concepts_t *c, return ok; } +static bool amduatd_concepts_migrate_unscoped_edges( + amduatd_concepts_t *c, + amduat_asl_store_t *store, + const char *unscoped_collection) { + amduat_asl_collection_view_t view; + uint64_t from = 0u; + bool ok = false; + + if (c == NULL || store == NULL || unscoped_collection == NULL) { + return false; + } + + while (true) { + memset(&view, 0, sizeof(view)); + if (!amduatd_collection_view(store, + c->root_path, + unscoped_collection, + from, + AMDUATD_EDGE_VIEW_BATCH, + &view)) { + return false; + } + + for (size_t i = 0u; i < view.refs_len; ++i) { + uint64_t offset = 0u; + if (amduat_asl_collection_append(&c->edge_collection, + c->edge_collection_name, + view.refs[i], + AMDUATD_EDGE_COLLECTION_KIND, + amduat_octets(NULL, 0u), + &offset) != AMDUAT_ASL_COLLECTION_OK) { + goto migrate_cleanup; + } + if (offset != 0u && (offset % 256u) == 0u) { + amduat_reference_t snapshot_ref; + bool swapped = false; + memset(&snapshot_ref, 0, sizeof(snapshot_ref)); + (void)amduat_asl_collection_snapshot(&c->edge_collection, + c->edge_collection_name, + offset, + &snapshot_ref, + &swapped); + amduat_reference_free(&snapshot_ref); + } + } + + if (view.refs_len == 0u || view.computed_up_to_offset <= from) { + break; + } + from = view.computed_up_to_offset; + amduat_asl_collection_view_free(&view); + } + + ok = true; + +migrate_cleanup: + amduat_asl_collection_view_free(&view); + return ok; +} + static bool amduatd_concepts_init(amduatd_concepts_t *c, amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, + const amduatd_cfg_t *dcfg, const char *root_path) { + amduat_octets_t scoped_collection = amduat_octets(NULL, 0u); + if (c == NULL || store == NULL || cfg == NULL || root_path == NULL) { return false; } @@ -1800,76 +2160,119 @@ static bool amduatd_concepts_init(amduatd_concepts_t *c, c->root_path = root_path; (void)snprintf(c->edges_path, sizeof(c->edges_path), "%s/%s", root_path, AMDUATD_EDGES_FILE); + if (!amduatd_scope_name(dcfg, AMDUATD_EDGE_COLLECTION, &scoped_collection)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: scope edges failed"); + return false; + } + c->edge_collection_name = (char *)scoped_collection.data; + if (c->edge_collection_name == NULL) { + return false; + } if (!amduat_asl_collection_store_init(&c->edge_collection, root_path, store)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: collection store init failed"); return false; } - if (!amduatd_concepts_seed_relation(store, cfg, "aliases", + if (!amduatd_concepts_seed_relation(store, cfg, dcfg, "aliases", &c->rel_aliases_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: seed aliases failed"); return false; } - if (!amduatd_concepts_ensure_alias(c, store, cfg, "ms.aliases", + if (!amduatd_concepts_ensure_alias(c, store, cfg, dcfg, "ms.aliases", c->rel_aliases_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: ensure ms.aliases failed"); return false; } - if (!amduatd_concepts_seed_relation(store, cfg, "materializesAs", + if (!amduatd_concepts_seed_relation(store, cfg, dcfg, "materializesAs", &c->rel_materializes_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: seed materializesAs failed"); return false; } - if (!amduatd_concepts_ensure_alias(c, store, cfg, "ms.materializes_as", + if (!amduatd_concepts_ensure_alias(c, store, cfg, dcfg, "ms.materializes_as", c->rel_materializes_ref)) { + amduat_log(AMDUAT_LOG_ERROR, + "concepts init: ensure ms.materializes_as failed"); return false; } - if (!amduatd_concepts_seed_relation(store, cfg, "represents", + if (!amduatd_concepts_seed_relation(store, cfg, dcfg, "represents", &c->rel_represents_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: seed represents failed"); return false; } - if (!amduatd_concepts_ensure_alias(c, store, cfg, "ms.represents", + if (!amduatd_concepts_ensure_alias(c, store, cfg, dcfg, "ms.represents", c->rel_represents_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: ensure ms.represents failed"); return false; } - if (!amduatd_concepts_seed_relation(store, cfg, "requiresKey", + if (!amduatd_concepts_seed_relation(store, cfg, dcfg, "requiresKey", &c->rel_requires_key_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: seed requiresKey failed"); return false; } - if (!amduatd_concepts_ensure_alias(c, store, cfg, "ms.requires_key", + if (!amduatd_concepts_ensure_alias(c, store, cfg, dcfg, "ms.requires_key", c->rel_requires_key_ref)) { + amduat_log(AMDUAT_LOG_ERROR, + "concepts init: ensure ms.requires_key failed"); return false; } - if (!amduatd_concepts_seed_relation(store, cfg, "withinDomain", + if (!amduatd_concepts_seed_relation(store, cfg, dcfg, "withinDomain", &c->rel_within_domain_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: seed withinDomain failed"); return false; } - if (!amduatd_concepts_ensure_alias(c, store, cfg, "ms.within_domain", + if (!amduatd_concepts_ensure_alias(c, store, cfg, dcfg, "ms.within_domain", c->rel_within_domain_ref)) { + amduat_log(AMDUAT_LOG_ERROR, + "concepts init: ensure ms.within_domain failed"); return false; } - if (!amduatd_concepts_seed_relation(store, cfg, "computedBy", + if (!amduatd_concepts_seed_relation(store, cfg, dcfg, "computedBy", &c->rel_computed_by_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: seed computedBy failed"); return false; } - if (!amduatd_concepts_ensure_alias(c, store, cfg, "ms.computed_by", + if (!amduatd_concepts_ensure_alias(c, store, cfg, dcfg, "ms.computed_by", c->rel_computed_by_ref)) { + amduat_log(AMDUAT_LOG_ERROR, + "concepts init: ensure ms.computed_by failed"); return false; } - if (!amduatd_concepts_seed_relation(store, cfg, "hasProvenance", + if (!amduatd_concepts_seed_relation(store, cfg, dcfg, "hasProvenance", &c->rel_has_provenance_ref)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: seed hasProvenance failed"); return false; } - if (!amduatd_concepts_ensure_alias(c, store, cfg, "ms.has_provenance", + if (!amduatd_concepts_ensure_alias(c, store, cfg, dcfg, "ms.has_provenance", c->rel_has_provenance_ref)) { + amduat_log(AMDUAT_LOG_ERROR, + "concepts init: ensure ms.has_provenance failed"); return false; } if (!amduatd_concepts_load_edges(c, store)) { + amduat_log(AMDUAT_LOG_ERROR, "concepts init: load edges failed"); return false; } if (c->edges.len == 0u) { - if (!amduatd_concepts_migrate_edges(c, store)) { - return false; - } - if (!amduatd_concepts_load_edges(c, store)) { - return false; + if (dcfg != NULL && dcfg->space_enabled) { + if (dcfg->migrate_unscoped_edges) { + if (!amduatd_concepts_migrate_unscoped_edges( + c, + store, + AMDUATD_EDGE_COLLECTION)) { + return false; + } + if (!amduatd_concepts_load_edges(c, store)) { + return false; + } + } + } else { + if (!amduatd_concepts_migrate_edges(c, store)) { + return false; + } + if (!amduatd_concepts_load_edges(c, store)) { + return false; + } } } @@ -2073,6 +2476,7 @@ static bool amduatd_concepts_resolve_latest(amduat_asl_store_t *store, } static bool amduatd_parse_name_artifact(amduat_artifact_t artifact, + const amduatd_cfg_t *dcfg, char *out, size_t cap) { const uint8_t *bytes; @@ -2081,6 +2485,7 @@ static bool amduatd_parse_name_artifact(amduat_artifact_t artifact, size_t prefix_len; size_t i; size_t name_len; + char scoped[AMDUAT_ASL_POINTER_NAME_MAX + 1u]; if (out != NULL && cap != 0) { out[0] = '\0'; @@ -2106,17 +2511,18 @@ static bool amduatd_parse_name_artifact(amduat_artifact_t artifact, } } name_len = len - (prefix_len + 1u); - if (name_len == 0 || name_len >= cap) { + if (name_len == 0 || name_len >= sizeof(scoped)) { return false; } - memcpy(out, bytes + prefix_len + 1u, name_len); - out[name_len] = '\0'; - return amduatd_name_valid(out); + memcpy(scoped, bytes + prefix_len + 1u, name_len); + scoped[name_len] = '\0'; + return amduatd_unscoped_name(dcfg, scoped, out, cap); } static bool amduatd_handle_get_concepts(int fd, amduat_asl_store_t *store, - const amduatd_concepts_t *concepts) { + const amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg) { amduatd_strbuf_t b; bool first = true; size_t i; @@ -2135,7 +2541,7 @@ static bool amduatd_handle_get_concepts(int fd, const amduatd_edge_entry_t *entry = &concepts->edges.items[i]; amduat_artifact_t artifact; amduat_asl_store_error_t err; - char name[128]; + char name[AMDUAT_ASL_POINTER_NAME_MAX + 1u]; char *concept_hex = NULL; if (entry->rel == NULL || @@ -2146,7 +2552,7 @@ static bool amduatd_handle_get_concepts(int fd, memset(&artifact, 0, sizeof(artifact)); err = amduat_asl_store_get(store, entry->src_ref, &artifact); if (err != AMDUAT_ASL_STORE_OK || - !amduatd_parse_name_artifact(artifact, name, sizeof(name))) { + !amduatd_parse_name_artifact(artifact, dcfg, name, sizeof(name))) { amduat_asl_artifact_free(&artifact); continue; } @@ -2249,12 +2655,14 @@ static bool amduatd_handle_get_concept(int fd, amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, const amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const char *name) { amduat_reference_t concept_ref; amduat_reference_t latest_ref; amduatd_strbuf_t b; char *concept_hex = NULL; char *latest_hex = NULL; + char *scoped_name = NULL; bool have_latest = false; size_t i; size_t version_count = 0; @@ -2267,12 +2675,16 @@ static bool amduatd_handle_get_concept(int fd, return amduatd_send_json_error(fd, 500, "Internal Server Error", "internal error"); } - if (!amduatd_name_valid(name)) { + if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) { return amduatd_send_json_error(fd, 400, "Bad Request", "invalid name"); } - if (!amduatd_concepts_lookup_alias(store, cfg, concepts, name, &concept_ref)) { + amduatd_log_scoped_name(dcfg, name, scoped_name); + if (!amduatd_concepts_lookup_alias(store, cfg, concepts, scoped_name, + &concept_ref)) { + free(scoped_name); return amduatd_send_json_error(fd, 404, "Not Found", "unknown concept"); } + free(scoped_name); if (amduatd_concepts_resolve_latest(store, concepts, concept_ref, &latest_ref)) { have_latest = true; @@ -3353,11 +3765,13 @@ static amduatd_ref_status_t amduatd_decode_ref_or_name_latest( amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, const amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const char *s, size_t len, amduat_reference_t *out_ref) { amduat_reference_t concept_ref; char *tmp = NULL; + char *scoped_name = NULL; if (out_ref != NULL) { memset(out_ref, 0, sizeof(*out_ref)); @@ -3374,15 +3788,22 @@ static amduatd_ref_status_t amduatd_decode_ref_or_name_latest( if (!amduatd_copy_json_str(s, len, &tmp)) { return AMDUATD_REF_ERR_INTERNAL; } - if (!amduatd_name_valid(tmp)) { + if (!amduatd_scope_name_cstr(dcfg, tmp, &scoped_name)) { free(tmp); return AMDUATD_REF_ERR_INVALID; } + amduatd_log_scoped_name(dcfg, tmp, scoped_name); memset(&concept_ref, 0, sizeof(concept_ref)); - if (!amduatd_concepts_lookup_alias(store, cfg, concepts, tmp, &concept_ref)) { + if (!amduatd_concepts_lookup_alias(store, + cfg, + concepts, + scoped_name, + &concept_ref)) { + free(scoped_name); free(tmp); return AMDUATD_REF_ERR_NOT_FOUND; } + free(scoped_name); free(tmp); if (!amduatd_concepts_resolve_latest(store, concepts, concept_ref, out_ref)) { @@ -3645,11 +4066,14 @@ static bool amduatd_seed_concept_if_missing( amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const char *name, amduat_reference_t *out_concept_ref) { amduat_reference_t name_ref; amduat_reference_t concept_ref; amduat_reference_t edge_ref; + char *scoped_name = NULL; + bool ok = false; if (out_concept_ref != NULL) { *out_concept_ref = amduat_reference(0u, amduat_octets(NULL, 0u)); @@ -3658,21 +4082,24 @@ static bool amduatd_seed_concept_if_missing( out_concept_ref == NULL) { return false; } - if (amduatd_concepts_lookup_alias(store, cfg, concepts, name, + if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) { + return false; + } + if (amduatd_concepts_lookup_alias(store, cfg, concepts, scoped_name, out_concept_ref)) { - return true; + ok = true; + goto seed_cleanup; } memset(&name_ref, 0, sizeof(name_ref)); memset(&concept_ref, 0, sizeof(concept_ref)); memset(&edge_ref, 0, sizeof(edge_ref)); - if (!amduatd_concepts_put_name_artifact(store, name, &name_ref)) { - return false; + if (!amduatd_concepts_put_name_artifact(store, scoped_name, &name_ref)) { + goto seed_cleanup; } if (!amduatd_concepts_put_concept_id(store, cfg, &concept_ref)) { - amduat_reference_free(&name_ref); - return false; + goto seed_cleanup; } if (!amduatd_concepts_put_edge(store, concepts, @@ -3681,14 +4108,20 @@ static bool amduatd_seed_concept_if_missing( concepts->rel_aliases_ref, amduat_octets(NULL, 0u), &edge_ref)) { - amduat_reference_free(&name_ref); + goto seed_cleanup; + } + *out_concept_ref = concept_ref; + ok = true; + goto seed_cleanup; + +seed_cleanup: + if (!ok) { amduat_reference_free(&concept_ref); - return false; } amduat_reference_free(&name_ref); amduat_reference_free(&edge_ref); - *out_concept_ref = concept_ref; - return true; + free(scoped_name); + return ok; } static bool amduatd_seed_store_artifact(amduat_asl_store_t *store, @@ -3789,7 +4222,8 @@ static bool amduatd_seed_materializes_if_missing( static bool amduatd_seed_ms_ui_state(amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, - amduatd_concepts_t *concepts) { + amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg) { amduat_reference_t type_string_ref; amduat_reference_t type_ref_ref; amduat_reference_t key_title_ref; @@ -3837,21 +4271,25 @@ static bool amduatd_seed_ms_ui_state(amduat_asl_store_t *store, memset(&b, 0, sizeof(b)); memset(&artifact, 0, sizeof(artifact)); - if (!amduatd_seed_concept_if_missing(store, cfg, concepts, "ms.type.string", + if (!amduatd_seed_concept_if_missing(store, cfg, concepts, dcfg, + "ms.type.string", &type_string_ref) || - !amduatd_seed_concept_if_missing(store, cfg, concepts, "ms.type.ref", + !amduatd_seed_concept_if_missing(store, cfg, concepts, dcfg, + "ms.type.ref", &type_ref_ref) || - !amduatd_seed_concept_if_missing(store, cfg, concepts, "ms.ui.field.title", + !amduatd_seed_concept_if_missing(store, cfg, concepts, dcfg, + "ms.ui.field.title", &key_title_ref) || - !amduatd_seed_concept_if_missing(store, cfg, concepts, "ms.ui.field.status", + !amduatd_seed_concept_if_missing(store, cfg, concepts, dcfg, + "ms.ui.field.status", &key_status_ref) || - !amduatd_seed_concept_if_missing(store, cfg, concepts, + !amduatd_seed_concept_if_missing(store, cfg, concepts, dcfg, "ms.ui.field.latest_ref", &key_latest_ref) || - !amduatd_seed_concept_if_missing(store, cfg, concepts, + !amduatd_seed_concept_if_missing(store, cfg, concepts, dcfg, "ms.ui.state.schema.v1", &schema_concept_ref) || - !amduatd_seed_concept_if_missing(store, cfg, concepts, + !amduatd_seed_concept_if_missing(store, cfg, concepts, dcfg, "ms.ui.state.registry.v1", ®istry_concept_ref)) { goto seed_cleanup; @@ -4811,6 +5249,7 @@ static bool amduatd_handle_post_pel_run(int fd, amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, const amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const amduatd_http_req_t *req) { uint8_t *body = NULL; const char *p = NULL; @@ -4956,7 +5395,8 @@ static bool amduatd_handle_post_pel_run(int fd, "invalid program_ref"); goto pel_run_cleanup; } - st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, sv, sv_len, + st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, dcfg, sv, + sv_len, &program_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", @@ -5003,7 +5443,8 @@ static bool amduatd_handle_post_pel_run(int fd, "invalid params_ref"); goto pel_run_cleanup; } - st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, sv, sv_len, + st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, dcfg, sv, + sv_len, ¶ms_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", @@ -5044,7 +5485,7 @@ static bool amduatd_handle_post_pel_run(int fd, } { amduatd_ref_status_t st = amduatd_decode_ref_or_name_latest( - store, cfg, concepts, sv, sv_len, &ref); + store, cfg, concepts, dcfg, sv, sv_len, &ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", "input_ref not found"); @@ -5134,8 +5575,9 @@ static bool amduatd_handle_post_pel_run(int fd, "invalid input_manifest_ref"); goto pel_run_cleanup; } - st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, sv, - sv_len, &receipt_input_manifest_ref); + st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, dcfg, + sv, sv_len, + &receipt_input_manifest_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", "input_manifest_ref not found"); @@ -5156,8 +5598,9 @@ static bool amduatd_handle_post_pel_run(int fd, "invalid environment_ref"); goto pel_run_cleanup; } - st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, sv, - sv_len, &receipt_environment_ref); + st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, dcfg, + sv, sv_len, + &receipt_environment_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", "environment_ref not found"); @@ -5192,8 +5635,9 @@ static bool amduatd_handle_post_pel_run(int fd, "invalid executor_ref"); goto pel_run_cleanup; } - st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, sv, - sv_len, &receipt_executor_ref); + st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, dcfg, + sv, sv_len, + &receipt_executor_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", "executor_ref not found"); @@ -5214,8 +5658,8 @@ static bool amduatd_handle_post_pel_run(int fd, "invalid sbom_ref"); goto pel_run_cleanup; } - st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, sv, - sv_len, &receipt_sbom_ref); + st = amduatd_decode_ref_or_name_latest(store, cfg, concepts, dcfg, + sv, sv_len, &receipt_sbom_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", "sbom_ref not found"); @@ -5237,7 +5681,7 @@ static bool amduatd_handle_post_pel_run(int fd, goto pel_run_cleanup; } st = amduatd_decode_ref_or_name_latest( - store, cfg, concepts, sv, sv_len, + store, cfg, concepts, dcfg, sv, sv_len, &receipt_executor_fingerprint_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", @@ -5455,7 +5899,7 @@ static bool amduatd_handle_post_pel_run(int fd, goto pel_run_cleanup; } st = amduatd_decode_ref_or_name_latest( - store, cfg, concepts, sv, sv_len, &entry.log_ref); + store, cfg, concepts, dcfg, sv, sv_len, &entry.log_ref); if (st == AMDUATD_REF_ERR_NOT_FOUND) { ok = amduatd_send_json_error(fd, 404, "Not Found", "log_ref not found"); @@ -6771,6 +7215,7 @@ static bool amduatd_handle_post_concepts(int fd, amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const amduatd_http_req_t *req) { uint8_t *body = NULL; const char *p = NULL; @@ -6783,6 +7228,7 @@ static bool amduatd_handle_post_concepts(int fd, amduat_reference_t concept_ref; amduat_reference_t edge_ref; char *concept_hex = NULL; + char *scoped_name = NULL; char json[4096]; bool ok = false; amduat_octets_t actor = amduat_octets(NULL, 0u); @@ -6845,10 +7291,6 @@ static bool amduatd_handle_post_concepts(int fd, ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid name"); goto concepts_cleanup; } - if (!amduatd_name_valid(name)) { - ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid name"); - goto concepts_cleanup; - } have_name = true; } else if (key_len == strlen("ref") && memcmp(key, "ref", key_len) == 0) { if (have_ref || !amduatd_json_parse_string_noesc(&p, end, &sv, &sv_len) || @@ -6882,7 +7324,13 @@ static bool amduatd_handle_post_concepts(int fd, goto concepts_cleanup; } - if (!amduatd_concepts_put_name_artifact(store, name, &name_ref)) { + if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) { + ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid name"); + goto concepts_cleanup; + } + amduatd_log_scoped_name(dcfg, name, scoped_name); + + if (!amduatd_concepts_put_name_artifact(store, scoped_name, &name_ref)) { ok = amduatd_send_json_error(fd, 500, "Internal Server Error", "store error"); goto concepts_cleanup; @@ -6891,7 +7339,11 @@ static bool amduatd_handle_post_concepts(int fd, { amduat_reference_t existing; memset(&existing, 0, sizeof(existing)); - if (amduatd_concepts_lookup_alias(store, cfg, concepts, name, &existing)) { + if (amduatd_concepts_lookup_alias(store, + cfg, + concepts, + scoped_name, + &existing)) { amduat_reference_free(&existing); ok = amduatd_send_json_error(fd, 409, "Conflict", "name exists"); goto concepts_cleanup; @@ -6956,6 +7408,7 @@ static bool amduatd_handle_post_concepts(int fd, concepts_cleanup: free(body); free(name); + free(scoped_name); amduat_reference_free(&target_ref); amduat_reference_free(&name_ref); amduat_reference_free(&concept_ref); @@ -7015,6 +7468,7 @@ static bool amduatd_handle_post_context_frames( amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, const amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const amduatd_http_req_t *req) { uint8_t *body = NULL; const char *p = NULL; @@ -7244,6 +7698,7 @@ static bool amduatd_handle_post_context_frames( if (amduatd_decode_ref_or_name_latest(store, cfg, concepts, + dcfg, key_text, strlen(key_text), &key_ref) != AMDUATD_REF_OK) { @@ -7260,6 +7715,7 @@ static bool amduatd_handle_post_context_frames( if (amduatd_decode_ref_or_name_latest(store, cfg, concepts, + dcfg, vtext, strlen(vtext), &value_ref) != AMDUATD_REF_OK) { @@ -7277,6 +7733,7 @@ static bool amduatd_handle_post_context_frames( if (amduatd_decode_ref_or_name_latest(store, cfg, concepts, + dcfg, value_enum_text, strlen(value_enum_text), &enum_ref) != AMDUATD_REF_OK) { @@ -7542,6 +7999,7 @@ static bool amduatd_handle_post_concept_publish(int fd, amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const char *name, const amduatd_http_req_t *req) { uint8_t *body = NULL; @@ -7553,6 +8011,7 @@ static bool amduatd_handle_post_concept_publish(int fd, bool have_ref = false; bool ok = false; amduat_octets_t actor = amduat_octets(NULL, 0u); + char *scoped_name = NULL; memset(&target_ref, 0, sizeof(target_ref)); memset(&concept_ref, 0, sizeof(concept_ref)); @@ -7566,20 +8025,29 @@ static bool amduatd_handle_post_concept_publish(int fd, if (req->has_actor) { actor = req->actor; } - if (!amduatd_name_valid(name)) { + if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) { return amduatd_send_json_error(fd, 400, "Bad Request", "invalid name"); } + amduatd_log_scoped_name(dcfg, name, scoped_name); if (req->content_length == 0) { + free(scoped_name); return amduatd_send_json_error(fd, 400, "Bad Request", "missing body"); } if (req->content_length > (256u * 1024u)) { + free(scoped_name); return amduatd_send_json_error(fd, 413, "Payload Too Large", "payload too large"); } - if (!amduatd_concepts_lookup_alias(store, cfg, concepts, name, &concept_ref)) { + if (!amduatd_concepts_lookup_alias(store, + cfg, + concepts, + scoped_name, + &concept_ref)) { + free(scoped_name); return amduatd_send_json_error(fd, 404, "Not Found", "unknown concept"); } + free(scoped_name); body = (uint8_t *)malloc(req->content_length); if (body == NULL) { @@ -7671,12 +8139,14 @@ static bool amduatd_handle_get_resolve(int fd, amduat_asl_store_t *store, const amduat_asl_store_fs_config_t *cfg, const amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const char *name) { amduat_reference_t concept_ref; amduat_reference_t latest_ref; char *hex = NULL; char json[2048]; int n; + char *scoped_name = NULL; memset(&concept_ref, 0, sizeof(concept_ref)); memset(&latest_ref, 0, sizeof(latest_ref)); @@ -7685,12 +8155,16 @@ static bool amduatd_handle_get_resolve(int fd, return amduatd_send_json_error(fd, 500, "Internal Server Error", "internal error"); } - if (!amduatd_name_valid(name)) { + if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) { return amduatd_send_json_error(fd, 400, "Bad Request", "invalid name"); } - if (!amduatd_concepts_lookup_alias(store, cfg, concepts, name, &concept_ref)) { + amduatd_log_scoped_name(dcfg, name, scoped_name); + if (!amduatd_concepts_lookup_alias(store, cfg, concepts, scoped_name, + &concept_ref)) { + free(scoped_name); return amduatd_send_json_error(fd, 404, "Not Found", "unknown concept"); } + free(scoped_name); if (!amduatd_concepts_resolve_latest(store, concepts, concept_ref, &latest_ref)) { amduat_reference_free(&concept_ref); @@ -7718,6 +8192,7 @@ static bool amduatd_handle_conn(int fd, amduat_reference_t api_contract_ref, amduat_reference_t ui_ref, amduatd_concepts_t *concepts, + const amduatd_cfg_t *dcfg, const amduat_fed_coord_t *coord, const amduatd_allowlist_t *allowlist) { amduatd_http_req_t req; @@ -7785,7 +8260,7 @@ static bool amduatd_handle_conn(int fd, goto conn_cleanup; } if (strcmp(req.method, "POST") == 0 && strcmp(no_query, "/v1/pel/run") == 0) { - ok = amduatd_handle_post_pel_run(fd, store, cfg, concepts, &req); + ok = amduatd_handle_post_pel_run(fd, store, cfg, concepts, dcfg, &req); goto conn_cleanup; } if (strcmp(req.method, "POST") == 0 && @@ -7795,15 +8270,16 @@ static bool amduatd_handle_conn(int fd, } if (strcmp(req.method, "POST") == 0 && strcmp(no_query, "/v1/context_frames") == 0) { - ok = amduatd_handle_post_context_frames(fd, store, cfg, concepts, &req); + ok = amduatd_handle_post_context_frames(fd, store, cfg, concepts, dcfg, + &req); goto conn_cleanup; } if (strcmp(req.method, "POST") == 0 && strcmp(no_query, "/v1/concepts") == 0) { - ok = amduatd_handle_post_concepts(fd, store, cfg, concepts, &req); + ok = amduatd_handle_post_concepts(fd, store, cfg, concepts, dcfg, &req); goto conn_cleanup; } if (strcmp(req.method, "GET") == 0 && strcmp(no_query, "/v1/concepts") == 0) { - ok = amduatd_handle_get_concepts(fd, store, concepts); + ok = amduatd_handle_get_concepts(fd, store, concepts, dcfg); goto conn_cleanup; } if (strcmp(req.method, "GET") == 0 && strcmp(no_query, "/v1/relations") == 0) { @@ -7821,7 +8297,7 @@ static bool amduatd_handle_conn(int fd, ok = amduatd_send_json_error(fd, 400, "Bad Request", "missing name"); goto conn_cleanup; } - ok = amduatd_handle_get_concept(fd, store, cfg, concepts, name); + ok = amduatd_handle_get_concept(fd, store, cfg, concepts, dcfg, name); goto conn_cleanup; } if (strcmp(req.method, "POST") == 0 && @@ -7839,7 +8315,8 @@ static bool amduatd_handle_conn(int fd, goto conn_cleanup; } *slash = '\0'; - ok = amduatd_handle_post_concept_publish(fd, store, cfg, concepts, name, + ok = amduatd_handle_post_concept_publish(fd, store, cfg, concepts, dcfg, + name, &req); goto conn_cleanup; } @@ -7849,7 +8326,7 @@ static bool amduatd_handle_conn(int fd, ok = amduatd_send_json_error(fd, 400, "Bad Request", "missing name"); goto conn_cleanup; } - ok = amduatd_handle_get_resolve(fd, store, cfg, concepts, name); + ok = amduatd_handle_get_resolve(fd, store, cfg, concepts, dcfg, name); goto conn_cleanup; } if (strcmp(req.method, "GET") == 0 && @@ -7874,6 +8351,7 @@ static void amduatd_print_usage(FILE *stream) { fprintf(stream, "usage:\n" " amduatd [--root PATH] [--sock PATH]\n" + " [--space SPACE_ID] [--migrate-unscoped-edges]\n" " [--allow-uid UID] [--allow-user NAME]\n" "\n" "defaults:\n" @@ -7886,6 +8364,9 @@ static void amduatd_print_usage(FILE *stream) { int main(int argc, char **argv) { const char *root = AMDUATD_DEFAULT_ROOT; const char *sock_path = AMDUATD_DEFAULT_SOCK; + const char *space_id = NULL; + bool migrate_unscoped_edges = false; + amduatd_cfg_t dcfg; amduat_asl_store_fs_config_t cfg; amduat_asl_store_fs_t fs; amduat_asl_store_t store; @@ -7904,6 +8385,7 @@ int main(int argc, char **argv) { memset(&ui_ref, 0, sizeof(ui_ref)); memset(&concepts, 0, sizeof(concepts)); memset(&allowlist, 0, sizeof(allowlist)); + memset(&dcfg, 0, sizeof(dcfg)); for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "--root") == 0) { @@ -7918,6 +8400,18 @@ int main(int argc, char **argv) { return 2; } sock_path = argv[++i]; + } else if (strcmp(argv[i], "--space") == 0) { + if (i + 1 >= argc) { + fprintf(stderr, "error: --space requires a value\n"); + return 2; + } + space_id = argv[++i]; + if (!amduatd_space_id_valid(space_id)) { + fprintf(stderr, "error: invalid --space\n"); + return 2; + } + } else if (strcmp(argv[i], "--migrate-unscoped-edges") == 0) { + migrate_unscoped_edges = true; } else if (strcmp(argv[i], "--allow-uid") == 0) { char *endp = NULL; unsigned long uid_val; @@ -7958,6 +8452,10 @@ int main(int argc, char **argv) { } } + dcfg.space_id = space_id; + dcfg.space_enabled = (space_id != NULL); + dcfg.migrate_unscoped_edges = migrate_unscoped_edges; + memset(&cfg, 0, sizeof(cfg)); if (!amduat_asl_store_fs_load_config(root, &cfg)) { fprintf(stderr, "error: failed to load store config: %s\n", root); @@ -7979,11 +8477,11 @@ int main(int argc, char **argv) { fprintf(stderr, "error: failed to seed ui html\n"); return 8; } - if (!amduatd_concepts_init(&concepts, &store, &cfg, root)) { + if (!amduatd_concepts_init(&concepts, &store, &cfg, &dcfg, root)) { fprintf(stderr, "error: failed to init concept edges\n"); return 8; } - if (!amduatd_seed_ms_ui_state(&store, &cfg, &concepts)) { + if (!amduatd_seed_ms_ui_state(&store, &cfg, &concepts, &dcfg)) { fprintf(stderr, "error: failed to seed ms ui state\n"); return 8; } @@ -8097,6 +8595,7 @@ int main(int argc, char **argv) { api_contract_ref, ui_ref, &concepts, + &dcfg, fed_coord, &allowlist); (void)close(cfd); diff --git a/vendor/amduat b/vendor/amduat index 337466b..9a29030 160000 --- a/vendor/amduat +++ b/vendor/amduat @@ -1 +1 @@ -Subproject commit 337466b073ee1d357af2fa448b94af1d96ae621c +Subproject commit 9a2903072bd10b2bc09dd082681cc7c026bf9350