kibi-core 0.22.3 → 0.22.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-core",
3
- "version": "0.22.3",
3
+ "version": "0.22.5",
4
4
  "private": false,
5
5
  "description": "Core Prolog modules and RDF graph logic for Kibi",
6
6
  "type": "module",
@@ -29,7 +29,8 @@ entity_property(_, priority, atom).
29
29
  entity_property(_, severity, atom).
30
30
  entity_property(_, links, list).
31
31
  entity_property(_, text_ref, uri).
32
- entity_property(_, sourceFile, uri).
32
+ % Workspace-relative source paths only (no absolute / .. escapes).
33
+ entity_property(_, sourceFile, workspace_relpath).
33
34
  % Provenance of any authored entity: a JSON object (kind, ref, approved_by,
34
35
  % recorded_at) naming who authored it and on what authority.
35
36
  entity_property(_, origin, list_or_json).
@@ -50,11 +50,26 @@ check_kind(datetime, V) :- string(V). % accept ISO strings for now
50
50
  check_kind(list, V) :- is_list(V).
51
51
  check_kind(list_or_json, V) :- is_list(V) ; string(V) ; atom(V).
52
52
  check_kind(uri, V) :- string(V).
53
+ % Non-empty workspace-relative path: reject absolute forms and `..` segments.
54
+ check_kind(workspace_relpath, V) :-
55
+ string(V),
56
+ string_length(V, Len),
57
+ Len > 0,
58
+ \+ workspace_relpath_absolute(V),
59
+ split_string(V, "/\\", "", Parts),
60
+ \+ member("..", Parts).
53
61
  check_kind(integer, V) :- integer(V).
54
62
  check_kind(number, V) :- number(V).
55
63
  check_kind(boolean, true).
56
64
  check_kind(boolean, false).
57
65
 
66
+ workspace_relpath_absolute(V) :- sub_string(V, 0, 1, _, "/").
67
+ workspace_relpath_absolute(V) :-
68
+ string_length(V, Len),
69
+ Len >= 2,
70
+ sub_string(V, 1, 1, _, ":").
71
+ workspace_relpath_absolute(V) :- sub_string(V, 0, 2, _, "\\\\").
72
+
58
73
  % Fallback false
59
74
  check_kind(_, _) :- fail.
60
75
 
package/src/kb.pl CHANGED
@@ -16,6 +16,7 @@
16
16
  kb_commit_upsert/5,
17
17
  kb_commit_upsert_batch/2,
18
18
  kb_preview_upsert_contradiction/3,
19
+ kb_preview_upsert_contradiction/4,
19
20
  kb_log_entity_upsert/3,
20
21
  kb_retract_entity/1,
21
22
  kb_retract_entity/3,
