# Project Management

Projects are isolated workspaces within a team that provide data isolation, fine-grained access control, and API key management.

***

## What is a Project?

A project is an isolated workspace that:

* **Belongs to a team** - Every project is owned by exactly one team
* **Has its own API key** - For service-to-service authentication
* **Provides data isolation** - Backend services filter data by project
* **Has its own members** - With specific roles (project\_admin, editor, viewer)
* **Stores metadata** - Custom configuration and settings

### Example Project Structure

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                        PROJECT: LLM API                                      │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  BASIC INFO                                                                 │
│  ══════════                                                                 │
│  Team: Engineering                                                          │
│  Status: active                                                             │
│  Created: 2025-01-15                                                        │
│                                                                              │
│  API KEY                                                                    │
│  ═══════                                                                    │
│  sk-llm-api-abc123... (shown only at creation)                              │
│  Last used: 2025-01-20 14:30:00                                             │
│                                                                              │
│  MEMBERS                                                                    │
│  ═══════                                                                    │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │ alice@turing.com    │ project_admin │ explicit  │ 2025-01-15       │   │
│  │ bob@turing.com      │ editor        │ explicit  │ 2025-01-16       │   │
│  │ carol@turing.com    │ viewer        │ explicit  │ 2025-01-17       │   │
│  │ dave@turing.com     │ team_admin    │ implicit  │ (via team role)  │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                              │
│  METADATA                                                                   │
│  ════════                                                                   │
│  {                                                                          │
│    "model": "gpt-4-turbo",                                                  │
│    "max_tokens": 8192,                                                      │
│    "temperature": 0.7,                                                      │
│    "config": {                                                              │
│      "destination_folder": ["production-outputs"],                          │
│      "enabled_features": ["summarization", "translation"]                   │
│    }                                                                        │
│  }                                                                          │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

***

## Project Roles

### project\_admin

Project administrators have full control over the project:

| Capability           | Description                          |
| -------------------- | ------------------------------------ |
| **Manage Members**   | Add/remove users, change roles       |
| **Edit Settings**    | Update project name, description     |
| **Manage Metadata**  | Create, update, delete metadata keys |
| **Manage API Keys**  | Create/revoke project API keys       |
| **Full Data Access** | Read and write all project data      |

### editor

Editors can work with project data but cannot manage the project:

| Capability           | Description                                             |
| -------------------- | ------------------------------------------------------- |
| **Read Data**        | View all project data                                   |
| **Write Data**       | Create, update, delete data                             |
| **Execute Services** | Call backend services                                   |
| **Cannot Manage**    | Cannot add members, change settings, or manage API keys |

### viewer

Viewers have read-only access:

| Capability         | Description                           |
| ------------------ | ------------------------------------- |
| **Read Data**      | View all project data                 |
| **Cannot Write**   | Cannot create, update, or delete data |
| **Cannot Execute** | Cannot call backend services          |
| **Cannot Manage**  | Cannot change anything                |

***

## Data Isolation

One of the most important features of projects is **data isolation**. Each project's data is completely separate from other projects.

### How It Works

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                        DATA ISOLATION FLOW                                   │
└─────────────────────────────────────────────────────────────────────────────┘

  User Request
  ────────────
  GET /v1/llm/history
  JWT contains: project_id = "abc-123"
         │
         ▼
  ┌─────────────────────────────────────────────────────────────────────────┐
  │                          AUTH GUARD                                      │
  │                                                                          │
  │  1. Validate JWT                                                         │
  │  2. Extract project_id from JWT: "abc-123"                               │
  │  3. Verify user is project member                                        │
  │  4. Inject header: X-Project-ID: abc-123                                 │
  │                                                                          │
  └─────────────────────────────────────────────────────────────────────────┘
         │
         │  Request with X-Project-ID header
         ▼
  ┌─────────────────────────────────────────────────────────────────────────┐
  │                        BACKEND SERVICE (LLM)                             │
  │                                                                          │
  │  @app.get("/history")                                                    │
  │  async def get_history(x_project_id: str = Header(...)):                 │
  │      # MUST filter by project_id                                         │
  │      return db.query(History).filter(                                    │
  │          History.project_id == x_project_id  # "abc-123"                 │
  │      ).all()                                                             │
  │                                                                          │
  │  Returns: Only history for project "abc-123"                             │
  │                                                                          │
  └─────────────────────────────────────────────────────────────────────────┘
