File size: 11,313 Bytes
1d3f990
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
%% ════════════════════════════════════════════════════════════════════════════════
%% Shift Authorization Rules
%% SnapKitty Collective
%% ════════════════════════════════════════════════════════════════════════════════
%% Authorization flow for isomorphic shifts. All decisions are made by Prolog rules.
%% Integration with bob-orchestrator/prolog/sovereign_kernel.pl (agent trust model).

:- module(shift_authorization, [
    can_perform_shift/3,
    agent_has_capability/2,
    capability_sufficient_for_shift/2,
    authorization_trace/2,
    authorization_denied_reason/2
]).

%% ────────────────────────────────────────────────────────────────────────────────
%% AGENT TRUST LEVELS (imported from sovereign_kernel.pl)
%% ────────────────────────────────────────────────────────────────────────────────

trust_level(none,      0).
trust_level(low,       1).
trust_level(medium,    2).
trust_level(high,      3).
trust_level(sovereign, 4).

agent_class(sentinel,  sovereign).
agent_class(oracle,    high).
agent_class(builder,   high).
agent_class(archivist, high).
agent_class(berserker, medium).

%% ────────────────────────────────────────────────────────────────────────────────
%% SHIFT CAPABILITY REQUIREMENTS
%% ────────────────────────────────────────────────────────────────────────────────
%% shift_requires_capability(+ShiftId, +CapabilityAtom, +MinTrustLevel)

shift_requires_capability('M1', read,   low).       % Surface β†’ Canonical (read source)
shift_requires_capability('M1', write,  low).       % (write canonical form)

shift_requires_capability('M2', read,   low).       % Canonical β†’ Logic (read canonical)
shift_requires_capability('M2', analyze, medium).   % (analyze/formalize)

shift_requires_capability('M3', read,   medium).    % Decision β†’ Command (read decision)
shift_requires_capability('M3', execute, high).     % (generate executable)

shift_requires_capability('M4', read,   medium).    % Obligation β†’ Invocation (read proof)
shift_requires_capability('M4', verify, high).      % (invoke verifier)

shift_requires_capability('M5', read,   low).       % Event β†’ Fact (read event)
shift_requires_capability('M5', analyze, medium).   % (analyze/classify)

shift_requires_capability('M6', read,   medium).    % Event β†’ Receipt (read event)
shift_requires_capability('M6', seal,   high).      % (seal receipt with WORM)

shift_requires_capability('M7', read,   low).       % Cell β†’ Fact (read notebook)
shift_requires_capability('M7', analyze, medium).   % (extract/analyze)

shift_requires_capability('M8', read,   low).       % Value β†’ Canonical (read value)
shift_requires_capability('M8', write,  low).       % (normalize/write)

%% ────────────────────────────────────────────────────────────────────────────────
%% AGENT CAPABILITIES (who can do what)
%% ────────────────────────────────────────────────────────────────────────────────

agent_has_capability(sentinel, read).
agent_has_capability(sentinel, write).
agent_has_capability(sentinel, execute).
agent_has_capability(sentinel, seal).
agent_has_capability(sentinel, verify).
agent_has_capability(sentinel, analyze).

agent_has_capability(oracle, read).
agent_has_capability(oracle, analyze).
agent_has_capability(oracle, pattern_match).

agent_has_capability(builder, read).
agent_has_capability(builder, write).
agent_has_capability(builder, generate).
agent_has_capability(builder, execute).
agent_has_capability(builder, seal).

agent_has_capability(archivist, read).
agent_has_capability(archivist, analyze).
agent_has_capability(archivist, index).
agent_has_capability(archivist, provenance).

agent_has_capability(berserker, read).
agent_has_capability(berserker, inject).
agent_has_capability(berserker, analyze).

%% ────────────────────────────────────────────────────────────────────────────────
%% CAPABILITY SUFFICIENCY FOR SHIFTS
%% ────────────────────────────────────────────────────────────────────────────────

%% capability_sufficient_for_shift(+Capability, +ShiftId)
%% Returns true if capability is sufficient to perform shift

capability_sufficient_for_shift(write, 'M1').
capability_sufficient_for_shift(write, 'M8').
capability_sufficient_for_shift(generate, 'M1').
capability_sufficient_for_shift(generate, 'M8').

