@agenticmail/enterprise 0.5.20 ā 0.5.22
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/dist/chunk-67KZYSLU.js +247 -0
- package/dist/chunk-P2ZBZVVD.js +898 -0
- package/dist/chunk-T3FMNQXM.js +12666 -0
- package/dist/chunk-VDAIXIUZ.js +1977 -0
- package/dist/cli.js +1 -1
- package/dist/dashboard/pages/settings.js +16 -7
- package/dist/index.js +35 -35
- package/dist/providers-DZDNNJTY.js +17 -0
- package/dist/runtime-6CYKDDPC.js +47 -0
- package/dist/server-C4OZWQML.js +11 -0
- package/dist/setup-IUABEVON.js +20 -0
- package/package.json +1 -1
- package/seed-data.mjs +455 -0
- package/src/admin/routes.ts +4 -3
- package/src/dashboard/pages/settings.js +16 -7
- package/src/server.ts +3 -11
package/seed-data.mjs
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgenticMail Enterprise ā Comprehensive Seed Data
|
|
4
|
+
* Populates knowledge bases, policies, guardrails, DLP rules, and onboarding
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import pg from 'pg';
|
|
8
|
+
const { Pool } = pg;
|
|
9
|
+
|
|
10
|
+
const DATABASE_URL = 'postgresql://postgres.ziurzgoffaexxgjmfjph:MK6PHWIpjDO0cPwU@aws-1-us-east-2.pooler.supabase.com:5432/postgres';
|
|
11
|
+
const ORG_ID = 'default';
|
|
12
|
+
|
|
13
|
+
const pool = new Pool({ connectionString: DATABASE_URL, ssl: { rejectUnauthorized: false }, max: 3 });
|
|
14
|
+
|
|
15
|
+
function uid() { return crypto.randomUUID(); }
|
|
16
|
+
const now = new Date().toISOString();
|
|
17
|
+
|
|
18
|
+
async function run(sql, params = []) {
|
|
19
|
+
const client = await pool.connect();
|
|
20
|
+
try { await client.query(sql, params); }
|
|
21
|
+
finally { client.release(); }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function seed() {
|
|
25
|
+
console.log('š± Seeding AgenticMail Enterprise database...\n');
|
|
26
|
+
|
|
27
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
28
|
+
// 1. KNOWLEDGE BASES + DOCUMENTS + CHUNKS
|
|
29
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
30
|
+
console.log('š Creating knowledge bases...');
|
|
31
|
+
|
|
32
|
+
const kbData = [
|
|
33
|
+
{
|
|
34
|
+
id: uid(), name: 'AgenticMail Platform Guide',
|
|
35
|
+
description: 'Comprehensive guide to the AgenticMail platform ā architecture, features, API, configuration, deployment, and best practices for enterprise AI agent email infrastructure.',
|
|
36
|
+
documents: [
|
|
37
|
+
{
|
|
38
|
+
name: 'Platform Overview',
|
|
39
|
+
chunks: [
|
|
40
|
+
'AgenticMail is an enterprise-grade AI agent identity and email infrastructure platform. It provides each AI agent with its own email address, enabling agents to send, receive, and manage emails autonomously. The platform supports multi-tenant organizations with role-based access control, audit logging, and compliance features.',
|
|
41
|
+
'Core components include: (1) Agent Identity ā unique email addresses per agent with DKIM/SPF/DMARC authentication; (2) Email Engine ā full IMAP/SMTP stack with spam filtering and DLP; (3) Agent Runtime ā managed execution environment for AI agents; (4) Dashboard ā admin UI for monitoring, configuration, and management; (5) MCP Integration ā Model Context Protocol adapters for 20+ enterprise tools.',
|
|
42
|
+
'AgenticMail supports multiple database backends: PostgreSQL (recommended for production), SQLite (development), MySQL, Turso, MongoDB, and DynamoDB. The system uses a layered architecture with a core package (@agenticmail/core), API layer (@agenticmail/api), MCP server (@agenticmail/mcp), OpenClaw integration (@agenticmail/openclaw), and enterprise features (@agenticmail/enterprise).',
|
|
43
|
+
'Deployment options include Docker, Fly.io, AWS (ECS/Lambda), Google Cloud Run, Railway, Render, and bare metal. The setup wizard guides administrators through database configuration, domain setup, SSL certificates, and initial agent provisioning. All data stays on your infrastructure ā no phone-home after initial domain registration.',
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Agent Configuration Guide',
|
|
48
|
+
chunks: [
|
|
49
|
+
'Each managed agent has a lifecycle: provisioning ā active ā paused ā decommissioned. Agents are configured with a SOUL.md (personality and behavior rules), system prompt, allowed tools, rate limits, and budget constraints. The agent runtime executes agent tasks using configured LLM providers (Anthropic, OpenAI, Google, or self-hosted models).',
|
|
50
|
+
'Agent email addresses follow the format agent@yourdomain.com (custom domain mode) or yourname+agent@gmail.com (relay mode). Each agent has its own inbox, sent folder, drafts, and can be configured with auto-reply rules, email signatures, and forwarding policies.',
|
|
51
|
+
'Tool security is managed through permission profiles. Each profile defines which tools an agent can use, with granular controls: allow, deny, or require-approval. Tools can be grouped by category (communication, file-system, web, database, etc.) with per-tool parameter restrictions.',
|
|
52
|
+
'Budget management allows setting per-agent spending limits with alerts at configurable thresholds (e.g., 50%, 80%, 100%). When a budget is exhausted, the agent is automatically paused. Administrators receive notifications via the configured alert channels (email, Slack, webhook).',
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'API Reference',
|
|
57
|
+
chunks: [
|
|
58
|
+
'The AgenticMail API uses REST with JSON payloads. Authentication supports JWT tokens (for dashboard users), API keys (for programmatic access), and SSO/OIDC (for enterprise identity providers). All requests include X-Request-Id headers for tracing.',
|
|
59
|
+
'Core API endpoints: POST /api/agents (create agent), GET /api/agents (list agents), PATCH /api/agents/:id (update), DELETE /api/agents/:id (decommission). Agent email: GET /api/agents/:id/inbox, POST /api/agents/:id/send, GET /api/agents/:id/messages/:msgId.',
|
|
60
|
+
'Engine API endpoints (under /api/engine/): /knowledge-bases (RAG knowledge management), /policies (governance policies), /guardrails (runtime safety rules), /dlp (data loss prevention), /compliance (audit reports), /vault (secrets management), /approvals (human-in-the-loop workflows).',
|
|
61
|
+
'Webhook integrations: POST /api/webhooks/configure to set up event notifications. Supported events: agent.created, agent.paused, agent.error, email.received, email.sent, budget.alert, dlp.violation, approval.requested, compliance.report.generated.',
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'Security & Compliance',
|
|
66
|
+
chunks: [
|
|
67
|
+
'AgenticMail implements defense-in-depth security: (1) Network layer ā IP allowlisting, rate limiting, WAF integration; (2) Authentication ā JWT with refresh tokens, API key rotation, SSO/OIDC; (3) Authorization ā RBAC with owner/admin/member/viewer roles; (4) Data ā AES-256-GCM encryption at rest for vault secrets, TLS 1.3 in transit.',
|
|
68
|
+
'Data Loss Prevention (DLP) scans all outbound agent communications for: PII (emails, SSNs, credit cards, phone numbers), credentials (API keys, passwords, tokens), and custom patterns (regex or keyword-based). Violations can trigger block, alert, or quarantine actions with configurable severity levels.',
|
|
69
|
+
'Compliance features include: SOC 2 Type II audit trail generation, GDPR data subject access requests, HIPAA-compatible audit logging, and custom compliance report templates. All agent actions are logged in the action journal with actor, action, resource, timestamp, and full request/response metadata.',
|
|
70
|
+
'The vault stores secrets using AES-256-GCM with PBKDF2 key derivation (600,000 iterations, SHA-512). Each entry has its own random salt and IV. Master key is derived from the AGENTICMAIL_VAULT_KEY environment variable. Secrets can be rotated individually or in bulk with zero-downtime key rotation.',
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'Deployment Best Practices',
|
|
75
|
+
chunks: [
|
|
76
|
+
'Production deployment checklist: (1) Use PostgreSQL with connection pooling (PgBouncer or Supabase pooler); (2) Set DATABASE_URL and JWT_SECRET as environment variables, never in config files; (3) Enable HTTPS with valid certificates; (4) Configure CORS to restrict allowed origins; (5) Set up health check monitoring at /health endpoint.',
|
|
77
|
+
'Scaling recommendations: AgenticMail is stateless ā scale horizontally by adding more instances behind a load balancer. Database connections should use pooling with max 5-10 connections per instance. For high-throughput email, consider dedicated SMTP relay (Amazon SES, SendGrid, or Mailgun).',
|
|
78
|
+
'Monitoring: The /health endpoint returns { status: "ok", uptime, version }. Key metrics to monitor: API response times (p99 < 500ms), database connection pool utilization (< 80%), email delivery rate (> 99%), agent task success rate, and DLP violation frequency.',
|
|
79
|
+
'Backup strategy: Database backups should run daily with point-in-time recovery enabled. Vault secrets are encrypted at rest but should also be backed up. Domain registration deployment keys should be stored in a separate password manager ā they cannot be recovered if lost.',
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: uid(), name: 'Enterprise Security Policies',
|
|
86
|
+
description: 'Security policies, compliance frameworks, and governance guidelines for enterprise AI agent deployments.',
|
|
87
|
+
documents: [
|
|
88
|
+
{
|
|
89
|
+
name: 'Acceptable Use Policy',
|
|
90
|
+
chunks: [
|
|
91
|
+
'AI agents deployed through AgenticMail must comply with the organization\'s acceptable use policy. Agents are prohibited from: (1) Sending unsolicited bulk email (spam); (2) Impersonating humans without disclosure; (3) Accessing systems beyond their authorized scope; (4) Storing or transmitting classified data without encryption.',
|
|
92
|
+
'Agent communication guidelines: All external emails must include a clear identifier that the message was generated by an AI agent. Internal communications may omit this if the organization has a blanket AI disclosure policy. Agents must not use deceptive subject lines or social engineering tactics.',
|
|
93
|
+
'Data handling requirements: Agents must classify data they process as Public, Internal, Confidential, or Restricted. Confidential and Restricted data must never be included in outbound emails without explicit approval. PII must be minimized ā agents should reference record IDs rather than including full personal data.',
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'Incident Response Procedures',
|
|
98
|
+
chunks: [
|
|
99
|
+
'Security incident classification: P1 (Critical) ā data breach, unauthorized access, agent compromise; P2 (High) ā DLP violation, credential exposure, service outage; P3 (Medium) ā policy violation, anomalous behavior, failed authentication spike; P4 (Low) ā configuration drift, minor policy deviation.',
|
|
100
|
+
'Response workflow: (1) Detection ā automated via guardrails, DLP, or anomaly detection; (2) Triage ā severity classification and impact assessment; (3) Containment ā pause affected agents, revoke compromised credentials; (4) Investigation ā review action journal, analyze email logs; (5) Remediation ā patch vulnerability, update policies; (6) Post-mortem ā document findings, update playbooks.',
|
|
101
|
+
'Escalation matrix: P1 ā immediate notification to Security Lead + CTO, agent killed within 5 minutes; P2 ā Security Lead notified within 15 minutes, agent paused; P3 ā reviewed in next business day standup; P4 ā tracked in weekly security review.',
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: uid(), name: 'Agent Development Handbook',
|
|
108
|
+
description: 'Best practices for developing, testing, and deploying AI agents on the AgenticMail platform.',
|
|
109
|
+
documents: [
|
|
110
|
+
{
|
|
111
|
+
name: 'Agent Design Patterns',
|
|
112
|
+
chunks: [
|
|
113
|
+
'The Specialist pattern: Create focused agents with narrow responsibilities. Example: an "Invoice Agent" that only processes invoices, a "Customer Support Agent" for support tickets, a "Research Agent" for web research. Each specialist has a minimal tool set and clear boundaries.',
|
|
114
|
+
'The Coordinator pattern: A supervisor agent delegates tasks to specialist agents via email. The coordinator receives requests, determines which specialist should handle them, and routes accordingly. This enables complex workflows while keeping individual agents simple and auditable.',
|
|
115
|
+
'The Pipeline pattern: Chain agents in sequence where each agent\'s output becomes the next agent\'s input. Example: Data Collection Agent ā Analysis Agent ā Report Agent ā Distribution Agent. Use email threads to maintain context through the pipeline.',
|
|
116
|
+
'The Guardian pattern: Pair each operational agent with a review agent. The operational agent drafts outputs (emails, reports, decisions) and the guardian reviews them before they\'re sent. Implement via the approval workflow system for high-stakes operations.',
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'Testing & Quality Assurance',
|
|
121
|
+
chunks: [
|
|
122
|
+
'Agent testing framework: (1) Unit tests ā validate individual tool calls and response formatting; (2) Integration tests ā verify email send/receive, database operations, API interactions; (3) Scenario tests ā simulate realistic multi-turn conversations and workflows; (4) Adversarial tests ā attempt prompt injection, boundary violation, data exfiltration.',
|
|
123
|
+
'Staging environment: Always deploy agents to staging before production. Use a separate database and email domain (e.g., staging.agenticmail.io). Run the full test suite including DLP checks, guardrail triggers, and budget limit enforcement.',
|
|
124
|
+
'Monitoring in production: Track key metrics per agent: task completion rate, average response time, error rate, email bounce rate, DLP violations, budget consumption. Set up alerts for anomalies ā a sudden spike in email volume or tool calls may indicate agent malfunction or compromise.',
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
for (const kb of kbData) {
|
|
132
|
+
await run(
|
|
133
|
+
`INSERT INTO knowledge_bases (id, org_id, name, description, agent_ids, config, stats, created_at, updated_at)
|
|
134
|
+
VALUES ($1, $2, $3, $4, '[]', '{}', $5, $6, $6)
|
|
135
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
136
|
+
[kb.id, ORG_ID, kb.name, kb.description, JSON.stringify({ documents: kb.documents.length, chunks: kb.documents.reduce((a, d) => a + d.chunks.length, 0) }), now]
|
|
137
|
+
);
|
|
138
|
+
for (const doc of kb.documents) {
|
|
139
|
+
const docId = uid();
|
|
140
|
+
await run(
|
|
141
|
+
`INSERT INTO kb_documents (id, knowledge_base_id, name, source_type, mime_type, size, metadata, status, created_at, updated_at)
|
|
142
|
+
VALUES ($1, $2, $3, 'manual', 'text/plain', $4, '{}', 'ready', $5, $5)
|
|
143
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
144
|
+
[docId, kb.id, doc.name, doc.chunks.join('').length, now]
|
|
145
|
+
);
|
|
146
|
+
for (let i = 0; i < doc.chunks.length; i++) {
|
|
147
|
+
await run(
|
|
148
|
+
`INSERT INTO kb_chunks (id, document_id, content, token_count, position, metadata)
|
|
149
|
+
VALUES ($1, $2, $3, $4, $5, '{}')
|
|
150
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
151
|
+
[uid(), docId, doc.chunks[i], Math.ceil(doc.chunks[i].length / 4), i]
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
console.log(` ā
${kb.name} (${kb.documents.length} docs)`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
159
|
+
// 2. APPROVAL POLICIES
|
|
160
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
161
|
+
console.log('\nš Creating approval policies...');
|
|
162
|
+
|
|
163
|
+
const policies = [
|
|
164
|
+
{
|
|
165
|
+
name: 'External Email Approval',
|
|
166
|
+
description: 'Require human approval before agents send emails to external recipients (outside organization domain).',
|
|
167
|
+
triggers: { events: ['email.send'], conditions: { recipientType: 'external' } },
|
|
168
|
+
approvers: { roles: ['admin', 'owner'], minApprovals: 1, timeout: '4h' },
|
|
169
|
+
timeout: { action: 'deny', notifyOnTimeout: true },
|
|
170
|
+
notify: { channels: ['email', 'dashboard'], onRequest: true, onDecision: true },
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: 'High-Value Transaction Approval',
|
|
174
|
+
description: 'Require dual approval for any agent action involving financial transactions over $1,000.',
|
|
175
|
+
triggers: { events: ['tool.call'], conditions: { toolCategory: 'finance', amountThreshold: 1000 } },
|
|
176
|
+
approvers: { roles: ['owner'], minApprovals: 2, timeout: '2h' },
|
|
177
|
+
timeout: { action: 'deny', notifyOnTimeout: true },
|
|
178
|
+
notify: { channels: ['email', 'slack'], onRequest: true, onDecision: true, urgency: 'high' },
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'Database Write Approval',
|
|
182
|
+
description: 'Require approval for any destructive database operations (DELETE, DROP, TRUNCATE) performed by agents.',
|
|
183
|
+
triggers: { events: ['tool.call'], conditions: { toolName: 'database', operation: ['delete', 'drop', 'truncate', 'alter'] } },
|
|
184
|
+
approvers: { roles: ['admin', 'owner'], minApprovals: 1, timeout: '1h' },
|
|
185
|
+
timeout: { action: 'deny', notifyOnTimeout: true },
|
|
186
|
+
notify: { channels: ['email'], onRequest: true, onDecision: true },
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'New Tool Access Request',
|
|
190
|
+
description: 'When an agent requests access to a tool not in its permission profile, route to admin for approval.',
|
|
191
|
+
triggers: { events: ['tool.access_denied'], conditions: {} },
|
|
192
|
+
approvers: { roles: ['admin'], minApprovals: 1, timeout: '24h' },
|
|
193
|
+
timeout: { action: 'deny', notifyOnTimeout: false },
|
|
194
|
+
notify: { channels: ['dashboard'], onRequest: true, onDecision: true },
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'Bulk Email Campaign Approval',
|
|
198
|
+
description: 'Require approval before any agent sends more than 10 emails in a 1-hour window to prevent spam.',
|
|
199
|
+
triggers: { events: ['rate_limit.approaching'], conditions: { metric: 'emails_sent', threshold: 10, window: '1h' } },
|
|
200
|
+
approvers: { roles: ['admin', 'owner'], minApprovals: 1, timeout: '30m' },
|
|
201
|
+
timeout: { action: 'block', notifyOnTimeout: true },
|
|
202
|
+
notify: { channels: ['email', 'dashboard'], onRequest: true, onDecision: true },
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: 'Agent Deployment Approval',
|
|
206
|
+
description: 'Require owner approval before deploying new agents or promoting agents from staging to production.',
|
|
207
|
+
triggers: { events: ['agent.deploy', 'agent.promote'], conditions: { environment: 'production' } },
|
|
208
|
+
approvers: { roles: ['owner'], minApprovals: 1, timeout: '8h' },
|
|
209
|
+
timeout: { action: 'deny', notifyOnTimeout: true },
|
|
210
|
+
notify: { channels: ['email', 'slack'], onRequest: true, onDecision: true },
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: 'Sensitive Data Access',
|
|
214
|
+
description: 'Require approval when agents attempt to access documents classified as Confidential or Restricted.',
|
|
215
|
+
triggers: { events: ['document.access'], conditions: { classification: ['confidential', 'restricted'] } },
|
|
216
|
+
approvers: { roles: ['admin', 'owner'], minApprovals: 1, timeout: '2h' },
|
|
217
|
+
timeout: { action: 'deny', notifyOnTimeout: true },
|
|
218
|
+
notify: { channels: ['email'], onRequest: true, onDecision: true },
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
name: 'Budget Override Request',
|
|
222
|
+
description: 'When an agent exceeds its allocated budget, allow requesting a temporary override with manager approval.',
|
|
223
|
+
triggers: { events: ['budget.exceeded'], conditions: {} },
|
|
224
|
+
approvers: { roles: ['owner'], minApprovals: 1, timeout: '4h' },
|
|
225
|
+
timeout: { action: 'deny', notifyOnTimeout: true },
|
|
226
|
+
notify: { channels: ['email', 'dashboard'], onRequest: true, onDecision: true },
|
|
227
|
+
},
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
for (const p of policies) {
|
|
231
|
+
await run(
|
|
232
|
+
`INSERT INTO approval_policies (id, org_id, name, description, triggers, approvers, timeout, notify, enabled, created_at, updated_at)
|
|
233
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8,true, $9, $9)
|
|
234
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
235
|
+
[uid(), ORG_ID, p.name, p.description, JSON.stringify(p.triggers), JSON.stringify(p.approvers), JSON.stringify(p.timeout), JSON.stringify(p.notify), now]
|
|
236
|
+
);
|
|
237
|
+
console.log(` ā
${p.name}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
241
|
+
// 3. DLP RULES
|
|
242
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
243
|
+
console.log('\nš”ļø Creating DLP rules...');
|
|
244
|
+
|
|
245
|
+
const dlpRules = [
|
|
246
|
+
{ name: 'Credit Card Numbers', description: 'Detect and block credit card numbers (Visa, MC, Amex, Discover) in outbound communications.', pattern_type: 'regex', pattern: '\\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})\\b', action: 'block', severity: 'critical' },
|
|
247
|
+
{ name: 'Social Security Numbers', description: 'Detect and block US Social Security Numbers in any format.', pattern_type: 'regex', pattern: '\\b(?:\\d{3}[-\\s]?\\d{2}[-\\s]?\\d{4})\\b', action: 'block', severity: 'critical' },
|
|
248
|
+
{ name: 'API Keys & Tokens', description: 'Detect API keys, bearer tokens, and secret keys in outbound messages.', pattern_type: 'regex', pattern: '(?:sk-[a-zA-Z0-9]{32,}|ghp_[a-zA-Z0-9]{36}|glpat-[a-zA-Z0-9\\-]{20,}|xox[bps]-[a-zA-Z0-9\\-]+|Bearer\\s+[a-zA-Z0-9\\-._~+/]+=*)', action: 'block', severity: 'critical' },
|
|
249
|
+
{ name: 'AWS Credentials', description: 'Detect AWS access keys, secret keys, and session tokens.', pattern_type: 'regex', pattern: '(?:AKIA[0-9A-Z]{16}|(?:aws_secret_access_key|aws_access_key_id)\\s*[=:]\\s*[A-Za-z0-9/+=]{20,})', action: 'block', severity: 'critical' },
|
|
250
|
+
{ name: 'Private Keys', description: 'Detect PEM-encoded private keys (RSA, EC, DSA).', pattern_type: 'regex', pattern: '-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----', action: 'block', severity: 'critical' },
|
|
251
|
+
{ name: 'Email Addresses (Bulk)', description: 'Alert when outbound message contains more than 5 email addresses ā potential data harvesting.', pattern_type: 'pii_type', pattern: 'email_bulk', action: 'alert', severity: 'high' },
|
|
252
|
+
{ name: 'Phone Numbers', description: 'Detect and alert on phone numbers in outbound communications.', pattern_type: 'regex', pattern: '\\b(?:\\+?1?[-.]?\\(?\\d{3}\\)?[-.]?\\d{3}[-.]?\\d{4})\\b', action: 'alert', severity: 'medium' },
|
|
253
|
+
{ name: 'Internal URLs', description: 'Block exposure of internal service URLs, localhost references, or private IP addresses.', pattern_type: 'regex', pattern: '(?:https?://(?:localhost|127\\.0\\.0\\.1|10\\.\\d+\\.\\d+\\.\\d+|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d+\\.\\d+|192\\.168\\.\\d+\\.\\d+)(?::\\d+)?)', action: 'block', severity: 'high' },
|
|
254
|
+
{ name: 'Database Connection Strings', description: 'Detect and block database connection strings containing credentials.', pattern_type: 'regex', pattern: '(?:(?:postgres|mysql|mongodb|redis)(?:ql)?://[^\\s]+(?::[^\\s@]+)?@[^\\s]+)', action: 'block', severity: 'critical' },
|
|
255
|
+
{ name: 'Passport Numbers', description: 'Detect potential passport number patterns.', pattern_type: 'regex', pattern: '\\b[A-Z]{1,2}\\d{6,9}\\b', action: 'alert', severity: 'medium' },
|
|
256
|
+
{ name: 'Medical Record Numbers', description: 'Detect potential MRN patterns for HIPAA compliance.', pattern_type: 'regex', pattern: '\\b(?:MRN|Medical Record)\\s*[:#]?\\s*\\d{6,10}\\b', action: 'block', severity: 'high' },
|
|
257
|
+
{ name: 'Confidential Markings', description: 'Detect documents marked as confidential, secret, or top secret being shared externally.', pattern_type: 'keyword', pattern: 'CONFIDENTIAL,TOP SECRET,CLASSIFIED,RESTRICTED,INTERNAL ONLY,DO NOT DISTRIBUTE', action: 'alert', severity: 'high' },
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
for (const r of dlpRules) {
|
|
261
|
+
await run(
|
|
262
|
+
`INSERT INTO dlp_rules (id, org_id, name, description, pattern_type, pattern, action, applies_to, severity, enabled, created_at, updated_at)
|
|
263
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, 'outbound', $8,true, $9, $9)
|
|
264
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
265
|
+
[uid(), ORG_ID, r.name, r.description, r.pattern_type, r.pattern, r.action, r.severity, now]
|
|
266
|
+
);
|
|
267
|
+
console.log(` ā
${r.name}`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
271
|
+
// 4. GUARDRAIL RULES
|
|
272
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
273
|
+
console.log('\nš§ Creating guardrail rules...');
|
|
274
|
+
|
|
275
|
+
const guardrails = [
|
|
276
|
+
{ name: 'Excessive Email Volume', description: 'Alert when an agent sends more than 50 emails per hour.', category: 'rate_limit', rule_type: 'threshold', conditions: { metric: 'emails_sent', threshold: 50, window: '1h' }, action: 'alert', severity: 'high', cooldown: 60 },
|
|
277
|
+
{ name: 'Unusual Working Hours', description: 'Alert when agent activity occurs outside business hours (configurable per timezone).', category: 'behavioral', rule_type: 'time_window', conditions: { outsideHours: { start: '22:00', end: '06:00' }, timezone: 'UTC' }, action: 'alert', severity: 'low', cooldown: 480 },
|
|
278
|
+
{ name: 'High Error Rate', description: 'Pause agent if error rate exceeds 30% over 10 consecutive tasks.', category: 'performance', rule_type: 'threshold', conditions: { metric: 'error_rate', threshold: 0.3, sampleSize: 10 }, action: 'pause', severity: 'high', cooldown: 30 },
|
|
279
|
+
{ name: 'Budget 80% Warning', description: 'Alert when agent reaches 80% of allocated monthly budget.', category: 'budget', rule_type: 'threshold', conditions: { metric: 'budget_utilization', threshold: 0.8 }, action: 'alert', severity: 'medium', cooldown: 1440 },
|
|
280
|
+
{ name: 'Budget Exhausted', description: 'Automatically pause agent when monthly budget is fully consumed.', category: 'budget', rule_type: 'threshold', conditions: { metric: 'budget_utilization', threshold: 1.0 }, action: 'pause', severity: 'critical', cooldown: 0 },
|
|
281
|
+
{ name: 'Large Attachment Detection', description: 'Alert when agent attempts to send email with attachments over 10MB.', category: 'data_protection', rule_type: 'threshold', conditions: { metric: 'attachment_size_mb', threshold: 10 }, action: 'alert', severity: 'medium', cooldown: 5 },
|
|
282
|
+
{ name: 'Repeated Tool Failures', description: 'Alert when same tool fails 5+ times in succession ā possible misconfiguration.', category: 'performance', rule_type: 'pattern', conditions: { metric: 'consecutive_tool_failures', threshold: 5, sameToolOnly: true }, action: 'alert', severity: 'high', cooldown: 15 },
|
|
283
|
+
{ name: 'Memory Usage Spike', description: 'Alert when agent context/memory grows beyond configured limits.', category: 'performance', rule_type: 'threshold', conditions: { metric: 'memory_tokens', threshold: 100000 }, action: 'alert', severity: 'medium', cooldown: 60 },
|
|
284
|
+
{ name: 'Privilege Escalation Attempt', description: 'Kill agent immediately if it attempts to access tools or resources outside its permission profile.', category: 'security', rule_type: 'pattern', conditions: { event: 'permission_denied', consecutiveAttempts: 3 }, action: 'kill', severity: 'critical', cooldown: 0 },
|
|
285
|
+
{ name: 'Self-Modification Detection', description: 'Alert if agent attempts to modify its own configuration, SOUL.md, or permission profile.', category: 'security', rule_type: 'pattern', conditions: { event: 'config_write_attempt', targetSelf: true }, action: 'alert', severity: 'critical', cooldown: 0 },
|
|
286
|
+
{ name: 'External API Rate Limit', description: 'Throttle agent when it makes more than 100 external API calls per minute.', category: 'rate_limit', rule_type: 'threshold', conditions: { metric: 'external_api_calls', threshold: 100, window: '1m' }, action: 'throttle', severity: 'medium', cooldown: 5 },
|
|
287
|
+
{ name: 'Conversation Loop Detection', description: 'Pause agent if it enters a repetitive loop ā same output 3+ times consecutively.', category: 'behavioral', rule_type: 'pattern', conditions: { metric: 'duplicate_outputs', threshold: 3, windowMessages: 10 }, action: 'pause', severity: 'high', cooldown: 30 },
|
|
288
|
+
{ name: 'Unauthorized Outbound Connection', description: 'Block and alert when agent attempts to connect to domains not on the allowlist.', category: 'network', rule_type: 'allowlist', conditions: { allowedDomains: ['*.agenticmail.io', '*.openai.com', '*.anthropic.com', '*.googleapis.com'] }, action: 'block', severity: 'high', cooldown: 5 },
|
|
289
|
+
{ name: 'PII Accumulation Warning', description: 'Alert when agent stores more than 100 PII items in its working memory.', category: 'data_protection', rule_type: 'threshold', conditions: { metric: 'pii_items_in_context', threshold: 100 }, action: 'alert', severity: 'high', cooldown: 120 },
|
|
290
|
+
{ name: 'Cross-Agent Communication Anomaly', description: 'Alert when inter-agent email volume exceeds 50 messages per hour ā possible infinite loop.', category: 'behavioral', rule_type: 'threshold', conditions: { metric: 'inter_agent_emails', threshold: 50, window: '1h' }, action: 'alert', severity: 'high', cooldown: 60 },
|
|
291
|
+
];
|
|
292
|
+
|
|
293
|
+
for (const g of guardrails) {
|
|
294
|
+
await run(
|
|
295
|
+
`INSERT INTO guardrail_rules (id, org_id, name, description, category, rule_type, conditions, action, severity, cooldown_minutes, enabled, created_by, created_at, updated_at)
|
|
296
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, true, 'system', $11, $11)
|
|
297
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
298
|
+
[uid(), ORG_ID, g.name, g.description, g.category, g.rule_type, JSON.stringify(g.conditions), g.action, g.severity, g.cooldown, now]
|
|
299
|
+
);
|
|
300
|
+
console.log(` ā
${g.name}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
304
|
+
// 5. COMMUNITY SKILLS (Skill Index)
|
|
305
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
306
|
+
console.log('\nš§© Populating community skill index...');
|
|
307
|
+
|
|
308
|
+
const skills = [
|
|
309
|
+
{ skillId: 'email-triage', name: 'Email Triage & Classification', description: 'Automatically classify incoming emails by priority, category, and required action. Uses NLP to detect urgency, sentiment, and topic.', author: 'agenticmail', version: '1.2.0', tags: ['email', 'classification', 'nlp', 'productivity'], tools: ['email.read', 'email.label', 'email.move'], configSchema: { rules: { type: 'array', description: 'Classification rules' }, categories: { type: 'array', description: 'Custom categories' } } },
|
|
310
|
+
{ skillId: 'calendar-scheduler', name: 'Smart Calendar Scheduler', description: 'AI-powered meeting scheduling via email. Parses availability, suggests optimal times, sends calendar invites.', author: 'agenticmail', version: '1.0.3', tags: ['calendar', 'scheduling', 'email', 'productivity'], tools: ['calendar.read', 'calendar.create', 'email.send'], configSchema: { timezone: { type: 'string' }, workingHours: { type: 'object' } } },
|
|
311
|
+
{ skillId: 'slack-bridge', name: 'Slack Integration Bridge', description: 'Bridge agent email conversations to Slack channels. Forward important emails, send Slack notifications, sync threads.', author: 'agenticmail', version: '2.1.0', tags: ['slack', 'integration', 'communication', 'notifications'], tools: ['slack.post', 'slack.read', 'email.read'], configSchema: { channelMap: { type: 'object', description: 'Email-to-channel routing rules' }, botToken: { type: 'string', secret: true } } },
|
|
312
|
+
{ skillId: 'invoice-processor', name: 'Invoice Processing & Extraction', description: 'Extract data from PDF/image invoices using OCR. Parse line items, totals, vendor info. Create structured records.', author: 'agenticmail', version: '1.5.2', tags: ['finance', 'invoices', 'ocr', 'automation'], tools: ['file.read', 'vision.analyze', 'database.write'], configSchema: { approvalThreshold: { type: 'number', description: 'Amount requiring approval' } } },
|
|
313
|
+
{ skillId: 'customer-support', name: 'Customer Support Agent', description: 'Handle customer support emails with knowledge base lookup, ticket creation, escalation rules, and SLA tracking.', author: 'agenticmail', version: '3.0.1', tags: ['support', 'customer-service', 'tickets', 'sla'], tools: ['email.read', 'email.send', 'knowledge.search', 'ticket.create'], configSchema: { slaConfig: { type: 'object' }, escalationRules: { type: 'array' } } },
|
|
314
|
+
{ skillId: 'data-analyst', name: 'Data Analysis & Reporting', description: 'Analyze datasets, generate reports with visualizations, and distribute via email. Supports CSV, JSON, SQL queries.', author: 'community', version: '1.1.0', tags: ['analytics', 'reporting', 'data', 'visualization'], tools: ['database.query', 'file.read', 'file.write', 'email.send'], configSchema: { dataSources: { type: 'array' }, reportTemplates: { type: 'array' } } },
|
|
315
|
+
{ skillId: 'web-researcher', name: 'Web Research & Summarization', description: 'Research topics across the web, summarize findings, compile reports. Supports academic papers, news, and general research.', author: 'community', version: '2.0.0', tags: ['research', 'web', 'summarization', 'knowledge'], tools: ['web.search', 'web.fetch', 'file.write', 'email.send'], configSchema: { searchProviders: { type: 'array' }, maxSources: { type: 'number' } } },
|
|
316
|
+
{ skillId: 'compliance-monitor', name: 'Compliance Monitoring Agent', description: 'Monitor agent activities for compliance violations. Generate SOC 2, GDPR, HIPAA reports. Track policy adherence.', author: 'agenticmail', version: '1.3.0', tags: ['compliance', 'audit', 'soc2', 'gdpr', 'hipaa'], tools: ['audit.read', 'report.generate', 'email.send'], configSchema: { frameworks: { type: 'array', description: 'Compliance frameworks to monitor' } } },
|
|
317
|
+
{ skillId: 'document-drafting', name: 'Document Drafting & Review', description: 'Draft contracts, proposals, reports, and other business documents. Includes template management and review workflows.', author: 'community', version: '1.0.0', tags: ['documents', 'drafting', 'templates', 'review'], tools: ['file.write', 'file.read', 'email.send'], configSchema: { templates: { type: 'array' }, reviewers: { type: 'array' } } },
|
|
318
|
+
{ skillId: 'github-ops', name: 'GitHub Operations', description: 'Manage GitHub repositories, issues, PRs, and deployments via agent commands. Supports CI/CD triggers and code review.', author: 'community', version: '1.4.0', tags: ['github', 'devops', 'ci-cd', 'code-review'], tools: ['github.issues', 'github.prs', 'github.actions', 'email.send'], configSchema: { repos: { type: 'array' }, autoMerge: { type: 'boolean' } } },
|
|
319
|
+
];
|
|
320
|
+
|
|
321
|
+
for (const s of skills) {
|
|
322
|
+
await run(
|
|
323
|
+
`INSERT INTO community_skill_index (id, name, description, author, version, repository, license, category, tags, tools, config_schema, downloads, rating, rating_count, created_at, updated_at)
|
|
324
|
+
VALUES ($1, $2, $3, $4, $5, $6, 'MIT', $7, $8, $9, $10, $11, $12, $13, $14, $14)
|
|
325
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
326
|
+
[s.skillId, s.name, s.description, s.author, s.version, 'https://github.com/agenticmail/' + s.skillId, s.tags[0] || 'general', JSON.stringify(s.tags), JSON.stringify(s.tools), JSON.stringify(s.configSchema), Math.floor(Math.random() * 5000) + 100, parseFloat((3.5 + Math.random() * 1.5).toFixed(1)), Math.floor(Math.random() * 200) + 5, now]
|
|
327
|
+
);
|
|
328
|
+
console.log(` ā
${s.name}`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
332
|
+
// 6. VAULT ENTRIES (demo secrets ā encrypted values are placeholders)
|
|
333
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
334
|
+
console.log('\nš Creating vault entries...');
|
|
335
|
+
|
|
336
|
+
const vaultEntries = [
|
|
337
|
+
{ name: 'anthropic-api-key', category: 'api_key', metadata: { provider: 'Anthropic', environment: 'production', description: 'Claude API key for agent LLM calls' } },
|
|
338
|
+
{ name: 'openai-api-key', category: 'api_key', metadata: { provider: 'OpenAI', environment: 'production', description: 'GPT-4 API key for fallback provider' } },
|
|
339
|
+
{ name: 'sendgrid-api-key', category: 'api_key', metadata: { provider: 'SendGrid', environment: 'production', description: 'Email delivery service API key' } },
|
|
340
|
+
{ name: 'slack-bot-token', category: 'api_key', metadata: { provider: 'Slack', environment: 'production', description: 'Slack bot token for notifications' } },
|
|
341
|
+
{ name: 'stripe-secret-key', category: 'api_key', metadata: { provider: 'Stripe', environment: 'production', description: 'Payment processing secret key' } },
|
|
342
|
+
{ name: 'aws-access-credentials', category: 'cloud', metadata: { provider: 'AWS', region: 'us-east-1', description: 'S3 and SES access credentials' } },
|
|
343
|
+
{ name: 'database-backup-key', category: 'encryption', metadata: { algorithm: 'AES-256-GCM', description: 'Encryption key for database backup files' } },
|
|
344
|
+
{ name: 'smtp-relay-password', category: 'credential', metadata: { service: 'SMTP', host: 'smtp.agenticmail.io', description: 'SMTP relay authentication password' } },
|
|
345
|
+
];
|
|
346
|
+
|
|
347
|
+
for (const v of vaultEntries) {
|
|
348
|
+
await run(
|
|
349
|
+
`INSERT INTO vault_entries (id, org_id, name, category, encrypted_value, metadata, created_by, created_at, updated_at)
|
|
350
|
+
VALUES ($1, $2, $3, $4, $5, $6, 'admin', $7, $7)
|
|
351
|
+
ON CONFLICT DO NOTHING`,
|
|
352
|
+
[uid(), ORG_ID, v.name, v.category, 'DEMO_ENCRYPTED_VALUE_' + v.name, JSON.stringify(v.metadata), now]
|
|
353
|
+
);
|
|
354
|
+
console.log(` ā
${v.name}`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
358
|
+
// 7. MANAGED AGENTS (demo agents)
|
|
359
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
360
|
+
console.log('\nš¤ Creating managed agents...');
|
|
361
|
+
|
|
362
|
+
const agents = [
|
|
363
|
+
{ id: 'agent-support-01', name: 'Customer Support Agent', orgId: ORG_ID, state: 'active', config: { identity: { name: 'Support Agent', email: 'support@agenticmail.io', avatar: null }, model: 'claude-sonnet-4-20250514', systemPrompt: 'You are a helpful customer support agent for AgenticMail. Respond to customer inquiries professionally, escalate complex issues to human agents, and maintain a knowledge base of common solutions.', tools: ['email.read', 'email.send', 'knowledge.search', 'ticket.create'], maxTokensPerTurn: 4096, budgetMonthly: 50 } },
|
|
364
|
+
{ id: 'agent-research-01', name: 'Research Agent', orgId: ORG_ID, state: 'active', config: { identity: { name: 'Research Agent', email: 'research@agenticmail.io', avatar: null }, model: 'claude-sonnet-4-20250514', systemPrompt: 'You are a research agent that gathers information from the web, analyzes data, and compiles comprehensive reports. Be thorough, cite sources, and present findings clearly.', tools: ['web.search', 'web.fetch', 'file.write', 'email.send'], maxTokensPerTurn: 8192, budgetMonthly: 100 } },
|
|
365
|
+
{ id: 'agent-ops-01', name: 'DevOps Agent', orgId: ORG_ID, state: 'active', config: { identity: { name: 'DevOps Agent', email: 'devops@agenticmail.io', avatar: null }, model: 'claude-sonnet-4-20250514', systemPrompt: 'You are a DevOps agent responsible for monitoring deployments, running health checks, managing CI/CD pipelines, and alerting the team to infrastructure issues.', tools: ['github.actions', 'shell.execute', 'email.send', 'slack.post'], maxTokensPerTurn: 4096, budgetMonthly: 75 } },
|
|
366
|
+
{ id: 'agent-finance-01', name: 'Finance Agent', orgId: ORG_ID, state: 'paused', config: { identity: { name: 'Finance Agent', email: 'finance@agenticmail.io', avatar: null }, model: 'claude-sonnet-4-20250514', systemPrompt: 'You are a finance agent that processes invoices, tracks expenses, generates financial reports, and manages budget alerts. All financial actions require human approval.', tools: ['file.read', 'database.query', 'email.send', 'spreadsheet.edit'], maxTokensPerTurn: 4096, budgetMonthly: 30 } },
|
|
367
|
+
{ id: 'agent-compliance-01', name: 'Compliance Monitor', orgId: ORG_ID, state: 'active', config: { identity: { name: 'Compliance Agent', email: 'compliance@agenticmail.io', avatar: null }, model: 'claude-sonnet-4-20250514', systemPrompt: 'You are a compliance monitoring agent. Review agent activities for policy violations, generate compliance reports (SOC 2, GDPR), and flag potential security issues.', tools: ['audit.read', 'report.generate', 'email.send'], maxTokensPerTurn: 4096, budgetMonthly: 40 } },
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
for (const a of agents) {
|
|
371
|
+
await run(
|
|
372
|
+
`INSERT INTO managed_agents (id, org_id, name, display_name, state, config, health, usage, created_at, updated_at)
|
|
373
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $9)
|
|
374
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
375
|
+
[a.id, a.orgId, a.name.toLowerCase().replace(/\s+/g, '-'), a.name, a.state, JSON.stringify(a.config), JSON.stringify({ status: a.state === 'active' ? 'healthy' : 'paused', lastCheck: now }), JSON.stringify({ totalTasks: Math.floor(Math.random() * 500), totalTokens: Math.floor(Math.random() * 1000000), totalEmails: Math.floor(Math.random() * 200) }), now]
|
|
376
|
+
);
|
|
377
|
+
console.log(` ā
${a.name} (${a.state})`);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
381
|
+
// 8. ACTION JOURNAL (sample audit entries)
|
|
382
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
383
|
+
console.log('\nš Creating action journal entries...');
|
|
384
|
+
|
|
385
|
+
const journalEntries = [
|
|
386
|
+
{ agentId: 'agent-support-01', toolId: 'email-send', toolName: 'email.send', actionType: 'tool_call', forwardData: { to: 'customer@example.com', subject: 'RE: API rate limits inquiry', body: 'Thank you for reaching out...' } },
|
|
387
|
+
{ agentId: 'agent-support-01', toolId: 'kb-search', toolName: 'knowledge.search', actionType: 'tool_call', forwardData: { query: 'billing FAQ', knowledgeBase: 'platform-guide' } },
|
|
388
|
+
{ agentId: 'agent-research-01', toolId: 'web-search', toolName: 'web.search', actionType: 'tool_call', forwardData: { query: 'competitor pricing models Q1 2026', provider: 'brave' } },
|
|
389
|
+
{ agentId: 'agent-research-01', toolId: 'file-write', toolName: 'file.write', actionType: 'tool_call', forwardData: { path: 'reports/competitive-analysis-q1.pdf', size: 245760 }, reversible: true, reverseData: { action: 'delete', path: 'reports/competitive-analysis-q1.pdf' } },
|
|
390
|
+
{ agentId: 'agent-ops-01', toolId: 'gh-actions', toolName: 'github.actions', actionType: 'tool_call', forwardData: { repo: 'agenticmail/enterprise', workflow: 'deploy.yml', ref: 'v0.5.20' } },
|
|
391
|
+
{ agentId: 'agent-ops-01', toolId: 'email-send', toolName: 'email.send', actionType: 'tool_call', forwardData: { to: 'engineering@agenticmail.io', subject: 'Deployment v0.5.20 ā Success', body: 'All health checks passed.' } },
|
|
392
|
+
{ agentId: 'agent-finance-01', toolId: 'db-query', toolName: 'database.query', actionType: 'tool_call', forwardData: { query: 'SELECT * FROM expenses WHERE month = 2026-01', database: 'accounting' } },
|
|
393
|
+
{ agentId: 'agent-compliance-01', toolId: 'audit-read', toolName: 'audit.read', actionType: 'tool_call', forwardData: { period: 'last_24h', scope: 'all_agents', actionsReviewed: 847 } },
|
|
394
|
+
{ agentId: 'agent-compliance-01', toolId: 'report-gen', toolName: 'report.generate', actionType: 'tool_call', forwardData: { type: 'soc2_weekly', findings: 2, severity: 'medium' } },
|
|
395
|
+
{ agentId: 'agent-support-01', toolId: 'email-send', toolName: 'email.send', actionType: 'dlp_blocked', forwardData: { to: 'customer@example.com', reason: 'SSN detected in email body', severity: 'critical' } },
|
|
396
|
+
];
|
|
397
|
+
|
|
398
|
+
for (const j of journalEntries) {
|
|
399
|
+
await run(
|
|
400
|
+
`INSERT INTO action_journal (id, org_id, agent_id, tool_id, tool_name, action_type, forward_data, reverse_data, reversible, created_at)
|
|
401
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
402
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
403
|
+
[uid(), ORG_ID, j.agentId, j.toolId, j.toolName, j.actionType, JSON.stringify(j.forwardData), j.reverseData ? JSON.stringify(j.reverseData) : null, j.reversible ? 1 : 0, new Date(Date.now() - Math.random() * 7 * 86400000).toISOString()]
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
console.log(` ā
${journalEntries.length} journal entries`);
|
|
407
|
+
|
|
408
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
409
|
+
// 9. COMPLIANCE REPORTS
|
|
410
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
411
|
+
console.log('\nš Creating compliance reports...');
|
|
412
|
+
|
|
413
|
+
const reports = [
|
|
414
|
+
{ type: 'soc2', agentId: null, status: 'completed', data: { framework: 'SOC 2 Type II', period: '2026-01-01 to 2026-01-31', findings: 3, critical: 0, high: 1, medium: 2, controls_assessed: 47, controls_passed: 44, summary: 'Overall compliance posture is strong. One high-severity finding related to incomplete API key rotation schedule. Two medium findings on documentation gaps.' } },
|
|
415
|
+
{ type: 'gdpr', agentId: null, status: 'completed', data: { framework: 'GDPR', period: '2026-01-01 to 2026-01-31', dataSubjectRequests: 5, requestsCompleted: 5, averageResponseDays: 12, piiInventoryItems: 234, retentionViolations: 0, summary: 'All data subject access requests fulfilled within 30-day window. PII inventory up to date. No retention policy violations.' } },
|
|
416
|
+
{ type: 'hipaa', agentId: null, status: 'completed', data: { framework: 'HIPAA', period: '2026-01-01 to 2026-01-31', phiAccessEvents: 128, authorizedAccess: 128, unauthorizedAttempts: 0, encryptionCompliance: '100%', auditLogIntegrity: 'verified', summary: 'Full HIPAA compliance maintained. All PHI access logged and authorized. Encryption at rest and in transit verified.' } },
|
|
417
|
+
];
|
|
418
|
+
|
|
419
|
+
for (const r of reports) {
|
|
420
|
+
await run(
|
|
421
|
+
`INSERT INTO compliance_reports (id, org_id, type, title, parameters, status, data, format, generated_by, created_at)
|
|
422
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, 'json', 'system', $8)
|
|
423
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
424
|
+
[uid(), ORG_ID, r.type, r.data.framework + ' Report ā Jan 2026', JSON.stringify({ period: r.data.period }), r.status, JSON.stringify(r.data), now]
|
|
425
|
+
);
|
|
426
|
+
console.log(` ā
${r.type.toUpperCase()} report`);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
430
|
+
// SET ORG_ID on company_settings
|
|
431
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
432
|
+
console.log('\nš¢ Setting organization ID...');
|
|
433
|
+
const orgIdGenerated = 'AMXK7W9P3E';
|
|
434
|
+
await run(
|
|
435
|
+
`UPDATE company_settings SET org_id = $1 WHERE id = 'default' AND (org_id IS NULL OR org_id = '')`,
|
|
436
|
+
[orgIdGenerated]
|
|
437
|
+
);
|
|
438
|
+
console.log(` ā
Org ID set to: ${orgIdGenerated}`);
|
|
439
|
+
|
|
440
|
+
console.log('\n⨠Seed complete! All data populated.\n');
|
|
441
|
+
console.log('Summary:');
|
|
442
|
+
console.log(` š ${kbData.length} knowledge bases (${kbData.reduce((a, k) => a + k.documents.length, 0)} documents, ${kbData.reduce((a, k) => a + k.documents.reduce((b, d) => b + d.chunks.length, 0), 0)} chunks)`);
|
|
443
|
+
console.log(` š ${policies.length} approval policies`);
|
|
444
|
+
console.log(` š”ļø ${dlpRules.length} DLP rules`);
|
|
445
|
+
console.log(` š§ ${guardrails.length} guardrail rules`);
|
|
446
|
+
console.log(` š§© ${skills.length} community skills`);
|
|
447
|
+
console.log(` š ${vaultEntries.length} vault entries`);
|
|
448
|
+
console.log(` š¤ ${agents.length} managed agents`);
|
|
449
|
+
console.log(` š ${journalEntries.length} journal entries`);
|
|
450
|
+
console.log(` š ${reports.length} compliance reports`);
|
|
451
|
+
|
|
452
|
+
await pool.end();
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
seed().catch(err => { console.error('ā Seed failed:', err.message); process.exit(1); });
|
package/src/admin/routes.ts
CHANGED
|
@@ -569,8 +569,11 @@ export function createAdminRoutes(db: DatabaseAdapter) {
|
|
|
569
569
|
// āāā Provider Management āāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
570
570
|
|
|
571
571
|
api.get('/providers', requireRole('admin'), async (c) => {
|
|
572
|
+
var settings = await db.getSettings();
|
|
573
|
+
var pricingConfig = (settings as any)?.modelPricingConfig;
|
|
574
|
+
var savedApiKeys = pricingConfig?.providerApiKeys || {};
|
|
572
575
|
var builtIn = Object.values(PROVIDER_REGISTRY).map(function(p) {
|
|
573
|
-
var configured = !p.requiresApiKey || (p.envKey && !!process.env[p.envKey]);
|
|
576
|
+
var configured = !p.requiresApiKey || (p.envKey && !!process.env[p.envKey]) || !!savedApiKeys[p.id];
|
|
574
577
|
return {
|
|
575
578
|
id: p.id,
|
|
576
579
|
name: p.name,
|
|
@@ -584,8 +587,6 @@ export function createAdminRoutes(db: DatabaseAdapter) {
|
|
|
584
587
|
};
|
|
585
588
|
});
|
|
586
589
|
|
|
587
|
-
var settings = await db.getSettings();
|
|
588
|
-
var pricingConfig = (settings as any)?.modelPricingConfig;
|
|
589
590
|
var customProviders = pricingConfig?.customProviders || [];
|
|
590
591
|
var custom = customProviders.map(function(p: any) {
|
|
591
592
|
return { ...p, configured: true, source: 'custom' as const };
|
|
@@ -1323,31 +1323,40 @@ function ProvidersSection(props) {
|
|
|
1323
1323
|
? h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, fontSize: 12 } },
|
|
1324
1324
|
h('span', { style: { color: 'var(--success, #16a34a)' } }, 'ā API key configured via environment'),
|
|
1325
1325
|
h('button', { className: 'btn btn-sm btn-ghost', style: { padding: '2px 8px', fontSize: 11 }, onClick: function() {
|
|
1326
|
-
setApiKeyInput('');
|
|
1327
|
-
setApiKeyModal({ providerId: p.id, providerName: p.name, isUpdate: true });
|
|
1326
|
+
props.setApiKeyInput('');
|
|
1327
|
+
props.setApiKeyModal({ providerId: p.id, providerName: p.name, isUpdate: true });
|
|
1328
1328
|
}}, 'Update Key')
|
|
1329
1329
|
)
|
|
1330
1330
|
: h('div', null,
|
|
1331
1331
|
h('button', { className: 'btn btn-sm btn-primary', onClick: function() {
|
|
1332
|
-
setApiKeyInput('');
|
|
1333
|
-
setApiKeyModal({ providerId: p.id, providerName: p.name, isUpdate: false });
|
|
1332
|
+
props.setApiKeyInput('');
|
|
1333
|
+
props.setApiKeyModal({ providerId: p.id, providerName: p.name, isUpdate: false });
|
|
1334
1334
|
}}, 'š Add API Key')
|
|
1335
1335
|
)
|
|
1336
1336
|
),
|
|
1337
1337
|
h('div', { style: { display: 'flex', gap: 6, marginTop: 8 } },
|
|
1338
|
-
isLocal && h('button', {
|
|
1338
|
+
(isLocal || isConfigured) && h('button', {
|
|
1339
1339
|
className: 'btn btn-sm',
|
|
1340
1340
|
disabled: discovering[p.id],
|
|
1341
1341
|
onClick: function() { handleDiscover(p.id); },
|
|
1342
|
-
}, discovering[p.id] ? 'Discovering...' : 'Discover Models'),
|
|
1342
|
+
}, discovering[p.id] ? 'Discovering...' : (isLocal ? 'Discover Models' : 'List Models')),
|
|
1343
1343
|
p.isCustom && h('button', {
|
|
1344
1344
|
className: 'btn btn-sm btn-danger',
|
|
1345
1345
|
style: { padding: '2px 8px', fontSize: 12 },
|
|
1346
1346
|
onClick: function() { handleDeleteProvider(p.id); },
|
|
1347
1347
|
}, I.trash())
|
|
1348
1348
|
),
|
|
1349
|
+
// Show default models for cloud providers that have them
|
|
1350
|
+
!discovered && p.defaultModels && p.defaultModels.length > 0 && h('div', { style: { marginTop: 8, fontSize: 12 } },
|
|
1351
|
+
h('div', { style: { fontWeight: 600, marginBottom: 4, color: 'var(--text-secondary)' } }, 'Available Models (' + p.defaultModels.length + ')'),
|
|
1352
|
+
h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: 4 } },
|
|
1353
|
+
p.defaultModels.map(function(mid) {
|
|
1354
|
+
return h('span', { key: mid, className: 'badge badge-neutral', style: { fontSize: 11 } }, mid);
|
|
1355
|
+
})
|
|
1356
|
+
)
|
|
1357
|
+
),
|
|
1349
1358
|
discovered && discovered.length > 0 && h('div', { style: { marginTop: 8, padding: 8, background: 'var(--bg-secondary)', borderRadius: 'var(--radius)', fontSize: 12 } },
|
|
1350
|
-
h('div', { style: { fontWeight: 600, marginBottom: 4 } }, '
|
|
1359
|
+
h('div', { style: { fontWeight: 600, marginBottom: 4 } }, 'Models (' + discovered.length + ')'),
|
|
1351
1360
|
h('div', { style: { maxHeight: 120, overflow: 'auto' } },
|
|
1352
1361
|
discovered.map(function(m) {
|
|
1353
1362
|
var modelName = typeof m === 'string' ? m : (m.id || m.name || m.model);
|
package/src/server.ts
CHANGED
|
@@ -393,20 +393,12 @@ export function createServer(config: ServerConfig): ServerInstance {
|
|
|
393
393
|
healthMonitor.start();
|
|
394
394
|
|
|
395
395
|
// Load saved provider API keys from DB into process.env
|
|
396
|
-
config.db.getSettings().then((settings: any) => {
|
|
396
|
+
config.db.getSettings().then(async (settings: any) => {
|
|
397
397
|
const keys = settings?.modelPricingConfig?.providerApiKeys;
|
|
398
398
|
if (keys && typeof keys === 'object') {
|
|
399
|
-
|
|
400
|
-
const envMap: Record<string, string> = {
|
|
401
|
-
anthropic: 'ANTHROPIC_API_KEY', openai: 'OPENAI_API_KEY',
|
|
402
|
-
google: 'GOOGLE_API_KEY', deepseek: 'DEEPSEEK_API_KEY',
|
|
403
|
-
xai: 'XAI_API_KEY', mistral: 'MISTRAL_API_KEY',
|
|
404
|
-
groq: 'GROQ_API_KEY', together: 'TOGETHER_API_KEY',
|
|
405
|
-
fireworks: 'FIREWORKS_API_KEY', perplexity: 'PERPLEXITY_API_KEY',
|
|
406
|
-
cohere: 'COHERE_API_KEY',
|
|
407
|
-
};
|
|
399
|
+
const { PROVIDER_REGISTRY: _PR } = await import('./runtime/providers.js');
|
|
408
400
|
for (const [providerId, apiKey] of Object.entries(keys)) {
|
|
409
|
-
const envVar =
|
|
401
|
+
const envVar = _PR[providerId]?.envKey;
|
|
410
402
|
if (envVar && apiKey && !process.env[envVar]) {
|
|
411
403
|
process.env[envVar] = apiKey as string;
|
|
412
404
|
console.log(` š Loaded API key for ${providerId}`);
|