tractatus/docs/api/examples-javascript.md
TheFlow ca839123f1 feat: add comprehensive JavaScript and Python code examples
- Created examples-javascript.md (20KB, 638 lines)
  - Authentication, Documents, Governance, Audit examples
  - Node.js and browser implementations
  - Complete TractatusClient class
  - Error handling and retry logic
  - Rate limiting documentation

- Created examples-python.md (30KB, 983 lines)
  - Authentication, Documents, Governance, Audit examples
  - Type hints and data classes
  - Complete TractatusClient class
  - Error handling decorators and retry logic
  - Rate limiting documentation

- Updated api-reference.html with code examples links
- All examples deployed to production

Task 12 (API Documentation) - Code examples complete
2025-10-12 11:13:55 +13:00

783 lines
20 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# JavaScript API Examples
Complete examples for integrating with the Tractatus Framework API using JavaScript (Node.js and Browser).
## Table of Contents
- [Authentication](#authentication)
- [Documents](#documents)
- [Governance Services](#governance-services)
- [Audit Logs](#audit-logs)
- [Error Handling](#error-handling)
---
## Authentication
### Login and Store Token (Node.js)
```javascript
const axios = require('axios');
const API_BASE = 'https://agenticgovernance.digital/api';
// For local development: const API_BASE = 'http://localhost:9000/api';
async function login(email, password) {
try {
const response = await axios.post(`${API_BASE}/auth/login`, {
email,
password
});
const { token, user } = response.data;
// Store token for subsequent requests
process.env.TRACTATUS_TOKEN = token;
console.log('Login successful:', user);
return { token, user };
} catch (error) {
if (error.response?.status === 429) {
console.error('Too many login attempts. Please wait 15 minutes.');
} else if (error.response?.status === 401) {
console.error('Invalid credentials');
} else {
console.error('Login failed:', error.message);
}
throw error;
}
}
// Usage
login('admin@tractatus.local', 'your_password')
.then(({ token }) => {
console.log('Token:', token);
});
```
### Login and Store Token (Browser)
```javascript
async function login(email, password) {
try {
const response = await fetch('https://agenticgovernance.digital/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, password })
});
if (!response.ok) {
if (response.status === 429) {
throw new Error('Too many login attempts. Please wait 15 minutes.');
}
throw new Error('Login failed');
}
const { token, user } = await response.json();
// Store token in localStorage
localStorage.setItem('tractatus_token', token);
localStorage.setItem('tractatus_user', JSON.stringify(user));
console.log('Login successful:', user);
return { token, user };
} catch (error) {
console.error('Login error:', error);
throw error;
}
}
// Usage
login('admin@tractatus.local', 'your_password')
.then(({ user }) => {
console.log('Logged in as:', user.email);
});
```
### Making Authenticated Requests (Node.js)
```javascript
const axios = require('axios');
// Create axios instance with authentication
function createAuthClient(token) {
return axios.create({
baseURL: 'https://agenticgovernance.digital/api',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
}
// Usage
const token = process.env.TRACTATUS_TOKEN;
const client = createAuthClient(token);
// Now all requests include authentication
client.get('/governance/status')
.then(response => console.log(response.data));
```
### Making Authenticated Requests (Browser)
```javascript
async function authenticatedFetch(endpoint, options = {}) {
const token = localStorage.getItem('tractatus_token');
if (!token) {
throw new Error('Not authenticated. Please login first.');
}
const defaultOptions = {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
...options.headers
}
};
const response = await fetch(`https://agenticgovernance.digital/api${endpoint}`, {
...options,
...defaultOptions
});
if (response.status === 401) {
// Token expired or invalid
localStorage.removeItem('tractatus_token');
localStorage.removeItem('tractatus_user');
throw new Error('Session expired. Please login again.');
}
if (!response.ok) {
throw new Error(`API error: ${response.statusText}`);
}
return response.json();
}
// Usage
authenticatedFetch('/governance/status')
.then(data => console.log(data));
```
---
## Documents
### List All Documents
```javascript
async function listDocuments(options = {}) {
const { page = 1, limit = 50, quadrant } = options;
const params = new URLSearchParams({
page: page.toString(),
limit: limit.toString()
});
if (quadrant) {
params.append('quadrant', quadrant);
}
const response = await fetch(
`https://agenticgovernance.digital/api/documents?${params}`
);
if (!response.ok) {
throw new Error('Failed to fetch documents');
}
return response.json();
}
// Usage
listDocuments({ page: 1, limit: 10, quadrant: 'STRATEGIC' })
.then(data => {
console.log(`Found ${data.pagination.total} documents`);
data.documents.forEach(doc => {
console.log(`- ${doc.title} (${doc.quadrant})`);
});
});
```
### Get Single Document
```javascript
async function getDocument(identifier) {
const response = await fetch(
`https://agenticgovernance.digital/api/documents/${identifier}`
);
if (response.status === 404) {
throw new Error('Document not found');
}
if (!response.ok) {
throw new Error('Failed to fetch document');
}
return response.json();
}
// Usage (by slug)
getDocument('introduction-to-tractatus')
.then(data => {
console.log('Title:', data.document.title);
console.log('Quadrant:', data.document.quadrant);
console.log('Content:', data.document.content_html.substring(0, 100) + '...');
});
// Usage (by ID)
getDocument('672f821b6e820c0c7a0e0d55')
.then(data => console.log(data.document));
```
### Search Documents
```javascript
async function searchDocuments(query) {
const params = new URLSearchParams({ q: query });
const response = await fetch(
`https://agenticgovernance.digital/api/documents/search?${params}`
);
if (!response.ok) {
throw new Error('Search failed');
}
return response.json();
}
// Usage
searchDocuments('boundary enforcement')
.then(data => {
console.log(`Found ${data.count} results`);
data.results.forEach(result => {
console.log(`- ${result.title} (score: ${result.score})`);
});
});
```
### Create Document (Admin Only)
```javascript
async function createDocument(token, documentData) {
const client = createAuthClient(token);
try {
const response = await client.post('/documents', {
title: documentData.title,
slug: documentData.slug,
quadrant: documentData.quadrant,
content_markdown: documentData.content,
status: documentData.status || 'published'
});
console.log('Document created:', response.data.document._id);
return response.data.document;
} catch (error) {
if (error.response?.status === 403) {
console.error('Admin role required');
} else if (error.response?.status === 409) {
console.error('Slug already exists');
}
throw error;
}
}
// Usage
const newDocument = {
title: 'Advanced Boundary Enforcement Patterns',
slug: 'advanced-boundary-enforcement',
quadrant: 'OPERATIONAL',
content: '# Advanced Patterns\n\nThis document explores...',
status: 'published'
};
createDocument(process.env.TRACTATUS_TOKEN, newDocument);
```
---
## Governance Services
### InstructionPersistenceClassifier
```javascript
async function classifyInstruction(token, text, context = {}) {
const client = createAuthClient(token);
const response = await client.post('/governance/classify', {
text,
context: {
source: context.source || 'user',
session_id: context.session_id || 'default',
...context
}
});
return response.data.classification;
}
// Usage
classifyInstruction(
process.env.TRACTATUS_TOKEN,
'Always use MongoDB on port 27027',
{ source: 'user', session_id: 'sess_123' }
).then(classification => {
console.log('Quadrant:', classification.quadrant);
console.log('Persistence:', classification.persistence);
console.log('Temporal Scope:', classification.temporal_scope);
console.log('Confidence:', classification.confidence);
console.log('Reasoning:', classification.reasoning);
});
```
### CrossReferenceValidator
```javascript
async function validateAction(token, action, context = {}) {
const client = createAuthClient(token);
const response = await client.post('/governance/validate', {
action,
context: {
messages: context.messages || [],
session_id: context.session_id || 'default',
...context
}
});
return response.data.validation;
}
// Usage
const action = {
type: 'database_config',
target: 'MongoDB',
parameters: { port: 27017 }
};
validateAction(process.env.TRACTATUS_TOKEN, action)
.then(validation => {
if (validation.status === 'REJECTED') {
console.error('❌ Action rejected');
console.error('Reason:', validation.reason);
validation.conflicts.forEach(conflict => {
console.error(` Conflicts with: ${conflict.text} (${conflict.instruction_id})`);
});
console.log('Recommendation:', validation.recommendation);
} else if (validation.status === 'APPROVED') {
console.log('✅ Action approved');
}
});
```
### BoundaryEnforcer
```javascript
async function enforceBounda ry(token, action, context = {}) {
const client = createAuthClient(token);
const response = await client.post('/governance/enforce', {
action,
context
});
return response.data.enforcement;
}
// Usage
const action = {
type: 'policy_change',
description: 'Update privacy policy to enable more tracking',
impact: 'user_privacy'
};
enforceBoundary(process.env.TRACTATUS_TOKEN, action)
.then(enforcement => {
if (enforcement.decision === 'BLOCK') {
console.error('🚫 Action blocked - crosses values boundary');
console.error('Boundary:', enforcement.boundary_crossed);
console.error('Reason:', enforcement.reason);
console.log('\nAlternatives:');
enforcement.alternatives.forEach((alt, i) => {
console.log(`${i + 1}. ${alt}`);
});
} else {
console.log('✅ Action allowed');
}
});
```
### ContextPressureMonitor
```javascript
async function analyzePressure(token, context) {
const client = createAuthClient(token);
const response = await client.post('/governance/pressure', {
context: {
tokenUsage: context.tokenUsage || 50000,
tokenBudget: context.tokenBudget || 200000,
messageCount: context.messageCount || 20,
errorCount: context.errorCount || 0,
complexOperations: context.complexOperations || 0,
sessionDuration: context.sessionDuration || 1800
}
});
return response.data.pressure;
}
// Usage
analyzePressure(process.env.TRACTATUS_TOKEN, {
tokenUsage: 120000,
tokenBudget: 200000,
messageCount: 45,
errorCount: 3,
complexOperations: 8,
sessionDuration: 3600
}).then(pressure => {
console.log('Pressure Level:', pressure.level);
console.log('Score:', pressure.score + '%');
console.log('\nFactors:');
Object.entries(pressure.factors).forEach(([factor, data]) => {
console.log(` ${factor}: ${data.value} (${data.status})`);
});
console.log('\nRecommendation:', pressure.recommendation);
if (pressure.triggerHandoff) {
console.warn('⚠️ Session handoff recommended');
}
});
```
### MetacognitiveVerifier
```javascript
async function verifyAction(token, action, reasoning, context = {}) {
const client = createAuthClient(token);
const response = await client.post('/governance/verify', {
action,
reasoning,
context
});
return response.data.verification;
}
// Usage
const action = {
type: 'refactor',
scope: 'Refactor 47 files across 5 system areas',
complexity: 'high'
};
const reasoning = {
intent: 'Improve code organization',
approach: 'Extract shared utilities, consolidate duplicates',
risks: 'Potential breaking changes'
};
const context = {
requested: 'Refactor authentication module',
original_scope: 'single module'
};
verifyAction(process.env.TRACTATUS_TOKEN, action, reasoning, context)
.then(verification => {
console.log('Decision:', verification.decision);
console.log('Confidence:', verification.confidence);
if (verification.concerns.length > 0) {
console.log('\n⚠ Concerns:');
verification.concerns.forEach(concern => {
console.log(` [${concern.severity}] ${concern.type}: ${concern.detail}`);
});
}
if (verification.scopeCreep) {
console.warn('\n🔴 Scope creep detected');
}
console.log('\nCriteria Scores:');
Object.entries(verification.criteria).forEach(([criterion, score]) => {
console.log(` ${criterion}: ${(score * 100).toFixed(0)}%`);
});
if (verification.alternatives.length > 0) {
console.log('\nAlternatives:');
verification.alternatives.forEach((alt, i) => {
console.log(`${i + 1}. ${alt}`);
});
}
});
```
---
## Audit Logs
### Get Audit Logs with Filtering
```javascript
async function getAuditLogs(token, options = {}) {
const client = createAuthClient(token);
const params = {
page: options.page || 1,
limit: options.limit || 50
};
if (options.action) params.action = options.action;
if (options.userId) params.userId = options.userId;
if (options.startDate) params.startDate = options.startDate;
if (options.endDate) params.endDate = options.endDate;
const response = await client.get('/audit/audit-logs', { params });
return response.data;
}
// Usage
getAuditLogs(process.env.TRACTATUS_TOKEN, {
page: 1,
limit: 20,
action: 'validate_action',
startDate: '2025-10-01T00:00:00Z'
}).then(data => {
console.log(`Total logs: ${data.total}`);
data.logs.forEach(log => {
console.log(`[${log.timestamp}] ${log.service}: ${log.action} - ${log.status}`);
if (log.details) {
console.log(' Details:', JSON.stringify(log.details, null, 2));
}
});
});
```
### Get Audit Analytics
```javascript
async function getAuditAnalytics(token, startDate, endDate) {
const client = createAuthClient(token);
const params = {};
if (startDate) params.startDate = startDate;
if (endDate) params.endDate = endDate;
const response = await client.get('/audit/audit-analytics', { params });
return response.data.analytics;
}
// Usage
getAuditAnalytics(
process.env.TRACTATUS_TOKEN,
'2025-10-01T00:00:00Z',
'2025-10-12T23:59:59Z'
).then(analytics => {
console.log('Total Events:', analytics.total_events);
console.log('\nBreakdown by Service:');
Object.entries(analytics.by_service).forEach(([service, count]) => {
console.log(` ${service}: ${count}`);
});
console.log('\nBreakdown by Status:');
Object.entries(analytics.by_status).forEach(([status, count]) => {
console.log(` ${status}: ${count}`);
});
console.log('\nRejection Rate:', analytics.rejection_rate + '%');
});
```
---
## Error Handling
### Comprehensive Error Handler
```javascript
async function handleApiRequest(requestFn) {
try {
return await requestFn();
} catch (error) {
// Axios error structure
if (error.response) {
const { status, data } = error.response;
switch (status) {
case 400:
console.error('Bad Request:', data.message);
console.error('Details:', data.details);
break;
case 401:
console.error('Unauthorized: Please login');
// Clear stored token
localStorage.removeItem('tractatus_token');
break;
case 403:
console.error('Forbidden: Insufficient permissions');
console.error('Required role:', data.required_role || 'admin');
break;
case 404:
console.error('Not Found:', data.message);
break;
case 409:
console.error('Conflict:', data.message);
console.error('Conflicting resource:', data.conflict);
break;
case 429:
console.error('Rate Limit Exceeded:', data.message);
console.error('Retry after:', error.response.headers['retry-after']);
break;
case 500:
console.error('Internal Server Error');
console.error('Error ID:', data.errorId);
break;
default:
console.error('API Error:', status, data.message);
}
} else if (error.request) {
console.error('Network Error: No response received');
console.error('Check your internet connection');
} else {
console.error('Error:', error.message);
}
throw error;
}
}
// Usage
handleApiRequest(async () => {
return await classifyInstruction(token, 'Test instruction');
})
.then(result => console.log('Success:', result))
.catch(error => console.log('Handled error'));
```
### Retry Logic with Exponential Backoff
```javascript
async function retryWithBackoff(fn, maxRetries = 3, baseDelay = 1000) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
// Don't retry on client errors (4xx except 429)
if (error.response?.status >= 400 &&
error.response?.status < 500 &&
error.response?.status !== 429) {
throw error;
}
const delay = baseDelay * Math.pow(2, attempt - 1);
console.log(`Attempt ${attempt} failed. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// Usage
retryWithBackoff(async () => {
return await getDocument('some-slug');
}, 3, 1000)
.then(doc => console.log('Document:', doc))
.catch(error => console.error('All retries failed:', error));
```
---
## Complete Example: Full Integration
```javascript
const axios = require('axios');
class TractatusClient {
constructor(baseURL = 'https://agenticgovernance.digital/api') {
this.baseURL = baseURL;
this.token = null;
this.client = axios.create({ baseURL });
}
async login(email, password) {
const response = await this.client.post('/auth/login', { email, password });
this.token = response.data.token;
this.client.defaults.headers.common['Authorization'] = `Bearer ${this.token}`;
return response.data;
}
async classifyInstruction(text, context = {}) {
const response = await this.client.post('/governance/classify', { text, context });
return response.data.classification;
}
async validateAction(action, context = {}) {
const response = await this.client.post('/governance/validate', { action, context });
return response.data.validation;
}
async getDocuments(options = {}) {
const response = await this.client.get('/documents', { params: options });
return response.data;
}
}
// Usage
const tractatus = new TractatusClient();
async function main() {
await tractatus.login('admin@tractatus.local', 'password');
const classification = await tractatus.classifyInstruction(
'Always use MongoDB on port 27027'
);
console.log('Classification:', classification);
const docs = await tractatus.getDocuments({ limit: 5 });
console.log(`Found ${docs.total} documents`);
}
main().catch(console.error);
```
---
## Rate Limiting
The Tractatus API implements rate limiting:
- **Login endpoint**: 5 attempts per 15 minutes per IP
- **General API**: 100 requests per 15 minutes per IP
Handle rate limiting:
```javascript
async function apiCallWithRateLimit(fn) {
try {
return await fn();
} catch (error) {
if (error.response?.status === 429) {
const retryAfter = error.response.headers['retry-after'];
console.warn(`Rate limited. Retry after ${retryAfter} seconds`);
// Wait and retry
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return await fn();
}
throw error;
}
}
```
---
For more information, see the [API Reference](https://agenticgovernance.digital/api-reference.html) and [OpenAPI Specification](https://agenticgovernance.digital/docs/api/openapi.yaml).