buzzster 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client.js ADDED
@@ -0,0 +1,138 @@
1
+ /**
2
+ * BioFirewall Client - HTTP client for central API
3
+ */
4
+
5
+ const axios = require('axios');
6
+
7
+ class BioFirewallClient {
8
+ constructor(apiUrl, options = {}) {
9
+ this.apiUrl = apiUrl.replace(/\/$/, ''); // Remove trailing slash
10
+ this.timeout = options.timeout || 5000;
11
+ this.cacheTokens = options.cacheTokens !== false;
12
+ this.cacheTTL = options.cacheTTL || 30000; // 30 seconds
13
+
14
+ // Token cache
15
+ this.tokenCache = new Map();
16
+
17
+ // HTTP client
18
+ this.http = axios.create({
19
+ baseURL: this.apiUrl,
20
+ timeout: this.timeout,
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ 'User-Agent': 'BioFirewallClient/3.0'
24
+ }
25
+ });
26
+ }
27
+
28
+ /**
29
+ * Verify token with central API
30
+ * Caches result to reduce API calls
31
+ */
32
+ async verifyToken(agentId, token) {
33
+ const cacheKey = `${agentId}:${token}`;
34
+
35
+ // Check cache
36
+ if (this.cacheTokens && this.tokenCache.has(cacheKey)) {
37
+ const cached = this.tokenCache.get(cacheKey);
38
+ if (Date.now() - cached.timestamp < this.cacheTTL) {
39
+ return cached.data;
40
+ }
41
+ }
42
+
43
+ try {
44
+ // Call central API
45
+ const response = await this.http.post('/verify', {
46
+ agentId,
47
+ token
48
+ });
49
+
50
+ const result = response.data;
51
+
52
+ // Cache the result
53
+ if (this.cacheTokens) {
54
+ this.tokenCache.set(cacheKey, {
55
+ data: result,
56
+ timestamp: Date.now()
57
+ });
58
+ }
59
+
60
+ return result;
61
+
62
+ } catch (error) {
63
+ // Return error response
64
+ const errorResponse = error.response?.data || {
65
+ success: false,
66
+ valid: false,
67
+ error: 'API_ERROR',
68
+ message: error.message
69
+ };
70
+
71
+ return errorResponse;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Get agent info from central API
77
+ */
78
+ async getAgent(agentId) {
79
+ try {
80
+ const response = await this.http.get(`/agents/${agentId}`);
81
+ return response.data;
82
+ } catch (error) {
83
+ return {
84
+ success: false,
85
+ error: error.response?.data?.error || 'API_ERROR',
86
+ message: error.message
87
+ };
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Get global statistics
93
+ */
94
+ async getStats() {
95
+ try {
96
+ const response = await this.http.get('/agents/stats/global');
97
+ return response.data;
98
+ } catch (error) {
99
+ return {
100
+ success: false,
101
+ error: 'API_ERROR',
102
+ message: error.message
103
+ };
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Health check
109
+ */
110
+ async health() {
111
+ try {
112
+ const response = await this.http.get('/health');
113
+ return response.data;
114
+ } catch (error) {
115
+ return {
116
+ status: 'unhealthy',
117
+ error: error.message
118
+ };
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Clear token cache
124
+ */
125
+ clearCache() {
126
+ this.tokenCache.clear();
127
+ }
128
+
129
+ /**
130
+ * Clear specific token from cache
131
+ */
132
+ clearCacheEntry(agentId, token) {
133
+ const cacheKey = `${agentId}:${token}`;
134
+ this.tokenCache.delete(cacheKey);
135
+ }
136
+ }
137
+
138
+ module.exports = BioFirewallClient;
package/index.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * BioFirewall Client Module
3
+ * Express middleware for agent authentication
4
+ */
5
+
6
+ const createMiddleware = require('./middleware');
7
+ const BioFirewallClient = require('./client');
8
+
9
+ /**
10
+ * Main export: Express middleware factory
11
+ */
12
+ function BioFirewall(options) {
13
+ // If options is a string, treat it as apiUrl
14
+ if (typeof options === 'string') {
15
+ options = { apiUrl: options };
16
+ }
17
+
18
+ return createMiddleware(options);
19
+ }
20
+
21
+ // Export components
22
+ BioFirewall.createMiddleware = createMiddleware;
23
+ BioFirewall.Client = BioFirewallClient;
24
+
25
+ module.exports = BioFirewall;
package/middleware.js ADDED
@@ -0,0 +1,111 @@
1
+ /**
2
+ * BioFirewall Client Middleware
3
+ * Express middleware to protect routes with agent authentication
4
+ */
5
+
6
+ const BioFirewallClient = require('./client');
7
+ const rules = require('./rules');
8
+
9
+ /**
10
+ * Create BioFirewall middleware
11
+ */
12
+ function createMiddleware(options = {}) {
13
+ const {
14
+ apiUrl,
15
+ blockBrowsers = true,
16
+ enforceAuthentication = true,
17
+ cacheTokens = true,
18
+ cacheTTL = 30000
19
+ } = options;
20
+
21
+ if (!apiUrl) {
22
+ throw new Error('apiUrl is required');
23
+ }
24
+
25
+ // Create client
26
+ const client = new BioFirewallClient(apiUrl, {
27
+ cacheTokens,
28
+ cacheTTL
29
+ });
30
+
31
+ // Return middleware function
32
+ return async (req, res, next) => {
33
+ try {
34
+ // Layer 1: Passive filtering (User-Agent detection)
35
+ if (blockBrowsers && rules.isHuman(req)) {
36
+ return res.status(406).json({
37
+ success: false,
38
+ error: 'BIOLOGICAL_ENTITY_DETECTED',
39
+ message: 'This resource is reserved for automated agents',
40
+ tip: 'Use an API client. Ensure User-Agent does not look like a browser'
41
+ });
42
+ }
43
+
44
+ // Layer 2: Authentication
45
+ if (enforceAuthentication) {
46
+ const agentId = req.headers['x-bio-agent-id'];
47
+ const token = req.headers['x-bio-token'];
48
+
49
+ // Check headers present
50
+ if (!rules.hasValidAgentHeaders(req)) {
51
+ return res.status(428).json({
52
+ success: false,
53
+ error: 'AUTHENTICATION_REQUIRED',
54
+ message: 'Valid agent token required to access this resource',
55
+ protocol: {
56
+ version: '3.0',
57
+ method: 'JWT + RS256',
58
+ headers: {
59
+ 'X-Bio-Agent-Id': 'Your agent ID from registration',
60
+ 'X-Bio-Token': 'JWT token signed with your private key'
61
+ }
62
+ },
63
+ documentation: 'https://github.com/openclaw/biofirewall',
64
+ hint: 'Register your agent first at POST /register'
65
+ });
66
+ }
67
+
68
+ // Verify token with central API
69
+ const verification = await client.verifyToken(agentId, token);
70
+
71
+ if (!verification.valid) {
72
+ const statusCode = verification.error === 'AGENT_NOT_FOUND' ? 428 :
73
+ verification.error === 'AGENT_NOT_ACTIVE' ? 403 :
74
+ 401;
75
+
76
+ return res.status(statusCode).json({
77
+ success: false,
78
+ error: verification.error,
79
+ message: verification.message,
80
+ hint: verification.error === 'AGENT_NOT_FOUND'
81
+ ? 'Register at POST /register'
82
+ : 'Check your token and try again'
83
+ });
84
+ }
85
+
86
+ // Attach agent info to request
87
+ req.agent = verification.agent;
88
+
89
+ // Add response headers
90
+ res.set({
91
+ 'X-Bio-Verified': 'true',
92
+ 'X-Bio-Agent-Name': verification.agent.name,
93
+ 'X-Bio-Version': '3.0'
94
+ });
95
+ }
96
+
97
+ next();
98
+
99
+ } catch (error) {
100
+ console.error('BioFirewall middleware error:', error);
101
+
102
+ res.status(500).json({
103
+ success: false,
104
+ error: 'INTERNAL_ERROR',
105
+ message: 'Authentication system error'
106
+ });
107
+ }
108
+ };
109
+ }
110
+
111
+ module.exports = createMiddleware;
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "buzzster",
3
+ "version": "1.0.0",
4
+ "description": "Buzzster Client - Express middleware to protect routes with agent authentication",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "jest"
8
+ },
9
+ "keywords": [
10
+ "buzzster",
11
+ "client",
12
+ "middleware",
13
+ "express",
14
+ "authentication",
15
+ "agents"
16
+ ],
17
+ "author": "Comma",
18
+ "license": "MIT",
19
+ "dependencies": {
20
+ "axios": "^1.6.0",
21
+ "express": "^4.18.2"
22
+ },
23
+ "devDependencies": {
24
+ "jest": "^29.7.0",
25
+ "supertest": "^6.3.3"
26
+ },
27
+ "peerDependencies": {
28
+ "express": "^4.0.0"
29
+ }
30
+ }
package/rules.js ADDED
@@ -0,0 +1,100 @@
1
+ /**
2
+ * BioFirewall Client - Security Rules
3
+ * User-Agent validation (local, no API calls needed)
4
+ */
5
+
6
+ // Patterns that indicate a human browser
7
+ const BROWSER_PATTERNS = [
8
+ /mozilla.*firefox/i,
9
+ /mozilla.*safari.*chrome/i, // Chrome
10
+ /mozilla.*safari(?!.*linux)/i, // Safari (not Linux)
11
+ /mozilla.*edge/i, // Edge
12
+ /mozilla.*trident.*rv:11/i, // IE 11
13
+ /mozilla.*applewebkit/i, // WebKit-based
14
+ /opr\//i, // Opera
15
+ ];
16
+
17
+ // Patterns that indicate a legitimate bot/agent
18
+ const BOT_PATTERNS = [
19
+ /bot/i,
20
+ /agent/i,
21
+ /crawler/i,
22
+ /curl/i,
23
+ /wget/i,
24
+ /python/i,
25
+ /java(?!script)/i,
26
+ /axios/i,
27
+ /node/i,
28
+ /go-http-client/i,
29
+ ];
30
+
31
+ module.exports = {
32
+ /**
33
+ * Check if request appears to be from a human (browser)
34
+ */
35
+ isHuman: (req) => {
36
+ const userAgent = (req.get('User-Agent') || '').trim();
37
+ const accept = (req.get('Accept') || '').trim();
38
+ const acceptLanguage = req.get('Accept-Language');
39
+
40
+ // Rule 1: Accept header containing text/html = human
41
+ if (accept.includes('text/html')) {
42
+ return true;
43
+ }
44
+
45
+ // Rule 2: Accept-Language header = human trait
46
+ if (acceptLanguage) {
47
+ return true;
48
+ }
49
+
50
+ // Rule 3: No User-Agent = suspicious but check other traits
51
+ if (!userAgent) {
52
+ return !this._isBotUser(req);
53
+ }
54
+
55
+ // Rule 4: Check against browser patterns
56
+ const isBrowserLike = BROWSER_PATTERNS.some(pattern => pattern.test(userAgent));
57
+
58
+ if (isBrowserLike) {
59
+ // Could still be a bot pretending to be a browser
60
+ if (this._isBotUser(req)) {
61
+ return false;
62
+ }
63
+ return true;
64
+ }
65
+
66
+ // Rule 5: Check if it matches legitimate bot patterns
67
+ const isBot = BOT_PATTERNS.some(pattern => pattern.test(userAgent));
68
+
69
+ if (isBot) {
70
+ return false;
71
+ }
72
+
73
+ // Default: DENY (prefer blocking a bot over allowing a human)
74
+ return true;
75
+ },
76
+
77
+ /**
78
+ * Helper: Check if request has bot-like characteristics
79
+ */
80
+ _isBotUser: (req) => {
81
+ const userAgent = (req.get('User-Agent') || '').toLowerCase();
82
+ const accept = (req.get('Accept') || '').toLowerCase();
83
+
84
+ const asksForJson = accept.includes('application/json');
85
+ const asksForHtml = accept.includes('text/html');
86
+ const hasProperUA = BOT_PATTERNS.some(pattern => pattern.test(userAgent));
87
+
88
+ return (asksForJson || hasProperUA) && !asksForHtml;
89
+ },
90
+
91
+ /**
92
+ * Check if request has valid agent authentication headers
93
+ */
94
+ hasValidAgentHeaders: (req) => {
95
+ const token = req.headers['x-bio-token'];
96
+ const agentId = req.headers['x-bio-agent-id'];
97
+
98
+ return !!(token && agentId);
99
+ }
100
+ };
package/setup.sh ADDED
@@ -0,0 +1,50 @@
1
+ #!/bin/bash
2
+
3
+ # BioFirewall Client Setup Script
4
+
5
+ echo "🔒 BioFirewall Client - Setup"
6
+ echo "======================================"
7
+
8
+ # Check Node.js
9
+ if ! command -v node &> /dev/null; then
10
+ echo "❌ Node.js is not installed"
11
+ exit 1
12
+ fi
13
+
14
+ echo "✅ Node.js $(node --version)"
15
+
16
+ # Check if already in a project with express
17
+ if ! grep -q "\"express\"" package.json 2>/dev/null; then
18
+ echo "⚠️ This is a module. Use in your Express project:"
19
+ echo " npm install biofirewall-client"
20
+ exit 0
21
+ fi
22
+
23
+ # Install biofirewall-client
24
+ echo ""
25
+ echo "📦 Installing biofirewall-client..."
26
+ npm install biofirewall-client
27
+
28
+ # Create .env if doesn't exist
29
+ if [ ! -f .env ]; then
30
+ echo ""
31
+ echo "📝 Creating .env file..."
32
+ cp .env.example .env
33
+ echo " Please update .env with your configuration"
34
+ fi
35
+
36
+ # Display next steps
37
+ echo ""
38
+ echo "======================================"
39
+ echo "✅ Setup complete!"
40
+ echo ""
41
+ echo "Next steps:"
42
+ echo "1. Update .env with your configuration"
43
+ echo "2. Add middleware to your Express app:"
44
+ echo ""
45
+ echo " const BioFirewall = require('biofirewall-client');"
46
+ echo " const bio = new BioFirewall('http://localhost:3333');"
47
+ echo " app.use(bio);"
48
+ echo ""
49
+ echo "3. Start your API and test!"
50
+ echo ""