```

### Why This Matters

| Without Isolation           | With Isolation                        |
| --------------------------- | ------------------------------------- |
| User A sees User B's data   | User A only sees their project's data |
| Data leaks between projects | Complete separation                   |
| Security vulnerabilities    | Secure by design                      |

### Backend Service Responsibility

⚠️ **Critical:** Backend services **MUST** filter all data by `X-Project-ID`:

```python
# ✅ CORRECT - Always filter by project_id
@app.get("/objects")
async def list_objects(x_project_id: str = Header(...)):
    return db.query(Object).filter(
        Object.project_id == x_project_id
    ).all()

# ❌ WRONG - Returns all data regardless of project
@app.get("/objects")
async def list_objects():
    return db.query(Object).all()  # SECURITY RISK!
```

***

## Access Types

When viewing project members, you'll see an `access_type` field:

### Explicit Access

User has a **direct role assignment** to the project.

```
User: bob@turing.com
Project: LLM API
Role: editor
Access Type: explicit
Assigned: 2025-01-16
```

### Implicit Access

User has access **via their team role** (team\_admin or team\_member get implicit access to all team projects).

```
User: dave@turing.com
Project: LLM API
Role: team_admin (inherited)
Access Type: implicit
Assigned: (via team membership)
```

### Access Hierarchy

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                        ACCESS RESOLUTION                                     │
└─────────────────────────────────────────────────────────────────────────────┘

  Does user have EXPLICIT project role?
         │
    ┌────┴────┐
    │         │
   YES       NO
    │         │
    ▼         ▼
  Use       Does user have TEAM role in project's team?
  explicit         │
  role        ┌────┴────┐
              │         │
             YES       NO
              │         │
              ▼         ▼
           Use        No access
           team       (403 Forbidden)
           role
           (implicit)
```

***

## Project Metadata

Projects can store arbitrary key-value metadata for configuration, settings, or custom data.

### Common Use Cases

| Use Case                 | Example Metadata                                             |
| ------------------------ | ------------------------------------------------------------ |
| **Model Configuration**  | `{"model": "gpt-4", "temperature": 0.7}`                     |
| **Feature Flags**        | `{"beta_features": true, "new_ui": false}`                   |
| **Integration Settings** | `{"webhook_url": "https://...", "notify_on_complete": true}` |
| **Storage Config**       | `{"destination_folder": ["outputs"], "retention_days": 30}`  |

### Metadata Operations

| Operation      | Description           | Permission Required               |
| -------------- | --------------------- | --------------------------------- |
| **Get All**    | Retrieve all metadata | `read:project` (viewer+)          |
| **Get Key**    | Retrieve specific key | `read:project` (viewer+)          |
| **Set Key**    | Create/update a key   | `write:project` (project\_admin+) |
| **Merge**      | Update multiple keys  | `write:project` (project\_admin+) |
| **Delete Key** | Remove a key          | `write:project` (project\_admin+) |

### Metadata Best Practices

| Do                         | Don't                          |
| -------------------------- | ------------------------------ |
| ✅ Store configuration      | ❌ Store secrets/passwords      |
| ✅ Store feature flags      | ❌ Store large binary data      |
| ✅ Use consistent key names | ❌ Store PII without encryption |
| ✅ Document your keys       | ❌ Use metadata as a database   |

***

## Admin Dashboard Features

Access project management at: `/admin/projects`

