Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd0507292e |
@@ -0,0 +1,193 @@
|
|||||||
|
# User Data Isolation Redline
|
||||||
|
|
||||||
|
Status: mandatory
|
||||||
|
|
||||||
|
Decision date: 2026-07-10
|
||||||
|
|
||||||
|
Baseline at decision: V1R4C3
|
||||||
|
|
||||||
|
## Redline
|
||||||
|
|
||||||
|
User data isolation is a hard system-design requirement.
|
||||||
|
|
||||||
|
No component may read, write, search, rank, summarize, cache, or report data from another user, tenant, project, session, workspace, branch, agent, or task context unless explicit authorization and context binding exist.
|
||||||
|
|
||||||
|
This applies to memory search, filesystem logs, vector indexes, search gateways, autonomous controller state, task records, audit logs, artifacts, and any fallback provider.
|
||||||
|
|
||||||
|
## Incident Class
|
||||||
|
|
||||||
|
Any cross-context data contamination is a security and reliability incident, not a normal feature bug.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- memory search returns records from another project;
|
||||||
|
- shared workspace logs are used as current-session evidence;
|
||||||
|
- global `memory/` state mixes unrelated users or tasks;
|
||||||
|
- fallback provider uses unscoped records;
|
||||||
|
- agent reports status based on stale or unrelated context;
|
||||||
|
- shared cache leaks content across users, groups, or sessions.
|
||||||
|
|
||||||
|
## Core Rule
|
||||||
|
|
||||||
|
A query may only access records satisfying all required scope dimensions:
|
||||||
|
|
||||||
|
```text
|
||||||
|
user_id
|
||||||
|
AND tenant_id / group_id
|
||||||
|
AND session_id or conversation_id
|
||||||
|
AND project_id
|
||||||
|
AND workspace_id
|
||||||
|
AND branch or baseline scope
|
||||||
|
AND agent_id / tool_context when applicable
|
||||||
|
```
|
||||||
|
|
||||||
|
If a dimension is unavailable, the safe behavior is deny-by-default or text-only fallback.
|
||||||
|
|
||||||
|
## Forbidden Design
|
||||||
|
|
||||||
|
The following are forbidden in production paths:
|
||||||
|
|
||||||
|
1. Global shared memory directories without per-scope namespace.
|
||||||
|
2. Search over untagged records.
|
||||||
|
3. Search over records whose owner/scope cannot be proven.
|
||||||
|
4. Trusting filesystem location alone as authorization.
|
||||||
|
5. Treating memory search results as authoritative without provenance.
|
||||||
|
6. Cross-session fallback without explicit allowlist.
|
||||||
|
7. Auto-reporting from memory results that are not bound to the current runtime/baseline/task.
|
||||||
|
8. Using stale context from unrelated branches or projects as current-state evidence.
|
||||||
|
|
||||||
|
## Required Design
|
||||||
|
|
||||||
|
Every persisted memory/state record must include immutable metadata:
|
||||||
|
|
||||||
|
```text
|
||||||
|
record_id
|
||||||
|
user_id
|
||||||
|
tenant_id or group_id
|
||||||
|
session_id / conversation_id
|
||||||
|
project_id
|
||||||
|
workspace_id
|
||||||
|
branch
|
||||||
|
baseline
|
||||||
|
agent_id
|
||||||
|
source_tool
|
||||||
|
created_at
|
||||||
|
schema_version
|
||||||
|
sensitivity
|
||||||
|
retention_class
|
||||||
|
```
|
||||||
|
|
||||||
|
Every read/search request must include a scope envelope:
|
||||||
|
|
||||||
|
```text
|
||||||
|
request_user_id
|
||||||
|
request_tenant_id / group_id
|
||||||
|
request_session_id / conversation_id
|
||||||
|
request_project_id
|
||||||
|
request_workspace_id
|
||||||
|
allowed_branches / current_branch
|
||||||
|
allowed_baselines / current_baseline
|
||||||
|
purpose
|
||||||
|
```
|
||||||
|
|
||||||
|
A record is readable only if its metadata matches the request scope policy.
|
||||||
|
|
||||||
|
## Enforcement Layers
|
||||||
|
|
||||||
|
### 1. Storage namespace isolation
|
||||||
|
|
||||||
|
Memory/state paths must be namespaced:
|
||||||
|
|
||||||
|
```text
|
||||||
|
memory/{tenant_id}/{user_id}/{project_id}/{session_id}/...
|
||||||
|
state/{tenant_id}/{project_id}/{workspace_id}/...
|
||||||
|
```
|
||||||
|
|
||||||
|
No production component may write unrelated contexts into a single global `memory/` directory.
|
||||||
|
|
||||||
|
### 2. Metadata enforcement
|
||||||
|
|
||||||
|
Untagged records are unreadable by default.
|
||||||
|
|
||||||
|
Records without owner/scope metadata may be archived for forensic review but must not be searched or used for live reasoning.
|
||||||
|
|
||||||
|
### 3. Query-time ACL
|
||||||
|
|
||||||
|
Search must apply a mandatory scope filter before ranking or summarization.
|
||||||
|
|
||||||
|
The ranking stage must never receive out-of-scope records.
|
||||||
|
|
||||||
|
### 4. Provenance requirement
|
||||||
|
|
||||||
|
Every memory/search result used for operational reporting must carry provenance:
|
||||||
|
|
||||||
|
```text
|
||||||
|
record_id
|
||||||
|
scope metadata
|
||||||
|
source path or source index
|
||||||
|
match reason
|
||||||
|
created_at
|
||||||
|
```
|
||||||
|
|
||||||
|
Responses must prefer current runtime truth sources over memory:
|
||||||
|
|
||||||
|
```text
|
||||||
|
getRuntimeStatus
|
||||||
|
getBaseline
|
||||||
|
listPatches
|
||||||
|
explicit user-provided current context
|
||||||
|
current branch files
|
||||||
|
```
|
||||||
|
|
||||||
|
Memory search is advisory only after scope validation.
|
||||||
|
|
||||||
|
### 5. Fallback safety
|
||||||
|
|
||||||
|
If provider search cannot prove scope isolation, the system must use text-only fallback or no-memory fallback.
|
||||||
|
|
||||||
|
Fallback must not silently broaden the scope.
|
||||||
|
|
||||||
|
### 6. Write-path isolation
|
||||||
|
|
||||||
|
Writers must not append current-session records into shared directories.
|
||||||
|
|
||||||
|
Writers must derive the target path from the scope envelope, not from a global default.
|
||||||
|
|
||||||
|
### 7. Audit and detection
|
||||||
|
|
||||||
|
The system must produce audit events when:
|
||||||
|
|
||||||
|
- a record is denied due to scope mismatch;
|
||||||
|
- untagged memory is encountered;
|
||||||
|
- fallback disables memory search;
|
||||||
|
- a provider tries to return out-of-scope records;
|
||||||
|
- cross-context contamination is detected.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
A memory/search provider is allowed only if all tests pass:
|
||||||
|
|
||||||
|
1. Same user, same project, same session -> records are visible.
|
||||||
|
2. Same user, same project, different session -> visible only if policy permits.
|
||||||
|
3. Same user, different project -> denied by default.
|
||||||
|
4. Different user, same project -> denied unless explicitly shared by group policy.
|
||||||
|
5. Different tenant/group -> denied.
|
||||||
|
6. Untagged record -> denied.
|
||||||
|
7. Stale branch/baseline record -> not used as current evidence.
|
||||||
|
8. Provider fallback without scope support -> memory disabled.
|
||||||
|
9. Search result provenance is returned and logged.
|
||||||
|
10. Out-of-scope records are filtered before ranking/summarization.
|
||||||
|
|
||||||
|
## Runtime Rule
|
||||||
|
|
||||||
|
If memory search is enabled without these controls, recurrence is possible.
|
||||||
|
|
||||||
|
Therefore, memory search must remain disabled or in scoped allowlist mode until the isolation acceptance suite is green.
|
||||||
|
|
||||||
|
## Owner Gate
|
||||||
|
|
||||||
|
Any change that enables shared memory search, cross-session recall, global vector indexes, or cross-agent memory reuse requires owner/admin approval.
|
||||||
|
|
||||||
|
## Final Rule
|
||||||
|
|
||||||
|
User data isolation is a redline. Reliability, convenience, or recall quality may not override it.
|
||||||
Reference in New Issue
Block a user