Files
daily-notification-plugin/docs/getting-valid-plan-ids.md
Matthew Raymer ed5dcfbbd1 docs(testing): add PlanAction JWT hydration implementation guide
Add comprehensive implementation guide for creating PlanAction claims
via hydratePlan() function pattern, following established hydrateGive()
and hydrateOffer() patterns.

Changes:
- Add hydrate-plan-implementation-guide.md with complete implementation
  details, usage examples, and testing recommendations
- Link implementation guide from getting-valid-plan-ids.md Method 6
- Link implementation guide from localhost-testing-guide.md Option B

The guide provides:
- Complete hydratePlan() function implementation
- PlanActionClaim interface structure
- Helper functions (createAndSubmitPlan, editAndSubmitPlan)
- Usage examples and edge cases
- Testing recommendations and security considerations

This complements plan creation documentation by showing how to
programmatically construct valid PlanAction JWTs for POST /api/v2/claim.
2025-10-29 12:46:41 +00:00

219 lines
6.0 KiB
Markdown

# 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 [`docs/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.