47 lines
1.9 KiB
Python
47 lines
1.9 KiB
Python
"""
|
|
Logic for calculating effective memory scope based on different policies.
|
|
"""
|
|
from typing import Set
|
|
from contracts.common import CallerContext, EmmaConversation
|
|
|
|
def calculate_effective_memory_scope(
|
|
requested_scope: Set[str],
|
|
caller_context: CallerContext,
|
|
conversation_context: EmmaConversation
|
|
) -> Set[str]:
|
|
"""
|
|
Calculates the final, secure memory scope by intersecting requested scopes
|
|
with server-side policies.
|
|
|
|
Args:
|
|
requested_scope: The scope the client is asking for.
|
|
caller_context: The server-derived context of the authenticated caller.
|
|
conversation_context: The context of the current conversation.
|
|
|
|
Returns:
|
|
A set of strings representing the final, allowed memory scopes.
|
|
"""
|
|
# 1. Start with a default-deny principle
|
|
effective_scope = set()
|
|
|
|
# 2. Define server-side allowable scopes based on caller profile
|
|
# This is a placeholder for a more complex policy engine.
|
|
if caller_context.profile == "admin":
|
|
allowed_by_caller = {"current_conversation", "owner_private_memory", "workspace_operational_memory"}
|
|
elif caller_context.profile == "operator":
|
|
allowed_by_caller = {"current_conversation", "workspace_operational_memory"}
|
|
else: # readonly / default
|
|
allowed_by_caller = {"current_conversation"}
|
|
|
|
# 3. Intersect requested scope with what the caller is allowed to do
|
|
permitted_scope = requested_scope.intersection(allowed_by_caller)
|
|
|
|
# 4. Filter based on data attributes (this would happen in the query)
|
|
# For now, we just return the permitted scope types. The query in the
|
|
# persistence layer would be responsible for adding the WHERE clauses.
|
|
# e.g., if "owner_private_memory" is in the scope, the query must add
|
|
# `WHERE owner_id == caller_context.owner_id`.
|
|
effective_scope = permitted_scope
|
|
|
|
return effective_scope
|