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
This commit is contained in:
TheFlow 2025-10-12 11:13:55 +13:00
parent 8ada623bbf
commit 8cb075bce1
3 changed files with 1947 additions and 0 deletions

View file

@ -0,0 +1,783 @@
# 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).

1152
docs/api/examples-python.md Normal file

File diff suppressed because it is too large Load diff

View file

@ -81,6 +81,18 @@
Use this specification with Swagger UI, Postman, or any OpenAPI-compatible tool for interactive API exploration.
</p>
</div>
<div class="mt-4 bg-purple-50 border-l-4 border-purple-500 p-4">
<p class="text-sm text-purple-800">
<strong>💻 Code Examples:</strong>
<a href="/docs/api/examples-javascript.md" class="underline hover:text-purple-900 font-semibold">JavaScript</a>
<span class="mx-2 text-purple-600">|</span>
<a href="/docs/api/examples-python.md" class="underline hover:text-purple-900 font-semibold">Python</a>
</p>
<p class="text-xs text-purple-700 mt-1">
Complete integration examples for authentication, documents, governance services, and audit logs.
</p>
</div>
</div>
<!-- Authentication -->