kibi-core 0.18.2 → 0.19.0
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 +1 -1
- package/src/kb.pl +150 -0
package/package.json
CHANGED
package/src/kb.pl
CHANGED
|
@@ -135,6 +135,7 @@ kb_uri('urn-kibi:').
|
|
|
135
135
|
% the memo never serves a property list the store no longer holds.
|
|
136
136
|
:- dynamic kb_entity_props_memo/2.
|
|
137
137
|
:- dynamic kb_entity_props_memo_key/1.
|
|
138
|
+
:- dynamic kb_decision_signature_memo/2.
|
|
138
139
|
:- dynamic kb_index_verified_key/1.
|
|
139
140
|
:- dynamic entity/4. % Support legacy .pl file format (Type, Id, Title, Props)
|
|
140
141
|
|
|
@@ -361,6 +362,7 @@ kb_detach :-
|
|
|
361
362
|
retractall(kb_index_verified_key(_)),
|
|
362
363
|
retractall(kb_entity_props_memo(_, _)),
|
|
363
364
|
retractall(kb_entity_props_memo_key(_)),
|
|
365
|
+
retractall(kb_decision_signature_memo(_, _)),
|
|
364
366
|
retractall(kb_index_entity(_, _)),
|
|
365
367
|
retractall(kb_index_type(_, _)),
|
|
366
368
|
retractall(kb_index_tag(_, _)),
|
|
@@ -2662,6 +2664,154 @@ req_conflict_witness(ReqA, ReqB, Witness) :-
|
|
|
2662
2664
|
right: Right
|
|
2663
2665
|
}.
|
|
2664
2666
|
|
|
2667
|
+
% implements REQ-kibi-truthful-consistency
|
|
2668
|
+
% Opposite decisions on the same case: two asserted facts of a predicate
|
|
2669
|
+
% whose key arguments determine a closed allow/deny decision argument (the
|
|
2670
|
+
% built-in permission_rule, or a project schema that declares key_arguments
|
|
2671
|
+
% and a `decision` argument) agree on every key argument but decide
|
|
2672
|
+
% differently, e.g. permission_rule(coach, read, x, allow) against
|
|
2673
|
+
% permission_rule(coach, read, x, deny). kb_model writes a denial as
|
|
2674
|
+
% decision deny with polarity deny, so a deny decision counts as a denial
|
|
2675
|
+
% whatever its polarity; an allow decision counts only when asserted.
|
|
2676
|
+
%
|
|
2677
|
+
% Cost: the search answer layer and coverage ask for the witnesses of each
|
|
2678
|
+
% requirement with the other side unbound. The pairing therefore starts
|
|
2679
|
+
% from whichever requirement is bound, filters its facts against the
|
|
2680
|
+
% decision signatures (memoized per KB generation, so the project schemas
|
|
2681
|
+
% are read once rather than once per fact), and pre-binds the partner's key
|
|
2682
|
+
% arguments before enumerating partner requirements.
|
|
2683
|
+
req_conflict_witness(ReqA, ReqB, Witness) :-
|
|
2684
|
+
decision_signatures(Signatures),
|
|
2685
|
+
Signatures \== [],
|
|
2686
|
+
decision_conflict_pair(Signatures, ReqA, ReqB, FactA, FactB, Namespace, Name,
|
|
2687
|
+
ArgsA, ArgsB, PolarityA, PolarityB, KeyPositions, DecisionPosition),
|
|
2688
|
+
length(ArgsA, Arity),
|
|
2689
|
+
nth1(DecisionPosition, ArgsA, DecisionA),
|
|
2690
|
+
nth1(DecisionPosition, ArgsB, DecisionB),
|
|
2691
|
+
DecisionA \== DecisionB,
|
|
2692
|
+
effective_decision(DecisionA, PolarityA, EffectA),
|
|
2693
|
+
effective_decision(DecisionB, PolarityB, EffectB),
|
|
2694
|
+
EffectA \== EffectB,
|
|
2695
|
+
findall(KeyValue, (member(Position, KeyPositions), nth1(Position, ArgsA, KeyValue)), KeyValues),
|
|
2696
|
+
atomic_list_concat(KeyValues, ',', KeyText),
|
|
2697
|
+
format(
|
|
2698
|
+
string(Reason),
|
|
2699
|
+
"Decision conflict on ~w:~w(~w): ~w decides ~w while ~w decides ~w",
|
|
2700
|
+
[Namespace, Name, KeyText, ReqA, EffectA, ReqB, EffectB]
|
|
2701
|
+
),
|
|
2702
|
+
predicate_conflict_side(ReqA, FactA, Namespace, Name, ArgsA, PolarityA, Left),
|
|
2703
|
+
predicate_conflict_side(ReqB, FactB, Namespace, Name, ArgsB, PolarityB, Right),
|
|
2704
|
+
findall(SchemaId, predicate_schema(SchemaId, Namespace, Name, Arity, _Names, _Types), SchemaIds0),
|
|
2705
|
+
sort(SchemaIds0, SchemaIds),
|
|
2706
|
+
Witness = _{
|
|
2707
|
+
kind: predicate,
|
|
2708
|
+
status: contradiction,
|
|
2709
|
+
requirements: [ReqA, ReqB],
|
|
2710
|
+
reason: Reason,
|
|
2711
|
+
predicateNamespace: Namespace,
|
|
2712
|
+
predicateName: Name,
|
|
2713
|
+
predicateArgs: ArgsA,
|
|
2714
|
+
keyArguments: KeyValues,
|
|
2715
|
+
schemaIds: SchemaIds,
|
|
2716
|
+
left: Left,
|
|
2717
|
+
right: Right
|
|
2718
|
+
}.
|
|
2719
|
+
|
|
2720
|
+
%% decision_conflict_pair(+Signatures, ?ReqA, ?ReqB, -FactA, -FactB, -Namespace, -Name, -ArgsA, -ArgsB, -PolarityA, -PolarityB, -KeyPositions, -DecisionPosition)
|
|
2721
|
+
% Two decision-predicate facts of current requirements ReqA @< ReqB that
|
|
2722
|
+
% agree on every key argument. Starts from the bound requirement.
|
|
2723
|
+
decision_conflict_pair(Signatures, ReqA, ReqB, FactA, FactB, Namespace, Name,
|
|
2724
|
+
ArgsA, ArgsB, PolarityA, PolarityB, KeyPositions, DecisionPosition) :-
|
|
2725
|
+
( var(ReqA), nonvar(ReqB)
|
|
2726
|
+
-> decision_req_fact(Signatures, ReqB, FactB, Namespace, Name, ArgsB, PolarityB, KeyPositions, DecisionPosition),
|
|
2727
|
+
length(ArgsB, Arity),
|
|
2728
|
+
length(ArgsA, Arity),
|
|
2729
|
+
bind_key_arguments(KeyPositions, ArgsB, ArgsA),
|
|
2730
|
+
current_req(ReqA),
|
|
2731
|
+
ReqA @< ReqB,
|
|
2732
|
+
effective_req_predicate(ReqA, FactA, Namespace, Name, ArgsA, PolarityA)
|
|
2733
|
+
; decision_req_fact(Signatures, ReqA, FactA, Namespace, Name, ArgsA, PolarityA, KeyPositions, DecisionPosition),
|
|
2734
|
+
length(ArgsA, Arity),
|
|
2735
|
+
length(ArgsB, Arity),
|
|
2736
|
+
bind_key_arguments(KeyPositions, ArgsA, ArgsB),
|
|
2737
|
+
current_req(ReqB),
|
|
2738
|
+
ReqA @< ReqB,
|
|
2739
|
+
effective_req_predicate(ReqB, FactB, Namespace, Name, ArgsB, PolarityB)
|
|
2740
|
+
),
|
|
2741
|
+
FactA \= FactB.
|
|
2742
|
+
|
|
2743
|
+
decision_req_fact(Signatures, ReqId, FactId, Namespace, Name, Args, Polarity, KeyPositions, DecisionPosition) :-
|
|
2744
|
+
current_req(ReqId),
|
|
2745
|
+
effective_req_predicate(ReqId, FactId, Namespace, Name, Args, Polarity),
|
|
2746
|
+
length(Args, Arity),
|
|
2747
|
+
memberchk(decision_signature(Namespace, Name, Arity, KeyPositions, DecisionPosition), Signatures).
|
|
2748
|
+
|
|
2749
|
+
%% decision_predicate(?Namespace, ?Name, ?Arity, -KeyPositions, -DecisionPosition)
|
|
2750
|
+
% A predicate whose key arguments (1-based KeyPositions) determine one
|
|
2751
|
+
% allow/deny decision argument. A project-local predicate_schema decides
|
|
2752
|
+
% this for its own signature: it must declare key_arguments and name a
|
|
2753
|
+
% non-key argument `decision`. Without a project schema the built-in
|
|
2754
|
+
% catalog entry applies.
|
|
2755
|
+
decision_predicate(Namespace, Name, Arity, KeyPositions, DecisionPosition) :-
|
|
2756
|
+
decision_signatures(Signatures),
|
|
2757
|
+
member(decision_signature(Namespace, Name, Arity, KeyPositions, DecisionPosition), Signatures).
|
|
2758
|
+
|
|
2759
|
+
%% decision_signatures(-Signatures)
|
|
2760
|
+
% All decision predicates of the current KB, memoized per graph, RDF
|
|
2761
|
+
% generation and legacy fact count like the entity property memo.
|
|
2762
|
+
decision_signatures(Signatures) :-
|
|
2763
|
+
index_verification_key(decision_signatures, Key),
|
|
2764
|
+
( kb_decision_signature_memo(Key, Cached)
|
|
2765
|
+
-> Signatures = Cached
|
|
2766
|
+
; compute_decision_signatures(Computed),
|
|
2767
|
+
retractall(kb_decision_signature_memo(_, _)),
|
|
2768
|
+
assertz(kb_decision_signature_memo(Key, Computed)),
|
|
2769
|
+
Signatures = Computed
|
|
2770
|
+
).
|
|
2771
|
+
|
|
2772
|
+
compute_decision_signatures(Signatures) :-
|
|
2773
|
+
findall(Namespace-Name-Arity,
|
|
2774
|
+
predicate_schema(_SchemaId, Namespace, Name, Arity, _Names, _Types),
|
|
2775
|
+
SchemaSignatures0),
|
|
2776
|
+
sort(SchemaSignatures0, SchemaSignatures),
|
|
2777
|
+
findall(decision_signature(Namespace, Name, Arity, KeyPositions, DecisionPosition),
|
|
2778
|
+
( member(Namespace-Name-Arity, SchemaSignatures),
|
|
2779
|
+
schema_decision_positions(Namespace, Name, Arity, KeyPositions, DecisionPosition)
|
|
2780
|
+
),
|
|
2781
|
+
FromSchemas),
|
|
2782
|
+
findall(decision_signature(Namespace, Name, Arity, KeyPositions, DecisionPosition),
|
|
2783
|
+
( builtin_decision_predicate(Namespace, Name, Arity, KeyPositions, DecisionPosition),
|
|
2784
|
+
\+ memberchk(Namespace-Name-Arity, SchemaSignatures)
|
|
2785
|
+
),
|
|
2786
|
+
Builtins),
|
|
2787
|
+
append(FromSchemas, Builtins, Signatures).
|
|
2788
|
+
|
|
2789
|
+
schema_decision_positions(Namespace, Name, Arity, KeyPositions, DecisionPosition) :-
|
|
2790
|
+
predicate_schema_keys(Namespace, Name, Arity, KeyPositions),
|
|
2791
|
+
predicate_schema(_SchemaId, Namespace, Name, Arity, ArgumentNames, _ArgumentTypes),
|
|
2792
|
+
nth1(DecisionPosition, ArgumentNames, decision),
|
|
2793
|
+
\+ memberchk(DecisionPosition, KeyPositions),
|
|
2794
|
+
!.
|
|
2795
|
+
|
|
2796
|
+
%% bind_key_arguments(+KeyPositions, +ArgsA, ?ArgsB)
|
|
2797
|
+
% Unify ArgsB with ArgsA on every key position.
|
|
2798
|
+
bind_key_arguments([], _ArgsA, _ArgsB).
|
|
2799
|
+
bind_key_arguments([Position|Positions], ArgsA, ArgsB) :-
|
|
2800
|
+
nth1(Position, ArgsA, Value),
|
|
2801
|
+
nth1(Position, ArgsB, Value),
|
|
2802
|
+
bind_key_arguments(Positions, ArgsA, ArgsB).
|
|
2803
|
+
|
|
2804
|
+
%% builtin_decision_predicate(?Namespace, ?Name, ?Arity, ?KeyPositions, ?DecisionPosition)
|
|
2805
|
+
% Built-in catalog predicates with a closed allow/deny decision. Keep in
|
|
2806
|
+
% step with key_arguments in packages/cli/src/operations/modeling/
|
|
2807
|
+
% predicate-catalog-4.ts (permission_rule: actor, action, resource).
|
|
2808
|
+
builtin_decision_predicate(default, permission_rule, 4, [1, 2, 3], 4).
|
|
2809
|
+
|
|
2810
|
+
%% effective_decision(+Decision, +Polarity, -Effect)
|
|
2811
|
+
effective_decision(allow, assert, allow).
|
|
2812
|
+
effective_decision(allow, deny, deny).
|
|
2813
|
+
effective_decision(deny, _Polarity, deny).
|
|
2814
|
+
|
|
2665
2815
|
property_conflict_side(ReqId, FactId, SubjectKey, PropertyKey, Operator, ValueType, Value, Unit, Scope, Polarity, ValidFrom, ValidTo, Side) :-
|
|
2666
2816
|
entity_evidence_source(ReqId, req, RequirementSource),
|
|
2667
2817
|
fact_evidence_fields(FactId, FactSource, ClaimKey, ClaimText, _CanonicalKey),
|