Skip to content

fix(storage): enforce one KG and relation name grammar - #152

Merged
jsam merged 2 commits into
mainfrom
fix/name-validation
Oct 3, 2026
Merged

jsam merged 2 commits into
mainfrom
fix/name-validation

Conversation

@jsam

@jsam jsam commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

KG names could contain ':', which made shard keys {kg}:{relation} ambiguous. Dropping user wiped user:42, and restarts created phantom KGs.

  • src/naming.rs: names start with a-z and contain only a-z, 0-9 and _ (KG up to 128 bytes, relation up to 256). Checked on KG create, insert, delete and every schema registration path.
  • Recovery and drop give each shard to the longest matching KG name from metadata. Legacy colon KGs missing from metadata are inferred from the shard key's last ':'. If the metadata save fails, create rolls back.
  • Startup warns about existing invalid names. The troubleshooting docs list the drop steps.

Tests: tests/name_validation_tests.rs covers rejection, phantom KGs, prefix drop, stale or missing metadata and create rollback. fmt, clippy -D warnings, cargo test --workspace (3412 passed) and snapshot tests (1149 passed) all pass.

Closes #106

@jsam
jsam force-pushed the fix/persist-effective-delta branch from 2284549 to 6902668 Compare October 2, 2026 13:19
Base automatically changed from fix/persist-effective-delta to main October 2, 2026 13:58
jsam added 2 commits October 2, 2026 15:59
Names must start with a-z and contain only a-z, 0-9 and '_' (KG <= 128
bytes, relation <= 256). Checked in create_knowledge_graph,
insert_tuples_into, delete_tuples_from and register_schema_in, so every
entry path rejects ':' and the shard key "{kg}:{relation}" stays
unambiguous.

Recovery and drop assign shards to the longest KG name from metadata
instead of split(':'), so legacy names like "user:42" no longer create a
phantom "user" KG, and dropping "user" leaves "user:42" intact. Startup
warns about existing invalid names; troubleshooting docs list drop steps.

Closes #106
Validate names in register_or_update_schema_in and its session variant.
Infer legacy colon KGs missing from metadata from the last ':' of the shard
key, roll back create_knowledge_graph when the metadata save fails, and drop
the unused InvalidRelationName variant.
@jsam
jsam force-pushed the fix/name-validation branch from 217dc18 to 70b9a25 Compare October 2, 2026 14:04
@jsam
jsam merged commit e31751d into main Oct 3, 2026
13 checks passed
@jsam
jsam deleted the fix/name-validation branch October 3, 2026 09:45
jsam added a commit that referenced this pull request Oct 3, 2026
Rebased onto #152: map StorageError::InvalidName to Validation, and expect
invalid-name statements as structured statement errors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
jsam added a commit that referenced this pull request Oct 3, 2026
Rebased onto #152: map StorageError::InvalidName to Validation, and expect
invalid-name statements as structured statement errors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
jsam added a commit that referenced this pull request Oct 3, 2026
Rebased onto #152: map StorageError::InvalidName to Validation, and expect
invalid-name statements as structured statement errors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
jsam added a commit that referenced this pull request Oct 3, 2026
* fix(protocol): report per-statement failures structurally

QueryJob records each failed statement as {index, code, message} in
QueryResult.errors instead of only a message row. A one-statement
program that fails is a WS error frame with a code; a longer program
returns a result whose errors[] names each failed statement, including
when the program ends in a query. Removes is_error_message phrase
matching; ontology commands and .kg drop cleanup read errors.

* fix(ontology-client): read structured statement errors in soft_errors

soft_errors returns the engine's errors[] when present. For engines
without it, message rows must match an exact success shape: the old
prefix allowlist accepted "Relation 'x' not found." and
"Rule 'x' not found." as success. Adds table-driven tests over every
engine message.

* fix(protocol): route every statement failure through statement status

Rule, session-rule, storage and query failures no longer abort the
program: each is recorded in errors[] with a code and later statements
still run. Session-bound /ws rules and facts get code=validation, index
and .kg use errors are classified by cause, and ontology remove/upgrade
tolerate rules that are already gone. SDK and GUI frame types model
errors and code.

* fix(protocol): adapt to the InvalidName storage error from #152

Rebased onto #152: map StorageError::InvalidName to Validation, and expect
invalid-name statements as structured statement errors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
jsam added a commit that referenced this pull request Oct 3, 2026
* fix(protocol): report per-statement failures structurally

QueryJob records each failed statement as {index, code, message} in
QueryResult.errors instead of only a message row. A one-statement
program that fails is a WS error frame with a code; a longer program
returns a result whose errors[] names each failed statement, including
when the program ends in a query. Removes is_error_message phrase
matching; ontology commands and .kg drop cleanup read errors.

* fix(ontology-client): read structured statement errors in soft_errors

soft_errors returns the engine's errors[] when present. For engines
without it, message rows must match an exact success shape: the old
prefix allowlist accepted "Relation 'x' not found." and
"Rule 'x' not found." as success. Adds table-driven tests over every
engine message.

* fix(protocol): route every statement failure through statement status

Rule, session-rule, storage and query failures no longer abort the
program: each is recorded in errors[] with a code and later statements
still run. Session-bound /ws rules and facts get code=validation, index
and .kg use errors are classified by cause, and ontology remove/upgrade
tolerate rules that are already gone. SDK and GUI frame types model
errors and code.

* fix(protocol): adapt to the InvalidName storage error from #152

Rebased onto #152: map StorageError::InvalidName to Validation, and expect
invalid-name statements as structured statement errors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Engine: inserts bypass relation-name validation, creating unreadable ghost relations

1 participant