@l4yercak3/cli 1.1.11 → 1.2.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/bin/cli.js +6 -0
- package/docs/mcp_server/MCP_SERVER_ARCHITECTURE.md +1481 -0
- package/docs/mcp_server/applicationOntology.ts +817 -0
- package/docs/mcp_server/cliApplications.ts +639 -0
- package/docs/mcp_server/crmOntology.ts +1063 -0
- package/docs/mcp_server/eventOntology.ts +1183 -0
- package/docs/mcp_server/formsOntology.ts +1401 -0
- package/docs/mcp_server/ontologySchemas.ts +185 -0
- package/docs/mcp_server/schema.ts +250 -0
- package/package.json +5 -2
- package/src/commands/login.js +0 -6
- package/src/commands/mcp-server.js +32 -0
- package/src/commands/spread.js +57 -4
- package/src/mcp/auth.js +127 -0
- package/src/mcp/registry/domains/applications.js +516 -0
- package/src/mcp/registry/domains/codegen.js +894 -0
- package/src/mcp/registry/domains/core.js +326 -0
- package/src/mcp/registry/domains/crm.js +591 -0
- package/src/mcp/registry/domains/events.js +649 -0
- package/src/mcp/registry/domains/forms.js +696 -0
- package/src/mcp/registry/index.js +162 -0
- package/src/mcp/server.js +116 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ONTOLOGY SCHEMAS
|
|
3
|
+
*
|
|
4
|
+
* Universal object storage system for ALL data types.
|
|
5
|
+
* This replaces separate tables with a unified object model.
|
|
6
|
+
*
|
|
7
|
+
* Core Concepts:
|
|
8
|
+
* - objects: Universal storage for any entity (translations, events, contacts, etc.)
|
|
9
|
+
* - objectLinks: Relationships between objects (like graph edges)
|
|
10
|
+
* - objectActions: Audit trail of actions performed on objects
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { defineTable } from "convex/server";
|
|
14
|
+
import { v } from "convex/values";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* OBJECTS TABLE
|
|
18
|
+
* Universal storage for all entity types
|
|
19
|
+
*
|
|
20
|
+
* Examples:
|
|
21
|
+
* - type="translation", subtype="system", name="desktop.welcome"
|
|
22
|
+
* - type="event", subtype="podcast", name="Episode 42"
|
|
23
|
+
* - type="invoice", subtype="client", name="INV-2024-001"
|
|
24
|
+
* - type="contact", subtype="customer", name="John Doe"
|
|
25
|
+
* - type="transaction", subtype="ticket_purchase", name="Product - Customer"
|
|
26
|
+
*
|
|
27
|
+
* TRANSACTION OBJECT STRUCTURE:
|
|
28
|
+
* Transactions (type="transaction") store purchase data in customProperties.
|
|
29
|
+
*
|
|
30
|
+
* NEW STRUCTURE (v2 - Multi-line Item Transactions):
|
|
31
|
+
* One transaction per checkout with multiple line items:
|
|
32
|
+
* {
|
|
33
|
+
* checkoutSessionId: Id<"objects">,
|
|
34
|
+
* lineItems: [
|
|
35
|
+
* {
|
|
36
|
+
* productId: Id<"objects">,
|
|
37
|
+
* productName: string,
|
|
38
|
+
* productDescription?: string,
|
|
39
|
+
* quantity: number,
|
|
40
|
+
* unitPriceInCents: number, // Net price per unit
|
|
41
|
+
* totalPriceInCents: number, // Net total for this line (unitPrice * quantity)
|
|
42
|
+
* taxRatePercent: number,
|
|
43
|
+
* taxAmountInCents: number,
|
|
44
|
+
* ticketId?: Id<"objects">, // If this is a ticket product
|
|
45
|
+
* eventId?: Id<"objects">,
|
|
46
|
+
* eventName?: string,
|
|
47
|
+
* },
|
|
48
|
+
* // ... more line items
|
|
49
|
+
* ],
|
|
50
|
+
* subtotalInCents: number, // Sum of all line item totals (net)
|
|
51
|
+
* taxAmountInCents: number, // Sum of all line item taxes
|
|
52
|
+
* totalInCents: number, // Grand total (subtotal + tax)
|
|
53
|
+
* currency: string,
|
|
54
|
+
* customerName: string,
|
|
55
|
+
* customerEmail: string,
|
|
56
|
+
* payerType: "individual" | "organization",
|
|
57
|
+
* paymentMethod: string,
|
|
58
|
+
* paymentStatus: string,
|
|
59
|
+
* invoicingStatus: "pending" | "on_draft_invoice" | "invoiced",
|
|
60
|
+
* // ... other customer/payer fields
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* LEGACY STRUCTURE (v1 - Single Product Per Transaction):
|
|
64
|
+
* DEPRECATED: Old approach created one transaction per product.
|
|
65
|
+
* Kept for backward compatibility with existing data.
|
|
66
|
+
* {
|
|
67
|
+
* productId: Id<"objects">,
|
|
68
|
+
* productName: string,
|
|
69
|
+
* quantity: number,
|
|
70
|
+
* amountInCents: number, // Total for this ONE product
|
|
71
|
+
* currency: string,
|
|
72
|
+
* taxRatePercent: number,
|
|
73
|
+
* // ... single product fields
|
|
74
|
+
* }
|
|
75
|
+
*/
|
|
76
|
+
export const objects = defineTable({
|
|
77
|
+
// Multi-tenancy
|
|
78
|
+
organizationId: v.id("organizations"),
|
|
79
|
+
|
|
80
|
+
// Object Identity
|
|
81
|
+
type: v.string(), // "translation", "event", "invoice", "contact", etc.
|
|
82
|
+
subtype: v.optional(v.string()), // "system", "app", "content", etc.
|
|
83
|
+
|
|
84
|
+
// Universal Properties (ALL objects have these)
|
|
85
|
+
name: v.string(), // Human-readable identifier
|
|
86
|
+
description: v.optional(v.string()),
|
|
87
|
+
status: v.string(), // Object-specific statuses
|
|
88
|
+
|
|
89
|
+
// Translation-Specific Fields (only used when type="translation")
|
|
90
|
+
locale: v.optional(v.string()), // "en", "de", "pl"
|
|
91
|
+
value: v.optional(v.string()), // Translation text
|
|
92
|
+
|
|
93
|
+
// Gravel Road - Per-Org/Per-Type Customizations
|
|
94
|
+
// This allows each organization to add their own fields without schema changes
|
|
95
|
+
customProperties: v.optional(v.record(v.string(), v.any())),
|
|
96
|
+
|
|
97
|
+
// Metadata
|
|
98
|
+
// createdBy can be either platform user (staff) or frontend_user (customer)
|
|
99
|
+
// - Platform user (Id<"users">): When staff creates records administratively
|
|
100
|
+
// - Frontend user (Id<"objects">): When customers create records (guest registration, checkout)
|
|
101
|
+
createdBy: v.optional(v.union(v.id("users"), v.id("objects"))),
|
|
102
|
+
createdAt: v.number(),
|
|
103
|
+
updatedAt: v.number(),
|
|
104
|
+
})
|
|
105
|
+
// Core indexes for fast queries
|
|
106
|
+
.index("by_org", ["organizationId"])
|
|
107
|
+
.index("by_org_type", ["organizationId", "type"])
|
|
108
|
+
.index("by_org_type_subtype", ["organizationId", "type", "subtype"])
|
|
109
|
+
.index("by_type", ["type"])
|
|
110
|
+
.index("by_type_subtype", ["type", "subtype"])
|
|
111
|
+
.index("by_status", ["status"])
|
|
112
|
+
|
|
113
|
+
// Translation-specific indexes
|
|
114
|
+
.index("by_org_type_locale", ["organizationId", "type", "locale"])
|
|
115
|
+
.index("by_org_type_locale_name", ["organizationId", "type", "locale", "name"])
|
|
116
|
+
.index("by_type_locale", ["type", "locale"])
|
|
117
|
+
|
|
118
|
+
// Search indexes
|
|
119
|
+
.searchIndex("search_by_name", { searchField: "name" })
|
|
120
|
+
.searchIndex("search_by_value", { searchField: "value" });
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* OBJECT LINKS TABLE
|
|
124
|
+
* Relationships between objects (graph edges)
|
|
125
|
+
*
|
|
126
|
+
* Examples:
|
|
127
|
+
* - fromObjectId=translation1, toObjectId=event1, linkType="translates"
|
|
128
|
+
* - fromObjectId=user1, toObjectId=org1, linkType="member_of"
|
|
129
|
+
* - fromObjectId=org1, toObjectId=address1, linkType="has_address"
|
|
130
|
+
* - fromObjectId=contact1, toObjectId=event1, linkType="registers_for"
|
|
131
|
+
*/
|
|
132
|
+
export const objectLinks = defineTable({
|
|
133
|
+
organizationId: v.id("organizations"),
|
|
134
|
+
|
|
135
|
+
// Link Endpoints
|
|
136
|
+
fromObjectId: v.id("objects"),
|
|
137
|
+
toObjectId: v.id("objects"),
|
|
138
|
+
|
|
139
|
+
// Link Type (the "verb" in the relationship)
|
|
140
|
+
linkType: v.string(), // "translates", "member_of", "has_address", "registers_for", etc.
|
|
141
|
+
|
|
142
|
+
// Link-Specific Data
|
|
143
|
+
// Store additional metadata about the relationship
|
|
144
|
+
properties: v.optional(v.record(v.string(), v.any())),
|
|
145
|
+
|
|
146
|
+
// Metadata
|
|
147
|
+
// createdBy can be platform user or frontend_user (same as objects table)
|
|
148
|
+
createdBy: v.optional(v.union(v.id("users"), v.id("objects"))),
|
|
149
|
+
createdAt: v.number(),
|
|
150
|
+
})
|
|
151
|
+
.index("by_from_object", ["fromObjectId"])
|
|
152
|
+
.index("by_to_object", ["toObjectId"])
|
|
153
|
+
.index("by_org_link_type", ["organizationId", "linkType"])
|
|
154
|
+
.index("by_from_link_type", ["fromObjectId", "linkType"])
|
|
155
|
+
.index("by_to_link_type", ["toObjectId", "linkType"]);
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* OBJECT ACTIONS TABLE
|
|
159
|
+
* Audit trail of actions performed on objects
|
|
160
|
+
*
|
|
161
|
+
* Examples:
|
|
162
|
+
* - objectId=translation1, actionType="approve", performedBy=user1
|
|
163
|
+
* - objectId=event1, actionType="publish", performedBy=user2
|
|
164
|
+
* - objectId=invoice1, actionType="send", performedBy=user3
|
|
165
|
+
*/
|
|
166
|
+
export const objectActions = defineTable({
|
|
167
|
+
organizationId: v.id("organizations"),
|
|
168
|
+
objectId: v.id("objects"),
|
|
169
|
+
|
|
170
|
+
// Action Identity
|
|
171
|
+
actionType: v.string(), // "approve", "translate", "publish", "view", "edit", etc.
|
|
172
|
+
|
|
173
|
+
// Action Data
|
|
174
|
+
// Store details about what changed
|
|
175
|
+
actionData: v.optional(v.record(v.string(), v.any())),
|
|
176
|
+
|
|
177
|
+
// Who & When
|
|
178
|
+
// performedBy can be platform user or frontend_user (same as objects table)
|
|
179
|
+
performedBy: v.optional(v.union(v.id("users"), v.id("objects"))),
|
|
180
|
+
performedAt: v.number(),
|
|
181
|
+
})
|
|
182
|
+
.index("by_object", ["objectId"])
|
|
183
|
+
.index("by_org_action_type", ["organizationId", "actionType"])
|
|
184
|
+
.index("by_performer", ["performedBy"])
|
|
185
|
+
.index("by_performed_at", ["performedAt"]);
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ORGANIZED SCHEMA STRUCTURE
|
|
3
|
+
*
|
|
4
|
+
* This schema is composed from modular definitions in the schemas/ directory.
|
|
5
|
+
* See schemas/README.md for documentation on adding new apps.
|
|
6
|
+
*
|
|
7
|
+
* Structure:
|
|
8
|
+
* 1. Core platform (users, organizations, memberships)
|
|
9
|
+
* 2. App Store (apps registry, installations, purchases)
|
|
10
|
+
* 3. Individual Apps (l4yercak3pod, etc. - each is self-contained)
|
|
11
|
+
* 4. Utilities (audit logs)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { defineSchema } from "convex/server";
|
|
15
|
+
|
|
16
|
+
// Import modular schema definitions
|
|
17
|
+
import {
|
|
18
|
+
users,
|
|
19
|
+
organizations,
|
|
20
|
+
organizationMembers,
|
|
21
|
+
userPasswords,
|
|
22
|
+
sessions,
|
|
23
|
+
frontendSessions,
|
|
24
|
+
passkeys,
|
|
25
|
+
passkeysChallenges,
|
|
26
|
+
apiKeys,
|
|
27
|
+
roles,
|
|
28
|
+
permissions,
|
|
29
|
+
rolePermissions,
|
|
30
|
+
userPreferences,
|
|
31
|
+
organizationMedia,
|
|
32
|
+
oauthConnections,
|
|
33
|
+
oauthStates,
|
|
34
|
+
cliSessions,
|
|
35
|
+
cliLoginStates,
|
|
36
|
+
oauthSignupStates,
|
|
37
|
+
webhookSubscriptions
|
|
38
|
+
} from "./schemas/coreSchemas";
|
|
39
|
+
// NOTE: apiKeyDomains table removed - now using unified domain configurations in objects table
|
|
40
|
+
import { apps, appInstallations, snapshots, snapshotLoads, purchases, appAvailabilities } from "./schemas/appStoreSchemas";
|
|
41
|
+
// import { app_podcasting } from "./schemas/appDataSchemas"; // Not yet used
|
|
42
|
+
import { auditLogs, workflowExecutionLogs } from "./schemas/utilitySchemas";
|
|
43
|
+
|
|
44
|
+
// ✅ NEW ONTOLOGY SCHEMAS
|
|
45
|
+
import { objects, objectLinks, objectActions } from "./schemas/ontologySchemas";
|
|
46
|
+
|
|
47
|
+
// 🤖 AI INTEGRATION SCHEMAS
|
|
48
|
+
import {
|
|
49
|
+
aiConversations,
|
|
50
|
+
aiMessages,
|
|
51
|
+
aiToolExecutions,
|
|
52
|
+
organizationAiSettings,
|
|
53
|
+
aiAgentTasks,
|
|
54
|
+
aiAgentMemory,
|
|
55
|
+
aiModels,
|
|
56
|
+
aiWorkItems
|
|
57
|
+
} from "./schemas/aiSchemas";
|
|
58
|
+
|
|
59
|
+
// 💳 AI BILLING SCHEMAS v3.1 (VAT-inclusive pricing, EUR only)
|
|
60
|
+
import {
|
|
61
|
+
aiUsage,
|
|
62
|
+
aiSubscriptions,
|
|
63
|
+
aiTokenBalance,
|
|
64
|
+
aiTokenPurchases,
|
|
65
|
+
aiBudgetAlerts,
|
|
66
|
+
aiBillingEvents
|
|
67
|
+
} from "./schemas/aiBillingSchemas";
|
|
68
|
+
|
|
69
|
+
// 👤 USER QUOTA SCHEMAS (Phase 1: Foundation for per-user limits)
|
|
70
|
+
import { userAIQuotas } from "./schemas/userQuotaSchemas";
|
|
71
|
+
|
|
72
|
+
// 💾 STORAGE TRACKING SCHEMAS (Organization + per-user storage)
|
|
73
|
+
import { organizationStorage, userStorageQuotas } from "./schemas/storageSchemas";
|
|
74
|
+
|
|
75
|
+
// 📧 CONTACT SYNC & BULK EMAIL SCHEMAS (AI-powered external contact integration)
|
|
76
|
+
import { contactSyncs, emailCampaigns } from "./schemas/contactSyncSchemas";
|
|
77
|
+
|
|
78
|
+
// 🔐 OAUTH 2.0 SCHEMAS (OAuth authentication for third-party integrations)
|
|
79
|
+
import {
|
|
80
|
+
oauthApplications,
|
|
81
|
+
oauthAuthorizationCodes,
|
|
82
|
+
oauthRefreshTokens,
|
|
83
|
+
oauthRevokedTokens,
|
|
84
|
+
oauthTokenUsage
|
|
85
|
+
} from "./schemas/oauthSchemas";
|
|
86
|
+
|
|
87
|
+
// 🚦 RATE LIMITING SCHEMAS (Token bucket rate limiting for API abuse prevention)
|
|
88
|
+
import { rateLimitSchemas } from "./schemas/rateLimitSchemas";
|
|
89
|
+
|
|
90
|
+
// 🛡️ SECURITY SCHEMAS (Anomaly detection and security event monitoring)
|
|
91
|
+
import { securitySchemas } from "./schemas/securitySchemas";
|
|
92
|
+
|
|
93
|
+
// 📊 GROWTH TRACKING SCHEMAS (Launch metrics and KPI tracking)
|
|
94
|
+
import {
|
|
95
|
+
dailyGrowthMetrics,
|
|
96
|
+
signupEvents,
|
|
97
|
+
weeklyScorecard,
|
|
98
|
+
salesNotifications,
|
|
99
|
+
celebrationMilestones
|
|
100
|
+
} from "./schemas/growthTrackingSchemas";
|
|
101
|
+
|
|
102
|
+
// 📧 EMAIL QUEUE SCHEMA (Email delivery tracking)
|
|
103
|
+
import { emailQueue } from "./schemas/emailQueueSchemas";
|
|
104
|
+
|
|
105
|
+
// 🎁 BENEFITS PLATFORM SCHEMAS (Benefits & Commissions tracking)
|
|
106
|
+
import {
|
|
107
|
+
benefitClaims,
|
|
108
|
+
commissionPayouts,
|
|
109
|
+
memberWallets,
|
|
110
|
+
platformFees
|
|
111
|
+
} from "./schemas/benefitsSchemas";
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* MAIN SCHEMA EXPORT
|
|
115
|
+
*
|
|
116
|
+
* All tables are defined in their respective schema modules.
|
|
117
|
+
* This file simply composes them together.
|
|
118
|
+
*/
|
|
119
|
+
export default defineSchema({
|
|
120
|
+
// 👥 CORE: Platform foundation
|
|
121
|
+
users,
|
|
122
|
+
organizations,
|
|
123
|
+
organizationMembers,
|
|
124
|
+
userPasswords,
|
|
125
|
+
sessions,
|
|
126
|
+
frontendSessions, // Customer user sessions (separate from platform staff)
|
|
127
|
+
passkeys,
|
|
128
|
+
passkeysChallenges,
|
|
129
|
+
apiKeys,
|
|
130
|
+
// Domain configurations (including API access, email, branding) stored in objects table
|
|
131
|
+
userPreferences,
|
|
132
|
+
organizationMedia,
|
|
133
|
+
oauthConnections,
|
|
134
|
+
oauthStates,
|
|
135
|
+
cliSessions,
|
|
136
|
+
cliLoginStates,
|
|
137
|
+
oauthSignupStates,
|
|
138
|
+
webhookSubscriptions,
|
|
139
|
+
|
|
140
|
+
// 🔐 RBAC: Role-Based Access Control
|
|
141
|
+
roles,
|
|
142
|
+
permissions,
|
|
143
|
+
rolePermissions,
|
|
144
|
+
|
|
145
|
+
// 🏪 APP STORE: Marketplace functionality
|
|
146
|
+
apps,
|
|
147
|
+
appInstallations,
|
|
148
|
+
appAvailabilities,
|
|
149
|
+
snapshots,
|
|
150
|
+
snapshotLoads,
|
|
151
|
+
purchases,
|
|
152
|
+
|
|
153
|
+
// 📱 APPS: Individual app data tables
|
|
154
|
+
// Each app is self-contained with its own table
|
|
155
|
+
// All apps follow the appSchemaBase pattern (see schemas/appSchemaBase.ts)
|
|
156
|
+
// NAMING: Always prefix with "app_"
|
|
157
|
+
// app_podcasting, // Podcasting App
|
|
158
|
+
// Add more apps here as they're created:
|
|
159
|
+
// app_analytics,
|
|
160
|
+
// app_subscribers,
|
|
161
|
+
// app_calendar,
|
|
162
|
+
|
|
163
|
+
// 🛠️ UTILITIES: Supporting functionality
|
|
164
|
+
auditLogs,
|
|
165
|
+
workflowExecutionLogs,
|
|
166
|
+
|
|
167
|
+
// 🥷 ONTOLOGY: Universal object system
|
|
168
|
+
objects, // Universal storage for all entity types
|
|
169
|
+
objectLinks, // Relationships between objects
|
|
170
|
+
objectActions, // Audit trail of actions
|
|
171
|
+
|
|
172
|
+
// 🤖 AI INTEGRATION: General AI Assistant + Email AI Specialist
|
|
173
|
+
aiConversations, // Chat history for general AI assistant
|
|
174
|
+
aiMessages, // Individual messages in conversations
|
|
175
|
+
aiToolExecutions, // Audit trail of tool executions
|
|
176
|
+
// NOTE: Tool drafts use objects table with status="draft" + AI metadata in customProperties
|
|
177
|
+
organizationAiSettings, // AI configuration per organization (LLM + embeddings)
|
|
178
|
+
aiModels, // AI model discovery cache (auto-refreshed daily)
|
|
179
|
+
aiWorkItems, // Work items for human-in-the-loop approval workflow
|
|
180
|
+
aiAgentTasks, // Email AI tasks with approval workflow
|
|
181
|
+
aiAgentMemory, // Email templates and preferences with vector search
|
|
182
|
+
|
|
183
|
+
// 💳 AI BILLING v3.1: Three-tier system (€49 or €2,500-€12,000/mo, VAT incl.)
|
|
184
|
+
aiUsage, // Track AI API usage for billing and monitoring (with privacy audit)
|
|
185
|
+
aiSubscriptions, // Stripe subscriptions for AI features (tier-based + sub-tiers)
|
|
186
|
+
aiTokenBalance, // Purchased token balance (Standard/Privacy-Enhanced only)
|
|
187
|
+
aiTokenPurchases, // Token pack purchase history (with VAT breakdown)
|
|
188
|
+
aiBudgetAlerts, // Budget alert history and acknowledgments
|
|
189
|
+
aiBillingEvents, // Audit log for billing operations
|
|
190
|
+
|
|
191
|
+
// 👤 USER QUOTAS: Per-user limits foundation (Phase 1: tracking only, Phase 4: enforcement)
|
|
192
|
+
userAIQuotas, // Per-user monthly AI token limits
|
|
193
|
+
|
|
194
|
+
// 💾 STORAGE TRACKING: Organization + per-user storage metrics
|
|
195
|
+
organizationStorage, // Aggregated storage per organization
|
|
196
|
+
userStorageQuotas, // Per-user storage limits (Phase 1: tracking only)
|
|
197
|
+
|
|
198
|
+
// 📧 CONTACT SYNC & BULK EMAIL: AI-powered external contact integration
|
|
199
|
+
contactSyncs, // Audit trail for contact synchronization (Microsoft/Google → CRM)
|
|
200
|
+
emailCampaigns, // Bulk email campaigns to CRM contacts/organizations
|
|
201
|
+
|
|
202
|
+
// 🔐 OAUTH 2.0: Third-party authentication and authorization
|
|
203
|
+
oauthApplications, // OAuth apps registered by organizations (Zapier, Make, etc.)
|
|
204
|
+
oauthAuthorizationCodes, // Temporary authorization codes (10 min lifetime)
|
|
205
|
+
oauthRefreshTokens, // Long-lived refresh tokens (30 days)
|
|
206
|
+
oauthRevokedTokens, // Revocation list for access tokens
|
|
207
|
+
oauthTokenUsage, // Token usage analytics (optional, for monitoring)
|
|
208
|
+
|
|
209
|
+
// 🚦 RATE LIMITING: Token bucket rate limiting for API abuse prevention
|
|
210
|
+
...rateLimitSchemas, // rateLimitBuckets, rateLimitViolations
|
|
211
|
+
|
|
212
|
+
// 🛡️ SECURITY: Anomaly detection and security event monitoring
|
|
213
|
+
...securitySchemas, // securityEvents, usageMetadata, failedAuthAttempts
|
|
214
|
+
|
|
215
|
+
// 📊 GROWTH TRACKING: Launch metrics and KPI tracking
|
|
216
|
+
dailyGrowthMetrics, // Daily metrics (automated + manual)
|
|
217
|
+
signupEvents, // Signup event tracking
|
|
218
|
+
weeklyScorecard, // Weekly scorecard snapshots
|
|
219
|
+
salesNotifications, // Sales team notifications
|
|
220
|
+
celebrationMilestones, // Milestone achievements
|
|
221
|
+
|
|
222
|
+
// 📧 EMAIL QUEUE: Email delivery tracking
|
|
223
|
+
emailQueue, // Outbound email queue
|
|
224
|
+
|
|
225
|
+
// 🎁 BENEFITS PLATFORM: Benefits & Commissions tracking
|
|
226
|
+
benefitClaims, // Benefit claim workflow tracking
|
|
227
|
+
commissionPayouts, // Commission payout workflow tracking
|
|
228
|
+
memberWallets, // Crypto wallet links for members
|
|
229
|
+
platformFees, // Platform fee tracking for billing
|
|
230
|
+
|
|
231
|
+
// ❌ OLD TRANSLATIONS - Replaced by ontology
|
|
232
|
+
// systemTranslations,
|
|
233
|
+
// appTranslations,
|
|
234
|
+
// contentTranslations,
|
|
235
|
+
// translationNamespaces,
|
|
236
|
+
// translationKeys,
|
|
237
|
+
// supportedLocales,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* ADDING A NEW APP?
|
|
242
|
+
*
|
|
243
|
+
* 1. Define your table in schemas/appDataSchemas.ts
|
|
244
|
+
* 2. Import it above: import { yourapp } from "./schemas/appDataSchemas";
|
|
245
|
+
* 3. Add it to the schema export under "APPS" section
|
|
246
|
+
* 4. Register it in convex/apps.ts DEFAULT_APPS
|
|
247
|
+
* 5. Create convex/yourapp.ts for queries/mutations
|
|
248
|
+
*
|
|
249
|
+
* See schemas/README.md for complete guide
|
|
250
|
+
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@l4yercak3/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Icing on the L4yercak3 - The sweet finishing touch for your Layer Cake integration",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -37,11 +37,14 @@
|
|
|
37
37
|
"cli",
|
|
38
38
|
"backend",
|
|
39
39
|
"platform",
|
|
40
|
-
"integration"
|
|
40
|
+
"integration",
|
|
41
|
+
"mcp",
|
|
42
|
+
"claude-code"
|
|
41
43
|
],
|
|
42
44
|
"author": "",
|
|
43
45
|
"license": "MIT",
|
|
44
46
|
"dependencies": {
|
|
47
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
45
48
|
"chalk": "^4.1.2",
|
|
46
49
|
"commander": "^14.0.2",
|
|
47
50
|
"figlet": "^1.7.0",
|
package/src/commands/login.js
CHANGED
|
@@ -197,12 +197,6 @@ async function handleLogin() {
|
|
|
197
197
|
configManager.saveSession(session);
|
|
198
198
|
|
|
199
199
|
// Validate session with backend
|
|
200
|
-
// Add delay to allow Convex to propagate the session (debugging timing issues)
|
|
201
|
-
if (process.env.L4YERCAK3_DEBUG) {
|
|
202
|
-
console.log('[DEBUG] Waiting 2s for session propagation...');
|
|
203
|
-
}
|
|
204
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
205
|
-
|
|
206
200
|
try {
|
|
207
201
|
const userInfo = await backendClient.validateSession();
|
|
208
202
|
if (userInfo) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Command
|
|
3
|
+
*
|
|
4
|
+
* Starts the L4YERCAK3 MCP server for Claude Code integration.
|
|
5
|
+
* The server exposes L4YERCAK3 capabilities as MCP tools.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* l4yercak3 mcp-server
|
|
9
|
+
*
|
|
10
|
+
* To add to Claude Code:
|
|
11
|
+
* claude mcp add l4yercak3 -- npx l4yercak3 mcp-server
|
|
12
|
+
*
|
|
13
|
+
* @module commands/mcp-server
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const { startServer } = require('../mcp/server');
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
command: 'mcp-server',
|
|
20
|
+
description: 'Start the MCP server for Claude Code integration',
|
|
21
|
+
handler: async () => {
|
|
22
|
+
// Note: All output goes to stderr because stdout is used for MCP protocol
|
|
23
|
+
// console.error is used intentionally here
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
await startServer();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error(`[L4YERCAK3 MCP] Failed to start server: ${error.message}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
package/src/commands/spread.js
CHANGED
|
@@ -220,9 +220,9 @@ async function handleSpread() {
|
|
|
220
220
|
console.log(chalk.gray(' Could not check existing keys, attempting to generate...'));
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
if (existingKeys && existingKeys.
|
|
224
|
-
// At API key limit - inform user and exit
|
|
225
|
-
console.log(chalk.yellow(` ⚠️ You've reached your API key limit (${existingKeys.keys
|
|
223
|
+
if (existingKeys && existingKeys.canCreateMore === false) {
|
|
224
|
+
// At API key limit - inform user and exit (only if explicitly false, not undefined)
|
|
225
|
+
console.log(chalk.yellow(` ⚠️ You've reached your API key limit (${existingKeys.keys?.length || 0} key(s))`));
|
|
226
226
|
if (existingKeys.limitDescription) {
|
|
227
227
|
console.log(chalk.gray(` ${existingKeys.limitDescription}`));
|
|
228
228
|
}
|
|
@@ -230,8 +230,61 @@ async function handleSpread() {
|
|
|
230
230
|
console.log(chalk.gray(' • Delete an existing key at https://app.l4yercak3.com?openWindow=integrations&panel=api-keys'));
|
|
231
231
|
console.log(chalk.gray(' • Upgrade your plan at https://app.l4yercak3.com?openWindow=store\n'));
|
|
232
232
|
process.exit(0);
|
|
233
|
+
} else if (existingKeys && existingKeys.keys && existingKeys.keys.length > 0) {
|
|
234
|
+
// Has existing keys - offer to reuse or generate new
|
|
235
|
+
const activeKeys = existingKeys.keys.filter(k => k.status === 'active');
|
|
236
|
+
|
|
237
|
+
if (activeKeys.length > 0) {
|
|
238
|
+
console.log(chalk.gray(` Found ${activeKeys.length} active API key(s)\n`));
|
|
239
|
+
|
|
240
|
+
const keyChoices = activeKeys.map(key => ({
|
|
241
|
+
name: `${key.name} (${key.keyPreview})`,
|
|
242
|
+
value: key.id,
|
|
243
|
+
}));
|
|
244
|
+
keyChoices.push({ name: '➕ Generate a new API key', value: '__generate__' });
|
|
245
|
+
|
|
246
|
+
const { keyChoice } = await inquirer.prompt([
|
|
247
|
+
{
|
|
248
|
+
type: 'list',
|
|
249
|
+
name: 'keyChoice',
|
|
250
|
+
message: 'Which API key would you like to use?',
|
|
251
|
+
choices: keyChoices,
|
|
252
|
+
},
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
if (keyChoice === '__generate__') {
|
|
256
|
+
apiKey = await generateNewApiKey(organizationId);
|
|
257
|
+
} else {
|
|
258
|
+
// User selected existing key - we only have the preview, not the full key
|
|
259
|
+
// They need to use the key they have stored or get it from dashboard
|
|
260
|
+
const selectedKey = activeKeys.find(k => k.id === keyChoice);
|
|
261
|
+
console.log(chalk.yellow(`\n ⚠️ For security, we can't retrieve the full API key.`));
|
|
262
|
+
console.log(chalk.gray(` You selected: ${selectedKey.name} (${selectedKey.keyPreview})`));
|
|
263
|
+
console.log(chalk.gray(` If you have this key stored, enter it below.`));
|
|
264
|
+
console.log(chalk.gray(` Otherwise, generate a new key or find it at:`));
|
|
265
|
+
console.log(chalk.gray(` https://app.l4yercak3.com?openWindow=integrations&panel=api-keys\n`));
|
|
266
|
+
|
|
267
|
+
const { existingKey } = await inquirer.prompt([
|
|
268
|
+
{
|
|
269
|
+
type: 'input',
|
|
270
|
+
name: 'existingKey',
|
|
271
|
+
message: 'Enter your API key (or press Enter to generate new):',
|
|
272
|
+
},
|
|
273
|
+
]);
|
|
274
|
+
|
|
275
|
+
if (existingKey.trim()) {
|
|
276
|
+
apiKey = existingKey.trim();
|
|
277
|
+
console.log(chalk.green(` ✅ Using existing API key\n`));
|
|
278
|
+
} else {
|
|
279
|
+
apiKey = await generateNewApiKey(organizationId);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
// Only revoked keys exist - generate new
|
|
284
|
+
apiKey = await generateNewApiKey(organizationId);
|
|
285
|
+
}
|
|
233
286
|
} else {
|
|
234
|
-
//
|
|
287
|
+
// No existing keys - generate one
|
|
235
288
|
apiKey = await generateNewApiKey(organizationId);
|
|
236
289
|
}
|
|
237
290
|
} catch (error) {
|