capability_sufficient_for_shift(read, 'M2').
capability_sufficient_for_shift(analyze, 'M2').

capability_sufficient_for_shift(execute, 'M3').
capability_sufficient_for_shift(generate, 'M3').

capability_sufficient_for_shift(verify, 'M4').
capability_sufficient_for_shift(execute, 'M4').

capability_sufficient_for_shift(read, 'M5').
capability_sufficient_for_shift(analyze, 'M5').

capability_sufficient_for_shift(seal, 'M6').
capability_sufficient_for_shift(execute, 'M6').

capability_sufficient_for_shift(read, 'M7').
capability_sufficient_for_shift(analyze, 'M7').
capability_sufficient_for_shift(generate, 'M7').

%% ────────────────────────────────────────────────────────────────────────────────
%% PRIMARY AUTHORIZATION RULE
%% ────────────────────────────────────────────────────────────────────────────────

%% can_perform_shift(+Agent, +ShiftId, +Direction) β€” Main authorization predicate
can_perform_shift(Agent, ShiftId, Direction) :-
    % Agent must be known
    agent_class(Agent, _Trust),

    % Agent must have at least one capability required by shift
    agent_has_capability(Agent, Capability),
    capability_sufficient_for_shift(Capability, ShiftId),

    % Direction must be valid
    member(Direction, [forward, inverse, bidirectional]),

    % Trust level check: agent trust >= minimum required for this capability
    agent_class(Agent, AgentTrust),
    shift_requires_capability(ShiftId, Capability, MinTrust),
    trust_level(AgentTrust, AgentLevel),
    trust_level(MinTrust, MinLevel),
    AgentLevel >= MinLevel,

    % Oracle is read-only: cannot perform direction=forward on write-requiring shifts
    \+ (Agent = oracle, shift_requires_capability(ShiftId, write, _), Direction = forward),
    \+ (Agent = oracle, shift_requires_capability(ShiftId, execute, _), Direction = forward),
    \+ (Agent = oracle, shift_requires_capability(ShiftId, seal, _), Direction = forward).

%% ────────────────────────────────────────────────────────────────────────────────
%% AUTHORIZATION TRACE (for logging/auditing)
%% ────────────────────────────────────────────────────────────────────────────────

authorization_trace(Agent, trace{
    agent: Agent,
    status: authorized,
    rules_satisfied: [
        'agent_is_known',
        'agent_has_required_capability',
        'trust_level_sufficient',
        'direction_valid',
        'no_oracle_write_violation'
    ]
}) :-
    agent_class(Agent, _).

authorization_trace(Agent, trace{
    agent: Agent,
    status: denied,
    reason: 'agent_not_known'
}) :-
    \+ agent_class(Agent, _).

%% ────────────────────────────────────────────────────────────────────────────────
%% DENIAL REASONS
%% ────────────────────────────────────────────────────────────────────────────────

authorization_denied_reason(Agent, 'AGENT_UNKNOWN') :-
    \+ agent_class(Agent, _).

authorization_denied_reason(Agent, 'INSUFFICIENT_TRUST') :-
    agent_class(Agent, AgentTrust),
    \+ (shift_requires_capability(_ShiftId, _Capability, MinTrust),
        trust_level(AgentTrust, AgentLevel),
        trust_level(MinTrust, MinLevel),
        AgentLevel >= MinLevel).

authorization_denied_reason(Agent, 'NO_REQUIRED_CAPABILITY') :-
    agent_class(Agent, _),
    \+ agent_has_capability(Agent, _).

authorization_denied_reason(oracle, 'ORACLE_READ_ONLY_VIOLATION') :-
    shift_requires_capability(_ShiftId, Capability, _),
    member(Capability, [write, execute, seal]).

%% ════════════════════════════════════════════════════════════════════════════════
%% RESTRICTION: NO UNAUTHORIZED PERMISSION ESCALATION
%% ════════════════════════════════════════════════════════════════════════════════

%% Rule: If a shift is denied for an agent, it MUST remain denied.
%% No intermediate transformation step can escalate permissions.

prevent_permission_escalation(Agent, ShiftId, Direction) :-
    \+ can_perform_shift(Agent, ShiftId, Direction),
    !.  % Cut: once denied, always denied for this agent/shift/direction