# Technical Design: System Profile + Principal Profile Isolation

## Goal

Stop one user's private facts from being treated as shared state while still keeping a reusable system-wide policy layer.

## Design summary

Use a **layered prompt model**:

1. **System / global profile**
   - One shared policy layer for the whole Hermes deployment
   - Admin-only edits from the local machine
   - Holds stable behavior, safety policy, formatting rules, and product-wide defaults

2. **Principal profile**
   - One durable profile per canonical principal
   - Bound to the verified email and external identities for that person
   - Holds personal preferences and durable user-specific facts

3. **Session context**
   - Temporary, turn-local context only
   - Used for the current conversation and discarded unless it becomes a durable preference

## Precedence rules

Highest priority first:

1. system / safety / governance rules
2. developer or platform constraints
3. principal profile
4. session context

A lower layer may tailor the response, but it may not override a higher layer.

## Data model

### Canonical identity
- `principal_id`
- `verified_email`
- `external_identities`
- `profile_path`
- `last_verified_at`

### System profile
- Stored separately from principal data
- Editable only by local admin workflows
- Contains reusable rules that are not private to any one person

### Principal profile
- Stored under the canonical principal namespace
- Contains only data that belongs to that principal
- Must never be auto-populated from another person's conversation

### Shared knowledge
- Global, non-private FAQ / reusable notes
- Safe only when content is sanitized and clearly non-personal
- Lives outside principal homes

## Runtime flow

1. Resolve the live caller to a canonical principal.
2. Load the global system profile.
3. Load the matching principal profile.
4. Add session-only context.
5. Route session storage, response-chain storage, and managed-download ownership through the same resolved principal profile.
6. Build the prompt.
7. Refuse to build cross-principal context if the caller cannot be resolved.

## Write rules

### Allowed
- Admin local editing of the system profile
- Verified principal editing their own principal profile within allowed fields
- Session-only facts for the current conversation

### Not allowed
- Gateway users editing the global system profile
- One principal writing into another principal's profile
- Treating session-only facts as durable cross-user state
- Using `email` as the sole identity key when `principal_id` is available

## Security requirements

- Fail closed when caller identity is ambiguous
- Do not fall back to operator defaults on shared surfaces
- Do not treat summaries or snippets as public
- Sanitize shared knowledge before injection
- Keep audit trails for every profile write

## API response-chain and file-delivery requirements

- `previous_response_id`, conversation-name chaining, and response retrieval must resolve from the active principal profile only
- Session CRUD and message history endpoints must read and write `state.db` inside the resolved principal profile only
- Managed downloads may expose two delivery modes:
  - `private`: keep `owner_metadata` and enforce caller-bound access
  - `public`: strip `owner_metadata` but keep the same expiry semantics
- Any UI or API that can generate a managed download should be able to surface a caller choice between `private` and `public` without changing the underlying expiry contract

## Files to inspect during implementation

- `agent/prompt_builder.py`
- `agent/shared_knowledge.py`
- `gateway/principal_profiles.py`
- `gateway/user_verification.py`
- `hermes_cli/subcommands/memory.py`
- `tests/agent/test_system_prompt_principal_precedence.py`
- `tests/agent/test_system_prompt_shared_knowledge.py`
- `tests/gateway/test_principal_profile_routing_phase1.py`
- `tests/gateway/test_principal_profile_runtime_phase2.py`
- `tests/gateway/test_api_server.py`
- `tests/gateway/test_multiplex_api_server_routing.py`
- `tests/hermes_cli/test_managed_downloads.py`

## Rollout note

When this design changes, update this file first, then update the code comments that point here so future edits still have a clear starting point.