tractatus/docs/api/PROJECTS_API.md
TheFlow c96ad31046 feat: implement Rule Manager and Project Manager admin systems
Major Features:
- Multi-project governance with Rule Manager web UI
- Project Manager for organizing governance across projects
- Variable substitution system (${VAR_NAME} in rules)
- Claude.md analyzer for instruction extraction
- Rule quality scoring and optimization

Admin UI Components:
- /admin/rule-manager.html - Full-featured rule management interface
- /admin/project-manager.html - Multi-project administration
- /admin/claude-md-migrator.html - Import rules from Claude.md files
- Dashboard enhancements for governance analytics

Backend Implementation:
- Controllers: projects, rules, variables
- Models: Project, VariableValue, enhanced GovernanceRule
- Routes: /api/projects, /api/rules with full CRUD
- Services: ClaudeMdAnalyzer, RuleOptimizer, VariableSubstitution
- Utilities: mongoose helpers

Documentation:
- User guides for Rule Manager and Projects
- Complete API documentation (PROJECTS_API, RULES_API)
- Phase 3 planning and architecture diagrams
- Test results and error analysis
- Coding best practices summary

Testing & Scripts:
- Integration tests for projects API
- Unit tests for variable substitution
- Database migration scripts
- Seed data generation
- Test token generator

Key Capabilities:
 UNIVERSAL scope rules apply across all projects
 PROJECT_SPECIFIC rules override for individual projects
 Variable substitution per-project (e.g., ${DB_PORT} → 27017)
 Real-time validation and quality scoring
 Advanced filtering and search
 Import from existing Claude.md files

Technical Details:
- MongoDB-backed governance persistence
- RESTful API with Express
- JWT authentication for admin endpoints
- CSP-compliant frontend (no inline handlers)
- Responsive Tailwind UI

This implements Phase 3 architecture as documented in planning docs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 17:16:51 +13:00

822 lines
17 KiB
Markdown

