-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsecureexec_server.py
More file actions
117 lines (100 loc) · 4.03 KB
/
secureexec_server.py
File metadata and controls
117 lines (100 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env python3
"""
SecureExecAPI Flask server.
Full commercial API: x402 + MPP payment gate.
Internal agents (9 Achilles sub-agents) bypass 402 for seeding.
External agents always pay.
"""
import os
from flask import Flask, request, jsonify
from secureexec_engine import (
exec_tool, list_tools, generate_proof_hash, is_internal_agent
)
import time
from datetime import datetime, timezone
app = Flask(__name__)
PORT = int(os.getenv('PORT', 5091))
PAYMENT_WALLET = os.getenv('PAYMENT_WALLET', '')
def check_payment(req):
"""
Layer 4: x402/MPP payment gate.
Returns (authorized, payment_protocol, error_response)
"""
agent_id = (req.json or {}).get('agentId') or \
(req.json or {}).get('agent_id') or \
req.headers.get('x-agent-id', '')
# Internal agents bypass payment gate
if is_internal_agent(agent_id):
return True, 'internal', None
auth = req.headers.get('Authorization', '')
if not auth:
return False, None, {
'type': 'https://paymentauth.org/problems/payment-required',
'title': 'Payment Required',
'status': 402,
'amount': '0.01',
'currency': 'USDC',
'network': 'base',
'payTo': PAYMENT_WALLET,
'instructions': 'Pay 0.01 USDC on Base network then retry with payment credential in Authorization header',
'erc7710': 'Pre-approve spend limit via ERC-7710 scoped delegation for high-frequency calls',
'acp': 'https://app.virtuals.io/acp',
'schemaVersion': 'v1',
'timestamp': datetime.now(timezone.utc).isoformat()
}
protocol = 'mpp' if auth.startswith('MPP') else 'x402'
return True, protocol, None
@app.route('/health', methods=['GET'])
def health():
return jsonify({'status': 'ok', 'service': 'secureexec', 'version': 'v1'})
@app.route('/exec/tool', methods=['POST'])
def handle_exec():
try:
body = request.get_json(force=True) or {}
agent_id = (body.get('agentId') or body.get('agent_id') or
request.headers.get('x-agent-id', 'unknown'))
tool = body.get('tool')
if not tool or not tool.get('name'):
return jsonify({
'error': 'tool.name is required',
'schemaVersion': 'v1',
'timestamp': datetime.now(timezone.utc).isoformat()
}), 400
# Payment gate
authorized, payment_protocol, payment_error = check_payment(request)
if not authorized:
return jsonify(payment_error), 402
result = exec_tool(
agent_id=agent_id,
tool=tool,
dry_run=body.get('dryRun', True),
context=body.get('context', {}),
payment_protocol=payment_protocol
)
return jsonify(result), 200
except Exception as e:
proof_hash = generate_proof_hash({'error': str(e), 'ts': time.time()})
return jsonify({
'status': 'error', 'fallback': True,
'proofHash': proof_hash, 'schemaVersion': 'v1'
}), 200
@app.route('/exec/simulate', methods=['POST'])
def handle_simulate():
"""Always dry-run — no payment required for simulation."""
try:
body = request.get_json(force=True) or {}
agent_id = (body.get('agentId') or body.get('agent_id') or
request.headers.get('x-agent-id', 'unknown'))
tool = body.get('tool')
if not tool or not tool.get('name'):
return jsonify({'error': 'tool.name is required', 'schemaVersion': 'v1'}), 400
result = exec_tool(agent_id=agent_id, tool=tool, dry_run=True,
context=body.get('context', {}), payment_protocol='none')
return jsonify(result), 200
except Exception as e:
return jsonify({'status': 'error', 'fallback': True, 'schemaVersion': 'v1'}), 200
@app.route('/exec/tools', methods=['GET'])
def handle_list_tools():
return jsonify(list_tools()), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=PORT, debug=False)