Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.250.106"
VERSION = "0.250.107"
IS_DEVELOPMENT = is_development_env_enabled()

SESSION_COOKIE_SAMESITE = os.getenv('SESSION_COOKIE_SAMESITE', 'Lax')
Expand Down
8 changes: 7 additions & 1 deletion application/single_app/functions_simplechat_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
"group-single-user",
"public",
}
FORKABLE_PERSONAL_CONTEXT_SCOPES = {
"",
"personal",
"model",
"model_knowledge",
}
PERSONAL_FORK_CONVERSATION_FIELDS = (
"context",
"tags",
Expand Down Expand Up @@ -275,7 +281,7 @@ def _authorize_fork_conversation_context(
raise ConversationForkConflictError("The conversation context is invalid")

scope = str(context_item.get("scope") or "").strip().lower()
if scope in {"", "personal"}:
if scope in FORKABLE_PERSONAL_CONTEXT_SCOPES:
authorized_scopes.add("personal")
continue

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Personal Conversation Fork Model Context Fix

Check warning on line 1 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Fixed/Implemented in version: **0.250.107**

## Issue Description

Personal conversations that only had the built-in "Model's knowledge" context could be rejected during fork creation with an unsupported workspace context conflict, even though they were not group or public workspace conversations.

Check warning on line 7 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

## Root Cause Analysis

The fork authorization helper revalidated every stored context as either personal, group, or public. Conversation metadata stores model knowledge as a secondary context with scope `Model` and id `N/A`, so the fork helper interpreted it as an unsupported workspace context instead of treating it as model-only personal context.

Check warning on line 11 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Check warning on line 11 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.

Check warning on line 11 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.

## Technical Details

Files modified:
- `application/single_app/functions_simplechat_operations.py`
- `application/single_app/config.py`
- `functional_tests/test_conversation_fork.py`

Check warning on line 18 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Code changes summary:
- Added model and model-knowledge scopes to the personal fork context allow-list.
- Preserved group and public workspace revalidation behavior for real workspace contexts.
- Updated `config.py` from version `0.250.106` to `0.250.107` for traceability.

Testing approach:
- Added a regression test covering personal forks whose only stored context is model knowledge.
- Covered both the stored `Model` scope with `N/A` id and the normalized `model_knowledge` form.

## Validation

Expected behavior after the fix:
- Personal model-only conversations can be forked successfully.

Check warning on line 32 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
- The fork preserves the source model-knowledge context.
- Group and public workspace conversations still require the existing workspace availability and access checks.

Check warning on line 34 in docs/explanation/fixes/PERSONAL_CONVERSATION_FORK_MODEL_CONTEXT_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
38 changes: 35 additions & 3 deletions functional_tests/test_conversation_fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
# test_conversation_fork.py
"""
Functional test for personal conversation forking.
Version: 0.250.101
Version: 0.250.107
Implemented in: 0.250.074

This test ensures persisted personal conversation history is copied through an
assistant boundary with independent identifiers, deterministic ordering,
workspace-context authorization, concurrency protection, failed-write cleanup,
and stable conflict responses when structured logging is invoked.
workspace-context authorization, model-knowledge context handling, concurrency

Check warning on line 10 in functional_tests/test_conversation_fork.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
protection, failed-write cleanup, and stable conflict responses when structured
logging is invoked.
"""

import ast
Expand All @@ -22,6 +23,11 @@
import pytest
from azure.cosmos.exceptions import CosmosResourceNotFoundError
from flask import Blueprint, Flask, jsonify, request
import werkzeug


if not hasattr(werkzeug, '__version__'):
werkzeug.__version__ = '3'


sys.path.insert(
Expand Down Expand Up @@ -707,6 +713,32 @@
assert test_state['result']['conversation']['context'] == [context]


@pytest.mark.parametrize(
('model_scope', 'model_context_id'),
[
('Model', 'N/A'),
('model_knowledge', None),
],
)
def test_fork_allows_personal_model_knowledge_context(model_scope, model_context_id):
"""Allow personal forks when the only stored context is model knowledge."""
model_context = {
'type': 'secondary',
'scope': model_scope,
'name': "Model's knowledge",
}
if model_context_id is not None:
model_context['id'] = model_context_id

conversation = build_source_conversation(chat_type='personal')

Check warning on line 733 in functional_tests/test_conversation_fork.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
conversation['context'] = [model_context]

test_state = run_fork(source_conversation=conversation)

assert test_state['result']['conversation']['chat_type'] == 'personal_single_user'
assert test_state['result']['conversation']['context'] == [model_context]


@pytest.mark.parametrize(
('conversation', 'access_replacements', 'error_match'),
[
Expand Down
Loading