# Getting Valid Plan Handle IDs for Testing

**Author**: Matthew Raymer  
**Version**: 1.0.0  
**Status**: Testing Setup Guide

## Overview

Plan handle IDs must match the format used by your TimeSafari database. The placeholder IDs (`test_project_1`, etc.) are not valid. This guide explains how to obtain real plan handle IDs for testing.

## Methods to Get Valid Plan Handle IDs

### Method 1: Create Projects in TimeSafari App (Recommended)

1. **Start TimeSafari app** (development or test app)
2. **Create a project** via the UI
3. **Get the plan handle ID**:
   - Open browser DevTools (F12)
   - Check Network tab for API responses when creating/loading projects
   - Look for the `handleId` field in API responses
   - Note: Plans are created via **POST `/api/v2/claim`** with a PlanAction JWT (see Method 6)
   - Or check localStorage/database for the plan record

### Method 2: Query Your Local Database

If you have access to your local TimeSafari database:

```sql
-- SQLite example
SELECT handleId FROM plans LIMIT 5;

-- Or check what format handleIds use
SELECT handleId, name FROM plans WHERE name IS NOT NULL LIMIT 10;
```

### Method 3: Use Starred Projects from Account Settings

1. **Open TimeSafari app**
2. **Star some projects** in the UI
3. **Check account settings**:
   ```javascript
   // In browser console or app
   const settings = await $accountSettings();
   console.log(settings.starredPlanHandleIds);
   ```

### Method 4: Check API Responses

1. **Query your localhost API**:
   ```bash
   curl http://localhost:3000/api/v2/report/plans?planHandleIds=[]
   ```
2. **Look for existing projects** in the response

### Method 5: Extract from Crowd-Master Database

If you're using crowd-master for testing:

```bash
cd /home/matthew/projects/timesafari/crowd-master
# Check your local database or API for actual plan handle IDs
```

### Method 6: Create Plans via PlanAction JWT Import

Plans are created by importing JWT claims containing a `PlanAction`:

**Route: POST `/api/v2/claim`**

```json
{
  "jwtEncoded": "<signed JWT with PlanAction claim>"
}
```

**Requirements**:
- JWT claim payload must include `@type: "PlanAction"`
- JWT must be signed with a valid DID key
- Response includes `handleId` and `planId` if creation succeeds

**Implementation Guide**: See [hydrate-plan-implementation-guide.md](./hydrate-plan-implementation-guide.md) for complete implementation details, including:
- `hydratePlan()` function pattern
- PlanActionClaim interface structure
- Helper functions for create/edit operations
- Usage examples and testing recommendations

**Note**: This method requires generating signed JWTs with DID keys, which is complex. **Method 1 (TimeSafari App UI) is recommended** for creating test plans.

## Plan Handle ID Format

Plan handle IDs **must be valid URIs** (RFC 3986 format).

### Default Format (System-Generated)

**`https://endorser.ch/entity/{ULID}`**

- **ULID**: 26-character string, Crockford base32 encoded
- **Example**: `https://endorser.ch/entity/01GQBE7Q0RQQAGJMEEW6RSGKTF`

### Custom Global URIs

Any valid URI with a scheme is accepted:
- `https://endorser.ch/entity/01GQBE7Q0RQQAGJMEEW6RSGKTF` (default)
- `http://example.com/project/123` (custom)
- `did:ethr:0x1234...` (DID format)
- Any URI matching: `^[A-Za-z][A-Za-z0-9+.-]+:`

**Validation**: The format must match RFC 3986 URI specification.

### ULID Format Details

- **Length**: Exactly 26 characters
- **Encoding**: Crockford base32 (0-9, A-Z excluding I, L, O, U)
- **Structure**: Timestamp + random component
- **Purpose**: Globally unique, lexicographically sortable identifiers

## Updating Test Configuration

Once you have valid plan handle IDs:

### Update Test Config

Edit `test-apps/daily-notification-test/src/config/test-user-zero.ts`:

```typescript
starredProjects: {
  planIds: [
    "your-real-plan-id-1",  // Replace with actual IDs
    "your-real-plan-id-2",
    "your-real-plan-id-3"
  ],
  // ...
}
```

### Update Seed Script Defaults

Edit `scripts/seed-test-projects.js`:

```javascript
const DEFAULT_TEST_PROJECT_IDS = [
  "your-real-plan-id-1",  // Replace with actual IDs
  "your-real-plan-id-2",
  "your-real-plan-id-3"
];
```

### Pass IDs via Command Line

You can also provide IDs when starting the test server:

```bash
# Start test server with your real plan IDs
node scripts/test-api-server-with-seed.js 3000 "id1,id2,id3"

# Or when seeding
node scripts/seed-test-projects.js seed http://localhost:3000 "id1,id2,id3"
```

## Quick Setup Workflow

1. **Start your local TimeSafari API** (if you have one)
2. **Create 3-5 test projects** via the UI or API
3. **Note the plan handle IDs** from the responses
4. **Update test-user-zero.ts** with those IDs
5. **Restart test server** with real IDs

## Using Placeholder IDs (Limited)

The placeholder IDs (`PLACEHOLDER_ID_1`, etc.) will work for testing the **structure and flow** of the prefetch system, but:

- ❌ Won't match real projects in your database
- ❌ API responses will be empty or fail validation
- ❌ Can't test actual starred projects querying

For full testing, you **must** use real plan handle IDs.

## Troubleshooting

### "Invalid plan handle ID" errors

- Check the format matches your database
- Verify IDs exist in your TimeSafari database
- Check API logs for validation errors

### Empty API responses

- Plan IDs don't exist in database
- IDs are in wrong format
- Database query is failing

### Cannot find plan IDs

- Check Network tab in DevTools when creating projects
- Query database directly
- Check localStorage/IndexedDB for plan records
- Look at API response when loading projects list

## Example: Finding IDs via Browser DevTools

1. Open TimeSafari app in browser
2. Open DevTools → Network tab
3. Create a new project
4. Look for POST/GET requests to `/api/v2/plans` or similar
5. Check response JSON for `handleId` field
6. Copy the `handleId` value

Example response might look like:
```json
{
  "handleId": "abc123def456789",
  "name": "My Test Project",
  ...
}
```

Use that `handleId` in your test configuration.