@@ -1069,9 +1070,7 @@ kb_commit_upsert(Type, Props, Relationships, SkipContradiction, ChangeKind) :-
1069
1070
  catch(
1070
1071
  rdf_transaction((
1071
1072
  kb_stage(rdf_mutation),
1072
- kb_assert_entity_no_audit(Type, Props),
1073
- kb_commit_relationships_no_audit(Relationships),
1074
- kb_maybe_check_req_contradiction(Type, Id, SkipContradiction),
1073
+ kb_stage_upsert_mutation(Type, Id, Props, Relationships, SkipContradiction),
1075
1074
  kb_stage(entity_audit),
1076
1075
  kb_log_entity_upsert(ChangeKind, Type, Props),
1077
1076
  kb_stage(relationship_audit),
@@ -1101,9 +1100,7 @@ kb_commit_upsert(Type, Props, Relationships, SkipContradiction, ChangeKind) :-
1101
1100
  upsert_change_kind(Id, ChangeKind),
1102
1101
  rdf_transaction((
1103
1102
  kb_stage(rdf_mutation),
1104
- kb_assert_entity_no_audit(Type, Props),
1105
- kb_commit_relationships_no_audit(Relationships),
1106
- kb_maybe_check_req_contradiction(Type, Id, SkipContradiction),
1103
+ kb_stage_upsert_mutation(Type, Id, Props, Relationships, SkipContradiction),
1107
1104
  kb_stage(entity_audit),
1108
1105
  kb_log_entity_upsert(ChangeKind, Type, Props),
1109
1106
  kb_stage(relationship_audit),
@@ -1130,35 +1127,51 @@ kb_maybe_check_req_contradiction(req, Id, false) :-
1130
1127
  check_req_contradiction(Id).
1131
1128
  kb_maybe_check_req_contradiction(_, _, _).
1132
1129
 
1130
+ %% kb_stage_upsert_mutation(+Type, +Id, +Properties, +Relationships, +SkipContradiction)
1131
+ % implements REQ-kibi-operation-interface-parity
1132
+ % The RDF mutation and refusal rules of one upsert, shared by the commit, the
1133
+ % batch commit and the dry-run preview so all three refuse the same payloads:
1134
+ % a relationship whose source or target entity does not exist, an invalid
1135
+ % relationship direction, a symbol mixing executable_for with production
1136
+ % ownership/coverage edges, and (for a requirement) a contradiction.
1137
+ kb_stage_upsert_mutation(Type, Id, Props, Relationships, SkipContradiction) :-
1138
+ kb_assert_entity_no_audit(Type, Props),
1139
+ kb_commit_relationships_no_audit(Relationships),
1140
+ kb_maybe_check_req_contradiction(Type, Id, SkipContradiction).
1141
+
1133
1142
  % Stage one upsert inside an already-open transaction. The caller saves once.
1134
1143
  kb_stage_upsert(Type, Props, Relationships, SkipContradiction, ChangeKind) :-
1135
1144
  memberchk(id=Id, Props),
1136
1145
  memberchk(SkipContradiction, [true, false]),
1137
1146
  upsert_change_kind(Id, ChangeKind),
1138
- kb_assert_entity_no_audit(Type, Props),
1139
- kb_commit_relationships_no_audit(Relationships),
1140
- kb_maybe_check_req_contradiction(Type, Id, SkipContradiction),
1147
+ kb_stage_upsert_mutation(Type, Id, Props, Relationships, SkipContradiction),
1141
1148
  kb_log_entity_upsert(ChangeKind, Type, Props),
1142
1149
  kb_commit_relationship_audits(Relationships).
1143
1150
 
1144
1151
  %% kb_preview_upsert_contradiction(+Type, +Properties, +Relationships)
1152
+ %% kb_preview_upsert_contradiction(+Type, +Properties, +Relationships, +SkipContradiction)
1145
1153
  % implements REQ-kibi-operation-interface-parity
1146
- % Stage one upsert in a transaction that is always rolled back and run the
1147
- % commit-time requirement contradiction check against the staged KB, so a
1148
- % kb_upsert dry run refuses exactly what the commit would refuse. Nothing is
1149
- % written and nothing marks the branch dirty: the no-audit assertions only
1150
- % touch the RDF store, which the transaction rolls back, and no audit entry,
1151
- % snapshot save or journal flush follows. The entity index is not
1152
- % transactional, so the staged id is re-indexed from the restored store.
1154
+ % Stage one upsert in a transaction that is always rolled back and run every
1155
+ % commit-time refusal rule (kb_stage_upsert_mutation/5) against the staged
1156
+ % KB, so a kb_upsert dry run refuses exactly what the commit would refuse:
1157
+ % missing relationship endpoints, invalid directions, mixed symbol roles and,
1158
+ % unless skipped, requirement contradictions. Nothing is written and nothing
1159
+ % marks the branch dirty: the no-audit assertions only touch the RDF store,
1160
+ % which the transaction rolls back, and no audit entry, snapshot save or
1161
+ % journal flush follows. The entity index is not transactional, so the
1162
+ % staged id is re-indexed from the restored store.
1153
1163
  kb_preview_upsert_contradiction(Type, Props, Relationships) :-
1164
+ kb_preview_upsert_contradiction(Type, Props, Relationships, false).
1165
+
1166
+ kb_preview_upsert_contradiction(Type, Props, Relationships, SkipContradiction) :-
1154
1167
  memberchk(id=Id, Props),
1168
+ memberchk(SkipContradiction, [true, false]),
1155
1169
  with_kb_mutex(
1156
1170
  call_cleanup(
1157
1171
  catch(
1158
1172
  rdf_transaction((
1159
- kb_assert_entity_no_audit(Type, Props),
1160
- kb_commit_relationships_no_audit(Relationships),
1161
- kb_maybe_check_req_contradiction(Type, Id, false),
1173
+ kb_stage(rdf_mutation),
1174
+ kb_stage_upsert_mutation(Type, Id, Props, Relationships, SkipContradiction),
1162
1175
  throw(kibi_preview_rolled_back)
1163
1176
  )),
1164
1177
  Caught,