# Projects & Variables API Documentation
**Version:** 1.0
**Base URL:** `/api/admin`
**Authentication:** Required (Bearer token)
---
## Table of Contents
1. [Overview](#overview)
2. [Authentication](#authentication)
3. [Projects API](#projects-api)
4. [Variables API](#variables-api)
5. [Variable Substitution](#variable-substitution)
6. [Error Handling](#error-handling)
7. [Usage Examples](#usage-examples)
---
## Overview
The Projects & Variables API provides multi-project governance capabilities, allowing administrators to:
- Manage multiple projects with project-specific configurations
- Define and manage variable values per project
- Substitute variables in governance rules with project-specific values
- Support context-aware rule rendering
**Key Concepts:**
- **Project**: A codebase or application with its own configuration (e.g., `tractatus`, `family-history`)
- **Variable**: A placeholder in governance rules (e.g., `${DB_NAME}`, `${API_PORT}`)
- **Variable Value**: The actual value of a variable for a specific project
- **Variable Substitution**: Replacing `${VAR_NAME}` in rule text with actual values
---
## Authentication
All endpoints require admin authentication.
**Headers:**
```http
Authorization: Bearer <admin_token>
Content-Type: application/json
```
**Error Response (401):**
```json
{
"error": "Unauthorized",
"message": "Invalid or missing authentication token"
}
```
---
## Projects API
### GET /api/admin/projects
Get all projects with optional filtering.
**Query Parameters:**
- `active` (string, optional): Filter by active status (`"true"`, `"false"`, or omit for all)
- `database` (string, optional): Filter by database type (e.g., `"MongoDB"`, `"PostgreSQL"`)
**Response (200):**
```json
{
"success": true,
"projects": [
{
"_id": "507f1f77bcf86cd799439011",
"id": "tractatus",
"name": "Tractatus AI Safety Framework",
"description": "The Tractatus website...",
"techStack": {
"framework": "Express.js",
"database": "MongoDB",
"frontend": "Vanilla JavaScript"
},
"repositoryUrl": "https://github.com/example/tractatus",
"metadata": {
"environment": "production"
},
"active": true,
"variableCount": 7,
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": "2025-01-15T10:00:00.000Z"
}
],
"total": 1
}
```
---
### GET /api/admin/projects/:id
Get a single project by ID.
**URL Parameters:**
- `id` (string, required): Project ID (e.g., `tractatus`)
**Response (200):**
```json
{
"success": true,
"project": {
"_id": "507f1f77bcf86cd799439011",
"id": "tractatus",
"name": "Tractatus AI Safety Framework",
"description": "...",
"techStack": { ... },
"repositoryUrl": "...",
"metadata": { ... },
"active": true,
"variableCount": 7,
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": "2025-01-15T10:00:00.000Z"
}
}
```
**Error Response (404):**
```json
{
"success": false,
"message": "Project not found"
}
```
---
### POST /api/admin/projects
Create a new project.
**Request Body:**
```json
{
"id": "new-project",
"name": "New Project Name",
"description": "Optional description",
"techStack": {
"framework": "Express.js",
"database": "MongoDB"
},
"repositoryUrl": "https://github.com/...",
"metadata": {
"environment": "development"
},
"active": true
}
```
**Required Fields:**
- `id` (string): Unique project identifier (kebab-case recommended)
- `name` (string): Project display name
**Response (201):**
```json
{
"success": true,
"project": { ... },
"message": "Project created successfully"
}
```
**Error Response (400):**
```json
{
"success": false,
"message": "Project with this ID already exists"
}
```
---
### PUT /api/admin/projects/:id
Update an existing project.
**URL Parameters:**
- `id` (string, required): Project ID
**Request Body (all fields optional):**
```json
{
"name": "Updated Name",
"description": "Updated description",
"techStack": {
"framework": "Next.js",
"database": "PostgreSQL"
},
"repositoryUrl": "https://github.com/...",
"metadata": {
"version": "2.0"
},
"active": true
}
```
**Response (200):**
```json
{
"success": true,
"project": { ... },
"message": "Project updated successfully"
}
```
---
### DELETE /api/admin/projects/:id
Delete a project (soft delete by default).
**URL Parameters:**
- `id` (string, required): Project ID
**Query Parameters:**
- `hard` (string, optional): Set to `"true"` for permanent deletion
**Behavior:**
- **Soft Delete (default)**: Sets `active: false` on project and all its variables
- **Hard Delete**: Permanently removes project and all associated variables from database
**Response (200):**
```json
{
"success": true,
"message": "Project deleted successfully (soft delete)",
"deletedCount": 1,
"variablesDeactivated": 7
}
```
**Hard Delete Response:**
```json
{
"success": true,
"message": "Project permanently deleted",
"deletedCount": 1,
"variablesDeleted": 7
}
```
---
### GET /api/admin/projects/stats
Get project statistics.
**Response (200):**
```json
{
"success": true,
"stats": {
"total": 4,
"active": 3,
"inactive": 1,
"byDatabase": {
"MongoDB": 2,
"PostgreSQL": 1,
"MySQL": 1
},
"totalVariables": 26
}
}
```
---
## Variables API
### GET /api/admin/projects/:projectId/variables
Get all variables for a specific project.
**URL Parameters:**
- `projectId` (string, required): Project ID
**Response (200):**
```json
{
"success": true,
"variables": [
{
"_id": "507f1f77bcf86cd799439012",
"projectId": "tractatus",
"variableName": "DB_NAME",
"value": "tractatus_prod",
"description": "Production database name",
"category": "database",
"dataType": "string",
"active": true,
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": "2025-01-15T10:00:00.000Z"
}
],
"total": 7
}
```
---
### GET /api/admin/projects/variables/global
Get all variables across all projects.
**Query Parameters:**
- `active` (string, optional): Filter by active status
**Response (200):**
```json
{
"success": true,
"variables": [
{
"_id": "...",
"projectId": "tractatus",
"variableName": "DB_NAME",
"value": "tractatus_prod",
"projectName": "Tractatus AI Safety Framework",
...
}
],
"total": 26
}
```
---
### POST /api/admin/projects/:projectId/variables
Create or update a variable (upsert).
**URL Parameters:**
- `projectId` (string, required): Project ID
**Request Body:**
```json
{
"variableName": "DB_NAME",
"value": "tractatus_prod",
"description": "Production database name",
"category": "database",
"dataType": "string"
}
```
**Required Fields:**
- `variableName` (string): Variable name in UPPER_SNAKE_CASE (e.g., `DB_NAME`, `API_KEY_2`)
- `value` (string): Variable value
**Variable Name Validation:**
- Must match pattern: `/^[A-Z][A-Z0-9_]*$/`
- Must start with uppercase letter
- Can only contain uppercase letters, numbers, and underscores
**Categories:**
- `database` - Database configuration
- `config` - Application configuration
- `url` - URLs and endpoints
- `path` - File paths and directories
- `security` - Security credentials (use with caution)
- `feature_flag` - Feature flags
- `other` - Miscellaneous
**Data Types:**
- `string` (default)
- `number`
- `boolean`
- `json`
**Response (201 for create, 200 for update):**
```json
{
"success": true,
"variable": { ... },
"message": "Variable created successfully",
"isNew": true
}
```
**Error Response (400):**
```json
{
"success": false,
"error": "Invalid variable name",
"message": "Variable name must be UPPER_SNAKE_CASE (e.g., DB_NAME, API_KEY_2)"
}
```
---
### PUT /api/admin/projects/:projectId/variables/:variableName
Update an existing variable.
**URL Parameters:**
- `projectId` (string, required): Project ID
- `variableName` (string, required): Variable name
**Request Body (all fields optional):**
```json
{
"value": "new_value",
"description": "Updated description",
"category": "config",
"dataType": "string"
}
```
**Response (200):**
```json
{
"success": true,
"variable": { ... },
"message": "Variable updated successfully"
}
```
---
### DELETE /api/admin/projects/:projectId/variables/:variableName
Delete a variable (soft delete by default).
**URL Parameters:**
- `projectId` (string, required): Project ID
- `variableName` (string, required): Variable name
**Query Parameters:**
- `hard` (string, optional): Set to `"true"` for permanent deletion
**Response (200):**
```json
{
"success": true,
"message": "Variable deleted successfully"
}
```
---
### POST /api/admin/projects/:projectId/variables/validate
Validate variables against governance rules.
**URL Parameters:**
- `projectId` (string, required): Project ID
**Request Body:**
```json
{
"variables": ["DB_NAME", "API_PORT", "LOG_LEVEL"]
}
```
**Response (200):**
```json
{
"success": true,
"validation": {
"projectId": "tractatus",
"totalVariables": 3,
"found": ["DB_NAME", "API_PORT"],
"missing": ["LOG_LEVEL"],
"missingCount": 1
}
}
```
---
### POST /api/admin/projects/:projectId/variables/batch
Batch create/update variables.
**URL Parameters:**
- `projectId` (string, required): Project ID
**Request Body:**
```json
{
"variables": [
{
"variableName": "DB_NAME",
"value": "tractatus_prod",
"description": "Database name",
"category": "database"
},
{
"variableName": "DB_PORT",
"value": "27017",
"description": "Database port",
"category": "database",
"dataType": "number"
}
]
}
```
**Response (200):**
```json
{
"success": true,
"results": {
"created": 1,
"updated": 1,
"failed": 0,
"total": 2
},
"variables": [ ... ],
"message": "Batch operation completed: 1 created, 1 updated"
}
```
---
## Variable Substitution
### GET /api/admin/rules?projectId={projectId}
Get rules with variable substitution.
**Query Parameters:**
- `projectId` (string, optional): Project ID for variable substitution
- All standard rule filters (scope, quadrant, etc.)
**Behavior:**
- When `projectId` is **not** provided: Returns rules with template text only
- When `projectId` **is** provided: Returns rules with both template and rendered text
**Response WITHOUT projectId:**
```json
{
"success": true,
"rules": [
{
"id": "inst_001",
"text": "Connect to database ${DB_NAME} on port ${DB_PORT}",
"scope": "UNIVERSAL",
...
}
]
}
```
**Response WITH projectId:**
```json
{
"success": true,
"rules": [
{
"id": "inst_001",
"text": "Connect to database ${DB_NAME} on port ${DB_PORT}",
"renderedText": "Connect to database tractatus_prod on port 27017",
"projectContext": "tractatus",
"substitutions": {
"DB_NAME": "tractatus_prod",
"DB_PORT": "27017"
},
"scope": "UNIVERSAL",
...
}
]
}
```
**Variable Detection:**
- Variables are detected using pattern: `/\$\{([A-Z][A-Z0-9_]*)\}/g`
- Only UPPER_SNAKE_CASE variables are recognized
- Missing variables are left as `${MISSING_VAR}` in rendered text
- Warning included in response if variables are missing
---
## Error Handling
### Standard Error Response Format
```json
{
"success": false,
"error": "ErrorType",
"message": "Human-readable error description"
}
```
### HTTP Status Codes
| Code | Meaning | Common Causes |
|------|---------|---------------|
| 200 | OK | Successful GET/PUT/DELETE |
| 201 | Created | Successful POST |
| 400 | Bad Request | Invalid input, validation errors |
| 401 | Unauthorized | Missing/invalid token |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate ID |
| 500 | Internal Server Error | Server-side error |
### Common Error Scenarios
**Duplicate Project ID:**
```json
{
"success": false,
"message": "Project with ID 'tractatus' already exists"
}
```
**Invalid Variable Name:**
```json
{
"success": false,
"error": "Invalid variable name",
"message": "Variable name must be UPPER_SNAKE_CASE (e.g., DB_NAME, API_KEY_2)"
}
```
**Project Not Found:**
```json
{
"success": false,
"message": "Project 'invalid-id' not found"
}
```
---
## Usage Examples
### Example 1: Create a New Project with Variables
```javascript
// Step 1: Create project
const projectResponse = await fetch('/api/admin/projects', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 'my-app',
name: 'My Application',
description: 'A new application',
techStack: {
framework: 'Express.js',
database: 'MongoDB'
},
active: true
})
});
const project = await projectResponse.json();
console.log(project.project.id); // 'my-app'
// Step 2: Add variables using batch operation
const variablesResponse = await fetch('/api/admin/projects/my-app/variables/batch', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
variables: [
{
variableName: 'DB_NAME',
value: 'my_app_db',
category: 'database'
},
{
variableName: 'APP_PORT',
value: '3000',
category: 'config',
dataType: 'number'
}
]
})
});
const result = await variablesResponse.json();
console.log(result.results); // { created: 2, updated: 0, failed: 0, total: 2 }
```
### Example 2: View Rules with Variable Substitution
```javascript
// Get rules with variable substitution for 'tractatus' project
const response = await fetch('/api/admin/rules?projectId=tractatus', {
headers: {
'Authorization': `Bearer ${token}`
}
});
const data = await response.json();
data.rules.forEach(rule => {
console.log('Template:', rule.text);
// "Connect to database ${DB_NAME} on port ${DB_PORT}"
console.log('Rendered:', rule.renderedText);
// "Connect to database tractatus_prod on port 27017"
console.log('Substitutions:', rule.substitutions);
// { DB_NAME: "tractatus_prod", DB_PORT: "27017" }
});
```
### Example 3: Update Variable Value
```javascript
// Update DB_PORT for tractatus project
const response = await fetch('/api/admin/projects/tractatus/variables/DB_PORT', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
value: '27018', // Updated port
description: 'Updated MongoDB port'
})
});
const result = await response.json();
console.log(result.message); // 'Variable updated successfully'
```
### Example 4: Validate Required Variables
```javascript
// Check if all required variables exist for a project
const response = await fetch('/api/admin/projects/my-app/variables/validate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
variables: ['DB_NAME', 'DB_PORT', 'API_KEY', 'SECRET_KEY']
})
});
const validation = await response.json();
if (validation.validation.missingCount > 0) {
console.error('Missing variables:', validation.validation.missing);
// Create missing variables...
}
```
### Example 5: Soft Delete vs Hard Delete
```javascript
// Soft delete (default) - deactivates project and variables
const softDelete = await fetch('/api/admin/projects/old-project', {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${token}` }
});
const result1 = await softDelete.json();
console.log(result1.message); // 'Project deleted successfully (soft delete)'
// Hard delete - permanently removes from database
const hardDelete = await fetch('/api/admin/projects/old-project?hard=true', {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${token}` }
});
const result2 = await hardDelete.json();
console.log(result2.message); // 'Project permanently deleted'
```
---
## Best Practices
### Variable Naming
- ✅ Use UPPER_SNAKE_CASE: `DB_NAME`, `API_KEY_2`, `MAX_CONNECTIONS`
- ❌ Avoid lowercase or camelCase: `dbName`, `api_key`, `maxConnections`
### Security
- 🔒 Never commit sensitive variable values to version control
- 🔒 Use category `security` for credentials
- 🔒 Consider encrypting sensitive values in database
- 🔒 Rotate API keys regularly
### Organization
- 📁 Use categories to group related variables
- 📝 Provide clear descriptions for all variables
- 🏷️ Use consistent naming conventions across projects
- 🔄 Use batch operations for bulk updates
### Performance
- ⚡ Cache project data when possible
- ⚡ Use filters to reduce response payload
- ⚡ Batch variable operations instead of individual requests
- ⚡ Only request variable substitution when needed
---
## API Version History
**v1.0 (2025-01-15)**
- Initial release
- Projects CRUD operations
- Variables CRUD operations
- Variable substitution in rules
- Batch operations
- Validation endpoints
---
**Last Updated:** 2025-01-15
**Maintained By:** Tractatus Framework Team