@l4yercak3/cli 1.0.6 → 1.1.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.
@@ -0,0 +1,390 @@
1
+ # Connected Applications - Schema Specification
2
+
3
+ ## Overview
4
+
5
+ The `connected_application` object type represents an external application connected to L4YERCAK3 via CLI or boilerplate deployment. It's the **parent container** that ties together API connections, model mappings, deployments, and published pages.
6
+
7
+ ---
8
+
9
+ ## Object Type: `connected_application`
10
+
11
+ ### Base Structure (in `objects` table)
12
+
13
+ ```typescript
14
+ {
15
+ _id: Id<"objects">,
16
+ organizationId: Id<"organizations">,
17
+ type: "connected_application",
18
+ subtype: "cli" | "boilerplate" | "manual",
19
+ name: string, // "HaffNet Medical Platform"
20
+ description: string, // "CME course registration platform"
21
+ status: "active" | "paused" | "disconnected" | "archived",
22
+ customProperties: ConnectedApplicationProperties,
23
+ createdBy: Id<"users">,
24
+ createdAt: number,
25
+ updatedAt: number,
26
+ }
27
+ ```
28
+
29
+ ### Custom Properties
30
+
31
+ ```typescript
32
+ interface ConnectedApplicationProperties {
33
+ // ========================================
34
+ // SOURCE: Where the app comes from
35
+ // ========================================
36
+ source: {
37
+ type: "cli" | "boilerplate" | "manual";
38
+
39
+ // CLI-specific
40
+ projectPathHash?: string; // SHA256 of local project path (for identification)
41
+ cliVersion?: string; // CLI version that registered this app
42
+
43
+ // Boilerplate-specific
44
+ boilerplateId?: string; // "freelancer-portal", "event-landing", etc.
45
+ boilerplateVersion?: string; // Version of boilerplate used
46
+
47
+ // Framework detection
48
+ framework: string; // "nextjs", "remix", "astro", etc.
49
+ frameworkVersion?: string; // "16.0.0"
50
+ hasTypeScript: boolean;
51
+ routerType?: "app" | "pages"; // For Next.js
52
+ };
53
+
54
+ // ========================================
55
+ // CONNECTION: How app talks to L4YERCAK3
56
+ // ========================================
57
+ connection: {
58
+ apiKeyId?: Id<"apiKeys">; // Reference to API key used
59
+ apiKeyPrefix?: string; // "sk_live_xxx..." for display
60
+ backendUrl: string; // "https://app.l4yercak3.com"
61
+
62
+ // Features enabled for this app
63
+ features: Array<
64
+ | "crm"
65
+ | "events"
66
+ | "products"
67
+ | "checkout"
68
+ | "tickets"
69
+ | "invoicing"
70
+ | "forms"
71
+ | "projects"
72
+ | "workflows"
73
+ | "templates"
74
+ | "ai"
75
+ >;
76
+
77
+ // Dual-database pattern (like HaffNet)
78
+ hasFrontendDatabase: boolean;
79
+ frontendDatabaseType?: "convex" | "prisma" | "drizzle" | "other";
80
+ frontendDatabaseUrl?: string; // For reference only, not stored
81
+ };
82
+
83
+ // ========================================
84
+ // MODEL MAPPINGS: How app models map to L4YERCAK3
85
+ // ========================================
86
+ modelMappings: Array<{
87
+ localModel: string; // "User", "Company", "Event"
88
+ layerCakeType: string; // "contact", "crm_organization", "event"
89
+ syncDirection: "push" | "pull" | "bidirectional" | "none";
90
+ confidence: number; // 0-100, from CLI detection
91
+ isAutoDetected: boolean; // true if CLI detected, false if manual
92
+ fieldMappings: Array<{
93
+ localField: string; // "email", "firstName"
94
+ layerCakeField: string; // "email", "customProperties.firstName"
95
+ transform?: string; // Optional transform expression
96
+ }>;
97
+ }>;
98
+
99
+ // ========================================
100
+ // DEPLOYMENT: Where app is deployed
101
+ // ========================================
102
+ deployment: {
103
+ // Links to deployment system (Phase 1-2 work)
104
+ configurationId?: Id<"objects">; // deployment_configuration object
105
+
106
+ // Quick access URLs
107
+ productionUrl?: string; // "https://haffnet.vercel.app"
108
+ stagingUrl?: string; // "https://staging.haffnet.vercel.app"
109
+ localDevUrl?: string; // "http://localhost:3000"
110
+
111
+ // GitHub repo
112
+ githubRepo?: string; // "owner/repo"
113
+ githubBranch?: string; // "main"
114
+
115
+ // Deployment status
116
+ deploymentStatus: "not_deployed" | "deploying" | "deployed" | "failed";
117
+ lastDeployedAt?: number;
118
+ };
119
+
120
+ // ========================================
121
+ // PAGES: Published pages owned by this app
122
+ // ========================================
123
+ pageIds: Array<Id<"objects">>; // References to published_page objects
124
+
125
+ // ========================================
126
+ // SYNC STATUS: Data synchronization state
127
+ // ========================================
128
+ sync: {
129
+ enabled: boolean;
130
+ lastSyncAt?: number;
131
+ lastSyncDirection?: "push" | "pull" | "bidirectional";
132
+ lastSyncStatus?: "success" | "partial" | "failed";
133
+
134
+ // Per-model sync stats
135
+ stats: Record<string, { // Keyed by layerCakeType
136
+ totalRecords: number;
137
+ syncedRecords: number;
138
+ lastSyncAt: number;
139
+ errors: number;
140
+ lastError?: string;
141
+ }>;
142
+ };
143
+
144
+ // ========================================
145
+ // CLI METADATA
146
+ // ========================================
147
+ cli: {
148
+ registeredAt: number; // When CLI first registered this app
149
+ registeredBy?: Id<"users">; // User who ran CLI
150
+ lastActivityAt: number; // Last CLI command for this app
151
+ cliSessionId?: string; // Current/last CLI session
152
+
153
+ // Generated files tracking
154
+ generatedFiles: Array<{
155
+ path: string; // "src/lib/layercake.ts"
156
+ type: string; // "api-client", "types", "env"
157
+ generatedAt: number;
158
+ hash?: string; // For change detection
159
+ }>;
160
+ };
161
+ }
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Object Links
167
+
168
+ ### Application → API Key
169
+ ```typescript
170
+ {
171
+ fromObjectId: applicationId,
172
+ toObjectId: apiKeyId, // In apiKeys table, not objects
173
+ linkType: "uses_api_key",
174
+ organizationId,
175
+ properties: {
176
+ linkedAt: number,
177
+ }
178
+ }
179
+ ```
180
+
181
+ ### Application → Published Pages
182
+ ```typescript
183
+ {
184
+ fromObjectId: applicationId,
185
+ toObjectId: publishedPageId,
186
+ linkType: "owns_page",
187
+ organizationId,
188
+ properties: {
189
+ addedAt: number,
190
+ }
191
+ }
192
+ ```
193
+
194
+ ### Application → Deployment Configuration
195
+ ```typescript
196
+ {
197
+ fromObjectId: applicationId,
198
+ toObjectId: deploymentConfigId,
199
+ linkType: "deploys_via",
200
+ organizationId,
201
+ properties: {
202
+ environment: "production" | "staging",
203
+ }
204
+ }
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Convex Functions Required
210
+
211
+ ### Mutations
212
+
213
+ ```typescript
214
+ // Register new application (called by CLI)
215
+ registerConnectedApplication(args: {
216
+ token: string, // CLI session token
217
+ organizationId: Id<"organizations">,
218
+ name: string,
219
+ source: SourceConfig,
220
+ connection: ConnectionConfig,
221
+ modelMappings?: ModelMapping[],
222
+ deployment?: DeploymentConfig,
223
+ }): Promise<{
224
+ applicationId: Id<"objects">,
225
+ apiKeyId?: Id<"apiKeys">, // If new key was generated
226
+ }>
227
+
228
+ // Update application (called by CLI on re-run)
229
+ updateConnectedApplication(args: {
230
+ token: string,
231
+ applicationId: Id<"objects">,
232
+ updates: Partial<ConnectedApplicationProperties>,
233
+ }): Promise<void>
234
+
235
+ // Update sync status (called after sync operations)
236
+ updateApplicationSyncStatus(args: {
237
+ token: string,
238
+ applicationId: Id<"objects">,
239
+ syncResult: SyncResult,
240
+ }): Promise<void>
241
+
242
+ // Pause/resume application
243
+ setApplicationStatus(args: {
244
+ sessionId: string,
245
+ applicationId: Id<"objects">,
246
+ status: "active" | "paused",
247
+ }): Promise<void>
248
+
249
+ // Disconnect application (soft delete)
250
+ disconnectApplication(args: {
251
+ sessionId: string,
252
+ applicationId: Id<"objects">,
253
+ }): Promise<void>
254
+
255
+ // Link page to application
256
+ linkPageToApplication(args: {
257
+ sessionId: string,
258
+ applicationId: Id<"objects">,
259
+ pageId: Id<"objects">,
260
+ }): Promise<void>
261
+ ```
262
+
263
+ ### Queries
264
+
265
+ ```typescript
266
+ // List all applications for org (for Web Publishing UI)
267
+ getConnectedApplications(args: {
268
+ sessionId: string,
269
+ organizationId: Id<"organizations">,
270
+ status?: string,
271
+ }): Promise<ConnectedApplication[]>
272
+
273
+ // Get single application with full details
274
+ getConnectedApplication(args: {
275
+ sessionId: string,
276
+ applicationId: Id<"objects">,
277
+ }): Promise<ConnectedApplication | null>
278
+
279
+ // Get application by project path hash (for CLI to find existing)
280
+ getApplicationByPathHash(args: {
281
+ token: string,
282
+ organizationId: Id<"organizations">,
283
+ projectPathHash: string,
284
+ }): Promise<ConnectedApplication | null>
285
+
286
+ // Get applications using specific API key
287
+ getApplicationsByApiKey(args: {
288
+ sessionId: string,
289
+ apiKeyId: Id<"apiKeys">,
290
+ }): Promise<ConnectedApplication[]>
291
+ ```
292
+
293
+ ---
294
+
295
+ ## REST API Endpoints
296
+
297
+ ### For CLI
298
+
299
+ ```
300
+ POST /api/v1/cli/applications - Register application
301
+ GET /api/v1/cli/applications - List applications
302
+ GET /api/v1/cli/applications/:id - Get application
303
+ PATCH /api/v1/cli/applications/:id - Update application
304
+ DELETE /api/v1/cli/applications/:id - Disconnect application
305
+ POST /api/v1/cli/applications/:id/sync - Trigger/report sync
306
+ GET /api/v1/cli/applications/by-path - Find by project path hash
307
+ ```
308
+
309
+ ### Authentication
310
+
311
+ All CLI endpoints use Bearer token authentication:
312
+ ```
313
+ Authorization: Bearer cli_session_xxx
314
+ ```
315
+
316
+ ---
317
+
318
+ ## Web Publishing UI Changes
319
+
320
+ ### New "Applications" Tab
321
+
322
+ Position: First tab (before Pages)
323
+
324
+ **Content:**
325
+ - List of connected applications with:
326
+ - Name & framework icon
327
+ - Status badge (active/paused/disconnected)
328
+ - Features enabled (icons)
329
+ - Last sync time
330
+ - Production URL (if deployed)
331
+ - Quick actions: View, Pause, Settings, Disconnect
332
+
333
+ **Empty State:**
334
+ - "No applications connected"
335
+ - "Use the L4YERCAK3 CLI to connect an external app, or deploy a boilerplate"
336
+ - Buttons: "CLI Documentation", "Deploy Boilerplate"
337
+
338
+ ### Application Detail View
339
+
340
+ When clicking an application:
341
+ - **Overview Tab**: Status, URLs, features, last activity
342
+ - **Model Mappings Tab**: Visual mapping table
343
+ - **Sync Tab**: Sync status, stats, manual sync button
344
+ - **Pages Tab**: Published pages owned by this app
345
+ - **Settings Tab**: Edit name, features, deployment config
346
+ - **Logs Tab**: Recent CLI activity, sync history
347
+
348
+ ---
349
+
350
+ ## Integration with Existing Systems
351
+
352
+ ### With API Keys (`apiKeys` table)
353
+ - Application references API key via `connection.apiKeyId`
354
+ - Can query "which apps use this key"
355
+ - Revoking key should warn about connected apps
356
+
357
+ ### With Published Pages (`published_page` objects)
358
+ - Pages can belong to an application via `pageIds` array
359
+ - Page detail shows parent application (if any)
360
+ - Deleting app can optionally delete pages
361
+
362
+ ### With Deployment System (`deployment_configuration` objects)
363
+ - Application links to deployment config
364
+ - Shares GitHub/Vercel settings
365
+ - Deployment status synced
366
+
367
+ ### With CLI Sessions (`cliSessions` table)
368
+ - Application tracks which CLI session registered it
369
+ - Last activity updates on CLI commands
370
+ - Session expiry doesn't disconnect app
371
+
372
+ ---
373
+
374
+ ## Migration Strategy
375
+
376
+ 1. **No existing data to migrate** - This is a new object type
377
+ 2. **Backward compatible** - Existing pages/deployments continue to work
378
+ 3. **Optional adoption** - Apps without CLI still function
379
+ 4. **Gradual rollout** - UI can show "Applications" tab only when apps exist
380
+
381
+ ---
382
+
383
+ ## Success Criteria
384
+
385
+ - [ ] CLI can register application and see it in Web Publishing
386
+ - [ ] Web Publishing shows all connected applications
387
+ - [ ] Model mappings visible and editable
388
+ - [ ] Sync status accurately reflects last CLI sync
389
+ - [ ] Disconnecting app doesn't break existing pages
390
+ - [ ] API key relationship bidirectional (key → apps, app → key)