### Project List View

| Column      | Description              |
| ----------- | ------------------------ |
| **Name**    | Project name             |
| **Team**    | Parent team              |
| **Members** | Number of members        |
| **Status**  | active/inactive/archived |
| **Created** | Creation date            |

### Project Detail View

| Tab          | Features                               |
| ------------ | -------------------------------------- |
| **Overview** | Project info, stats, quick actions     |
| **Members**  | List members, add/remove, change roles |
| **Metadata** | View/edit configuration                |
| **API Keys** | Manage project API keys                |
| **Settings** | Edit name, description, status         |

***

## Common Scenarios

### Scenario 1: Creating a New Project

```
1. Go to Admin → Projects → Create Project
2. Select the parent team
3. Enter name and description
4. Project is created with you as project_admin
5. Add other members as needed
6. Configure metadata if required
7. Create API key for service access
```

### Scenario 2: Adding a User to a Project

```
1. Go to Admin → Projects → Select Project → Members
2. Click "Add Member"
3. Search for user by email
4. Select role: project_admin, editor, or viewer
5. Click "Add"

Note: User must be in the same organization.
If user is not in the team, they'll be added as team_member first.
```

### Scenario 3: User Needs Different Access Level

```
Current: bob@turing.com is "viewer"
Needed: bob@turing.com needs "editor"

1. Go to Project → Members
2. Find bob@turing.com
3. Click "Edit Role"
4. Change from "viewer" to "editor"
5. Save

Bob can now write data (effective immediately, no re-login needed)
```

### Scenario 4: Configuring Project for a Service

```
Project needs to use GPT-4 with specific settings:

1. Go to Project → Metadata
2. Add/update keys:
   - model: "gpt-4-turbo"
   - max_tokens: 8192
   - temperature: 0.7
3. Save

Backend service reads these settings via metadata API.
```

***

## Best Practices

### Project Structure

| Practice                     | Reason                           |
| ---------------------------- | -------------------------------- |
| **One project per use case** | Clear boundaries                 |
| **Meaningful names**         | "LLM Production" not "Project 1" |
| **Use descriptions**         | Document purpose                 |
| **Consistent naming**        | "team-service-env" pattern       |

### Member Management

| Practice                           | Reason                       |
| ---------------------------------- | ---------------------------- |
| **Limit project\_admins**          | 1-2 per project              |
| **Use viewer for read-only needs** | Principle of least privilege |
| **Review membership regularly**    | Remove inactive users        |

### Metadata Management

| Practice                      | Reason                         |
| ----------------------------- | ------------------------------ |
| **Document your keys**        | Others need to understand them |
| **Use namespaces**            | `config.model` vs just `model` |
| **Version sensitive changes** | Track what changed when        |
| **Don't store secrets**       | Use Secret Manager instead     |

***

## Troubleshooting

### "You are not a member of this project"

**Error:** `403 Forbidden: You are not a member of this project`

**Cause:** User doesn't have explicit or implicit project access.

**Solution:**

1. Add user to the project with appropriate role, OR
2. Add user to the team (team members have implicit access)
3. User may need to re-login for JWT to update

### "User must be a team member first"

**Error:** `400 Bad Request: User must be a team member before being added to a project`

**Cause:** Trying to add a user who isn't in the parent team.

**Solution:**

1. First add user to the team
2. Then add them to the project

### "Cannot access project data"

**Error:** Data requests return empty or 403

**Cause:** User's JWT has wrong project\_id, or backend isn't filtering correctly.

**Solution:**

1. Verify user is project member
2. User should re-login to get fresh JWT with correct project\_id
3. Check backend service is using X-Project-ID header

### "Metadata not updating"

**Error:** Metadata changes don't appear in backend service

**Cause:** Backend may cache metadata.

**Solution:**

1. Wait for cache TTL to expire
2. Backend should implement cache refresh
3. Verify metadata was actually saved in dashboard
