- Updated `package.json` in `web-service-package`, `cli-package`, and the root project to prefix internal NPM scripts with an underscore (`_`), such as `_version`, `_deploy`, `_dry-run`, etc. - Adjusted all relevant build, versioning, deployment, and test scripts to follow this convention. - Updated `.gitignore` to include `/brainy-models-package/node_modules/` for effective exclusion. **Purpose**: Standardize the naming of internal scripts to better differentiate them from user-facing commands and maintain consistency across packages. |
||
|---|---|---|
| .. | ||
| dist | ||
| src | ||
| tests | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| rollup.config.js | ||
| server-wrapper.js | ||
| tsconfig.json | ||
| vitest.config.ts | ||
Brainy Web Service
A secure, read-only web service wrapper for the Brainy vector graph database. This service exposes Brainy's search capabilities through RESTful API endpoints, designed specifically as a search service with comprehensive security measures.
Features
- 🔒 Read-only by design - Only safe search operations are exposed
- 🚀 RESTful API - Clean, well-documented HTTP endpoints
- 🛡️ Security-first - Rate limiting, input validation, CORS, and security headers
- 📊 Comprehensive search - Vector search, text search, similarity search
- 🔍 Flexible querying - Support for noun types, verb filtering, and pagination
- 📈 Production-ready - Proper error handling, logging, and graceful shutdown
- 🌐 CORS enabled - Ready for browser-based applications
Installation
npm install -g @soulcraft/brainy-web-service
Or run directly:
npx @soulcraft/brainy-web-service
Quick Start
-
Start the service:
brainy-server -
Check if it's running:
curl http://localhost:3000/health -
View API documentation:
curl http://localhost:3000/api
🚀 Easy Deployment
Option 1: Direct NPM Deployment
# Install globally and run
npm install -g @soulcraft/brainy-web-service
brainy-server
Option 2: One-liner with npx
# Run without installation
npx @soulcraft/brainy-web-service
Option 3: Docker Deployment
# Create a simple Dockerfile
cat > Dockerfile << EOF
FROM node:24-alpine
RUN npm install -g @soulcraft/brainy-web-service
EXPOSE 3000
CMD ["brainy-server"]
EOF
# Build and run
docker build -t brainy-web-service .
docker run -p 3000:3000 brainy-web-service
Option 4: Cloud Platform Deployment
Google Cloud Platform (App Engine)
# Create package.json
echo '{"scripts":{"start":"brainy-server"},"dependencies":{"@soulcraft/brainy-web-service":"latest"}}' > package.json
# Create app.yaml for App Engine
cat > app.yaml << EOF
runtime: nodejs20
env: standard
automatic_scaling:
min_instances: 1
max_instances: 10
EOF
# Deploy to App Engine
gcloud app deploy
AWS (App Runner)
# Create package.json
echo '{"scripts":{"start":"brainy-server"},"dependencies":{"@soulcraft/brainy-web-service":"latest"}}' > package.json
# Create apprunner.yaml
cat > apprunner.yaml << EOF
version: 1.0
runtime: nodejs20
build:
commands:
build:
- npm install
run:
runtime-version: 20
command: npm start
network:
port: 3000
env: PORT
EOF
# Deploy via AWS App Runner console or CLI
aws apprunner create-service --service-name brainy-web-service --source-configuration '{...}'
Microsoft Azure (App Service)
# Create package.json
echo '{"scripts":{"start":"brainy-server"},"dependencies":{"@soulcraft/brainy-web-service":"latest"}}' > package.json
# Deploy using Azure CLI
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name brainy-web-service --runtime "NODE:20-lts"
az webapp deployment source config-zip --resource-group myResourceGroup --name brainy-web-service --src deployment.zip
Cloudflare Workers
# Create package.json
echo '{"scripts":{"start":"brainy-server"},"dependencies":{"@soulcraft/brainy-web-service":"latest"}}' > package.json
# Create wrangler.toml
cat > wrangler.toml << EOF
name = "brainy-web-service"
main = "src/worker.js"
compatibility_date = "2024-01-01"
[env.production]
name = "brainy-web-service"
EOF
# Deploy with Wrangler
npx wrangler deploy
Option 5: Serverless Deployment
// For serverless platforms, wrap the service:
const express = require('express');
const app = require('@soulcraft/brainy-web-service');
module.exports = app;
Configuration
Configure the service using environment variables:
# Server configuration
PORT=3000 # Server port (default: 3000)
HOST=0.0.0.0 # Server host (default: 0.0.0.0)
# Local Storage configuration (fallback)
BRAINY_DATA_PATH=/path/to/data # Path to Brainy database files (used when no cloud storage configured)
FORCE_LOCAL_STORAGE=true # Force local filesystem storage (ignores cloud storage config)
# Security configuration
CORS_ORIGIN=* # CORS origin (default: *)
RATE_LIMIT_WINDOW=900000 # Rate limit window in ms (default: 15 minutes)
RATE_LIMIT_MAX=100 # Max requests per window (default: 100)
# Environment
NODE_ENV=production # Environment mode
Cloud Storage Configuration
The service automatically detects and uses cloud storage when configured. If no cloud storage is configured, it falls back to local filesystem storage.
AWS S3
S3_BUCKET_NAME=my-brainy-bucket
S3_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE # or AWS_ACCESS_KEY_ID
S3_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY # or AWS_SECRET_ACCESS_KEY
S3_REGION=us-west-2 # or AWS_REGION
Cloudflare R2
R2_BUCKET_NAME=my-brainy-bucket
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-r2-access-key
R2_SECRET_ACCESS_KEY=your-r2-secret-key
Google Cloud Storage (S3-compatible)
GCS_BUCKET_NAME=my-brainy-bucket
GCS_ACCESS_KEY_ID=your-gcs-access-key
GCS_SECRET_ACCESS_KEY=your-gcs-secret-key
GCS_ENDPOINT=https://storage.googleapis.com # Optional, defaults to GCS endpoint
Azure Blob Storage (S3-compatible)
For Azure, you can use the S3-compatible interface with a custom endpoint:
S3_BUCKET_NAME=my-brainy-container
S3_ACCESS_KEY_ID=your-storage-account-name
S3_SECRET_ACCESS_KEY=your-storage-account-key
S3_REGION=auto
# Note: Azure Blob Storage S3 compatibility may require additional configuration
Custom S3-Compatible Storage
S3_BUCKET_NAME=my-brainy-bucket
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
S3_REGION=us-east-1
# Set custom endpoint via application configuration
API Endpoints
Health & Status
GET /health
Health check endpoint.
Response:
{
"status": "healthy",
"timestamp": "2025-07-22T09:33:00.000Z",
"service": "brainy-web-service",
"version": "0.12.0"
}
GET /api
API documentation and endpoint listing.
GET /api/status
Database status and statistics.
Response:
{
"size": 1000,
"readOnly": true,
"timestamp": "2025-07-22T09:33:00.000Z"
}
Search Operations
POST /api/search
Search using a vector.
Request Body:
{
"vector": [0.1, 0.2, 0.3, ...],
"k": 10,
"nounTypes": ["document", "image"],
"includeVerbs": false
}
Response:
{
"results": [
{
"id": "item-1",
"score": 0.95,
"vector": [0.1, 0.2, 0.3, ...],
"metadata": {
"title": "Example Document",
"type": "document"
}
}
],
"query": {
"vectorLength": 384,
"k": 10,
"nounTypes": ["document"],
"includeVerbs": false
},
"timestamp": "2025-07-22T09:33:00.000Z"
}
POST /api/search/text
Search using text query (automatically vectorized).
Request Body:
{
"query": "machine learning algorithms",
"k": 5,
"nounTypes": ["document"],
"includeVerbs": false
}
Response: Same format as vector search.
Data Retrieval
GET /api/item/:id
Get a specific item by ID.
Response:
{
"item": {
"id": "item-1",
"vector": [0.1, 0.2, 0.3, ...],
"metadata": {
"title": "Example Document",
"type": "document"
}
},
"timestamp": "2025-07-22T09:33:00.000Z"
}
GET /api/items?page=1&limit=20
Get all items with pagination.
Query Parameters:
page(optional): Page number (default: 1)limit(optional): Items per page (default: 20, max: 100)
Response:
{
"items": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 1000,
"totalPages": 50,
"hasNext": true,
"hasPrev": false
},
"timestamp": "2025-07-22T09:33:00.000Z"
}
POST /api/similar/:id
Find items similar to a given item.
Request Body:
{
"k": 10,
"includeVerbs": false
}
Response: Same format as search results.
Usage Examples
JavaScript/Node.js
const axios = require('axios');
const API_BASE = 'http://localhost:3000/api';
// Text search
async function searchText(query) {
const response = await axios.post(`${API_BASE}/search/text`, {
query: query,
k: 10
});
return response.data.results;
}
// Vector search
async function searchVector(vector) {
const response = await axios.post(`${API_BASE}/search`, {
vector: vector,
k: 5
});
return response.data.results;
}
// Get item by ID
async function getItem(id) {
const response = await axios.get(`${API_BASE}/item/${id}`);
return response.data.item;
}
// Usage
searchText('artificial intelligence').then(results => {
console.log('Search results:', results);
});
Python
import requests
API_BASE = 'http://localhost:3000/api'
def search_text(query, k=10):
response = requests.post(f'{API_BASE}/search/text', json={
'query': query,
'k': k
})
return response.json()['results']
def search_vector(vector, k=10):
response = requests.post(f'{API_BASE}/search', json={
'vector': vector,
'k': k
})
return response.json()['results']
def get_item(item_id):
response = requests.get(f'{API_BASE}/item/{item_id}')
return response.json()['item']
# Usage
results = search_text('machine learning')
print(f'Found {len(results)} results')
cURL
# Text search
curl -X POST http://localhost:3000/api/search/text \
-H "Content-Type: application/json" \
-d '{"query": "artificial intelligence", "k": 5}'
# Vector search
curl -X POST http://localhost:3000/api/search \
-H "Content-Type: application/json" \
-d '{"vector": [0.1, 0.2, 0.3], "k": 10}'
# Get item
curl http://localhost:3000/api/item/example-id
# Get items with pagination
curl "http://localhost:3000/api/items?page=1&limit=10"
Security Features
Read-Only Protection
- Database is automatically set to read-only mode on startup
- No write operations (add, delete, update) are exposed
- Only safe search and retrieval operations are available
Rate Limiting
- Default: 100 requests per 15-minute window per IP
- Configurable via environment variables
- Returns 429 status code when limit exceeded
Input Validation
- All inputs are validated using express-validator
- Vector dimensions and types are checked
- String lengths are limited to prevent abuse
- Numeric ranges are enforced
Security Headers
- Helmet.js provides security headers
- Content Security Policy configured
- CORS properly configured
- Compression enabled for performance
Error Handling
- Detailed error messages in development
- Generic error messages in production
- All errors are logged for monitoring
- Graceful shutdown on SIGTERM/SIGINT
Deployment
Docker
Create a Dockerfile:
FROM node:24-alpine
# Create non-root user for security
RUN addgroup -g 1001 -S brainy && \
adduser -S brainy -u 1001
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy application
COPY . .
RUN npm run build
# Create data directory and set permissions
RUN mkdir -p /app/data && chown -R brainy:brainy /app
# Switch to non-root user
USER brainy
# Expose port
EXPOSE 3000
# Set environment
ENV NODE_ENV=production
# Start service
CMD ["npm", "start"]
Local Storage Deployment
docker build -t brainy-web-service .
docker run -p 3000:3000 \
-v /host/data:/app/data \
-e BRAINY_DATA_PATH=/app/data \
brainy-web-service
AWS S3 Deployment
docker run -p 3000:3000 \
-e S3_BUCKET_NAME=my-brainy-bucket \
-e S3_ACCESS_KEY_ID=your-access-key \
-e S3_SECRET_ACCESS_KEY=your-secret-key \
-e S3_REGION=us-west-2 \
brainy-web-service
Cloudflare R2 Deployment
docker run -p 3000:3000 \
-e R2_BUCKET_NAME=my-brainy-bucket \
-e R2_ACCOUNT_ID=your-account-id \
-e R2_ACCESS_KEY_ID=your-r2-access-key \
-e R2_SECRET_ACCESS_KEY=your-r2-secret-key \
brainy-web-service
Google Cloud Storage Deployment
docker run -p 3000:3000 \
-e GCS_BUCKET_NAME=my-brainy-bucket \
-e GCS_ACCESS_KEY_ID=your-gcs-access-key \
-e GCS_SECRET_ACCESS_KEY=your-gcs-secret-key \
brainy-web-service
Docker Compose
version: '3.8'
services:
brainy-web-service:
build: .
ports:
- "3000:3000"
volumes:
- ./data:/app/data
environment:
- NODE_ENV=production
- BRAINY_DATA_PATH=/app/data
- RATE_LIMIT_MAX=200
restart: unless-stopped
Systemd Service
Create /etc/systemd/system/brainy-web-service.service:
[Unit]
Description=Brainy Web Service
After=network.target
[Service]
Type=simple
User=brainy
WorkingDirectory=/opt/brainy-web-service
ExecStart=/usr/bin/node dist/server.js
Restart=always
RestartSec=10
Environment=NODE_ENV=production
Environment=BRAINY_DATA_PATH=/opt/brainy-web-service/data
Environment=PORT=3000
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable brainy-web-service
sudo systemctl start brainy-web-service
Reverse Proxy (Nginx)
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
Development
Setup
git clone https://github.com/soulcraft-research/brainy.git
cd brainy/web-service-package
npm install
Development Mode
npm run dev
Building
npm run build
Testing
npm test
Monitoring
Health Checks
The service provides health check endpoints for monitoring:
GET /health- Basic health checkGET /api/status- Detailed database status
Logging
All requests and errors are logged to console. In production, consider using a logging service like Winston or Bunyan.
Metrics
Consider integrating with monitoring solutions:
- Prometheus metrics
- New Relic
- DataDog
- Custom metrics via the status endpoint
Troubleshooting
Common Issues
-
Service won't start
- Check if the data directory exists and is readable
- Verify Node.js version (requires >= 24.4.0)
- Check port availability
-
Database not found
- Ensure
BRAINY_DATA_PATHpoints to valid Brainy database files - Check file permissions
- Ensure
-
Rate limiting issues
- Adjust
RATE_LIMIT_MAXandRATE_LIMIT_WINDOW - Consider implementing IP whitelisting
- Adjust
-
Memory issues
- Monitor memory usage with large databases
- Consider implementing pagination for large result sets
Debug Mode
Enable debug logging:
NODE_ENV=development npm start
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License
MIT License - see the main Brainy project for details.
Support
- GitHub Issues: https://github.com/soulcraft-research/brainy/issues
- Documentation: https://github.com/soulcraft-research/brainy
- Email: david@soulcraft.com