# 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).