@equilateral_ai/mindmeld 3.5.2 → 4.0.1

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.
Files changed (140) hide show
  1. package/hooks/session-end.js +25 -0
  2. package/hooks/session-start.js +363 -83
  3. package/hooks/session-watcher.js +585 -0
  4. package/package.json +19 -13
  5. package/scripts/init-project.js +9 -23
  6. package/src/client/dbShim.js +16 -0
  7. package/src/core/AuthManager.js +3 -2
  8. package/src/handlers/helpers/dbOperations.js +9 -46
  9. package/src/index.js +2 -217
  10. package/src/utils/piiMask.js +16 -0
  11. package/scripts/harvest.js +0 -601
  12. package/scripts/inject.js +0 -409
  13. package/scripts/mcp-bridge.js +0 -220
  14. package/scripts/repo-analyzer.js +0 -870
  15. package/src/collaboration/CollaborationPrompt.js +0 -460
  16. package/src/core/AlertEngine.js +0 -813
  17. package/src/core/AlertNotifier.js +0 -363
  18. package/src/core/CorrelationAnalyzer.js +0 -931
  19. package/src/core/CrossReferenceEngine.js +0 -624
  20. package/src/core/CurationEngine.js +0 -688
  21. package/src/core/DeprecationScheduler.js +0 -183
  22. package/src/core/LoadBearingDetector.js +0 -242
  23. package/src/core/NotificationService.js +0 -1032
  24. package/src/core/RapportOrchestrator.js +0 -632
  25. package/src/core/RelevanceDetector.js +0 -694
  26. package/src/core/StandardLifecycle.js +0 -244
  27. package/src/core/StandardsIngestion.js +0 -991
  28. package/src/core/TeamLoadBearingDetector.js +0 -431
  29. package/src/core/parsers/adrParser.js +0 -479
  30. package/src/core/parsers/cursorRulesParser.js +0 -564
  31. package/src/core/parsers/eslintParser.js +0 -439
  32. package/src/database/dbOperations.js +0 -105
  33. package/src/handlers/activity/activityGetMe.js +0 -98
  34. package/src/handlers/activity/activityGetTeam.js +0 -175
  35. package/src/handlers/admin/adminSetup.js +0 -216
  36. package/src/handlers/alerts/alertsAcknowledge.js +0 -92
  37. package/src/handlers/alerts/alertsGet.js +0 -250
  38. package/src/handlers/analytics/activitySummaryGet.js +0 -234
  39. package/src/handlers/analytics/coachingGet.js +0 -361
  40. package/src/handlers/analytics/convergenceGet.js +0 -236
  41. package/src/handlers/analytics/developerScoreGet.js +0 -137
  42. package/src/handlers/collaborators/collaboratorAdd.js +0 -200
  43. package/src/handlers/collaborators/collaboratorInvite.js +0 -219
  44. package/src/handlers/collaborators/collaboratorList.js +0 -82
  45. package/src/handlers/collaborators/collaboratorRemove.js +0 -128
  46. package/src/handlers/collaborators/inviteAccept.js +0 -122
  47. package/src/handlers/company/companyUsersDelete.js +0 -141
  48. package/src/handlers/company/companyUsersGet.js +0 -90
  49. package/src/handlers/company/companyUsersPost.js +0 -267
  50. package/src/handlers/company/companyUsersPut.js +0 -76
  51. package/src/handlers/context/contextGet.js +0 -57
  52. package/src/handlers/context/invariantsGet.js +0 -74
  53. package/src/handlers/context/loopsGet.js +0 -82
  54. package/src/handlers/context/notesCreate.js +0 -74
  55. package/src/handlers/context/purposeGet.js +0 -78
  56. package/src/handlers/correlations/correlationsDeveloperGet.js +0 -227
  57. package/src/handlers/correlations/correlationsGet.js +0 -93
  58. package/src/handlers/correlations/correlationsProjectGet.js +0 -153
  59. package/src/handlers/enterprise/controlTowerGet.js +0 -224
  60. package/src/handlers/enterprise/enterpriseAuditGet.js +0 -108
  61. package/src/handlers/enterprise/enterpriseContributorsGet.js +0 -85
  62. package/src/handlers/enterprise/enterpriseKnowledgeCategoriesGet.js +0 -53
  63. package/src/handlers/enterprise/enterpriseKnowledgeCreate.js +0 -77
  64. package/src/handlers/enterprise/enterpriseKnowledgeDelete.js +0 -71
  65. package/src/handlers/enterprise/enterpriseKnowledgeGet.js +0 -87
  66. package/src/handlers/enterprise/enterpriseKnowledgeUpdate.js +0 -122
  67. package/src/handlers/enterprise/enterpriseOnboardingComplete.js +0 -77
  68. package/src/handlers/enterprise/enterpriseOnboardingInvite.js +0 -138
  69. package/src/handlers/enterprise/enterpriseOnboardingSetup.js +0 -128
  70. package/src/handlers/enterprise/enterpriseOnboardingStatus.js +0 -88
  71. package/src/handlers/github/githubConnectionStatus.js +0 -49
  72. package/src/handlers/github/githubDiscoverPatterns.js +0 -621
  73. package/src/handlers/github/githubOAuthCallback.js +0 -178
  74. package/src/handlers/github/githubOAuthStart.js +0 -59
  75. package/src/handlers/github/githubPatternsReview.js +0 -76
  76. package/src/handlers/github/githubReposList.js +0 -105
  77. package/src/handlers/health/healthGet.js +0 -55
  78. package/src/handlers/helpers/auditLogger.js +0 -201
  79. package/src/handlers/helpers/checkSuperAdmin.js +0 -84
  80. package/src/handlers/helpers/decisionFrames.js +0 -29
  81. package/src/handlers/helpers/errorHandler.js +0 -49
  82. package/src/handlers/helpers/index.js +0 -138
  83. package/src/handlers/helpers/lambdaWrapper.js +0 -60
  84. package/src/handlers/helpers/mindmeldMcpCore.js +0 -1103
  85. package/src/handlers/helpers/predictiveCache.js +0 -51
  86. package/src/handlers/helpers/projectAccess.js +0 -88
  87. package/src/handlers/helpers/responseUtil.js +0 -55
  88. package/src/handlers/helpers/subscriptionTiers.js +0 -1168
  89. package/src/handlers/mcp/mcpHandler.js +0 -569
  90. package/src/handlers/mcp/mindmeldMcpHandler.js +0 -124
  91. package/src/handlers/mcp/mindmeldMcpStreamHandler.js +0 -342
  92. package/src/handlers/notifications/getPreferences.js +0 -84
  93. package/src/handlers/notifications/sendNotification.js +0 -170
  94. package/src/handlers/notifications/updatePreferences.js +0 -316
  95. package/src/handlers/patterns/patternEvaluatePromotionPost.js +0 -173
  96. package/src/handlers/patterns/patternUsagePost.js +0 -182
  97. package/src/handlers/patterns/patternViolationPost.js +0 -185
  98. package/src/handlers/projects/projectCreate.js +0 -248
  99. package/src/handlers/projects/projectDelete.js +0 -82
  100. package/src/handlers/projects/projectGet.js +0 -95
  101. package/src/handlers/projects/projectUpdate.js +0 -117
  102. package/src/handlers/reports/aiLeverage.js +0 -210
  103. package/src/handlers/reports/engineeringInvestment.js +0 -132
  104. package/src/handlers/reports/riskForecast.js +0 -206
  105. package/src/handlers/reports/standardsRoi.js +0 -254
  106. package/src/handlers/scheduled/analyzeCorrelations.js +0 -178
  107. package/src/handlers/scheduled/analyzeGitHistory.js +0 -510
  108. package/src/handlers/scheduled/generateAlerts.js +0 -135
  109. package/src/handlers/scheduled/maturityUpdateJob.js +0 -166
  110. package/src/handlers/scheduled/refreshActivity.js +0 -21
  111. package/src/handlers/scheduled/scanCompliance.js +0 -334
  112. package/src/handlers/sessions/sessionEndPost.js +0 -180
  113. package/src/handlers/sessions/sessionStandardsPost.js +0 -171
  114. package/src/handlers/standards/catalogGet.js +0 -185
  115. package/src/handlers/standards/catalogSync.js +0 -120
  116. package/src/handlers/standards/discoveriesGet.js +0 -89
  117. package/src/handlers/standards/projectStandardsGet.js +0 -129
  118. package/src/handlers/standards/projectStandardsPut.js +0 -151
  119. package/src/handlers/standards/standardsAuditGet.js +0 -65
  120. package/src/handlers/standards/standardsParseUpload.js +0 -149
  121. package/src/handlers/standards/standardsRelevantPost.js +0 -405
  122. package/src/handlers/standards/standardsTransition.js +0 -161
  123. package/src/handlers/stripe/addonManagePost.js +0 -240
  124. package/src/handlers/stripe/billingPortalPost.js +0 -93
  125. package/src/handlers/stripe/enterpriseCheckoutPost.js +0 -272
  126. package/src/handlers/stripe/seatsUpdatePost.js +0 -185
  127. package/src/handlers/stripe/subscriptionCancelDelete.js +0 -169
  128. package/src/handlers/stripe/subscriptionCreatePost.js +0 -221
  129. package/src/handlers/stripe/subscriptionUpdatePut.js +0 -163
  130. package/src/handlers/stripe/webhookPost.js +0 -482
  131. package/src/handlers/user/apiTokenCreate.js +0 -71
  132. package/src/handlers/user/apiTokenList.js +0 -64
  133. package/src/handlers/user/userSplashAck.js +0 -91
  134. package/src/handlers/user/userSplashGet.js +0 -211
  135. package/src/handlers/users/cognitoPostConfirmation.js +0 -186
  136. package/src/handlers/users/cognitoPreSignUp.js +0 -114
  137. package/src/handlers/users/userEntitlementsGet.js +0 -89
  138. package/src/handlers/users/userGet.js +0 -118
  139. package/src/handlers/users/userProfilePut.js +0 -77
  140. package/src/handlers/webhooks/githubWebhook.js +0 -215
@@ -1,171 +0,0 @@
1
- /**
2
- * Session Standards Handler
3
- * Records which standards were shown during a Claude Code session
4
- *
5
- * POST /api/sessions/standards
6
- * Body: { session_id, standards[], project_id?, user_id? }
7
- *
8
- * Called by: session-start.js hook (recordStandardsShown method)
9
- * Fire-and-forget - should not block session start
10
- */
11
-
12
- const { wrapHandler, executeQuery, createSuccessResponse, createErrorResponse, handleError } = require('./helpers');
13
-
14
- /**
15
- * Record standards shown during session
16
- * Creates session record if needed, then records standards
17
- */
18
- async function recordSessionStandards({ body: requestBody = {}, requestContext }) {
19
- try {
20
- const Request_ID = requestContext?.requestId || 'unknown';
21
-
22
- const {
23
- session_id,
24
- standards = [],
25
- project_id,
26
- user_id
27
- } = requestBody;
28
-
29
- // Validate required fields
30
- if (!session_id) {
31
- return createErrorResponse(400, 'session_id is required');
32
- }
33
-
34
- if (!standards || standards.length === 0) {
35
- // Not an error - just nothing to record
36
- return createSuccessResponse(
37
- { Records: [], recorded: 0 },
38
- 'No standards to record',
39
- { Request_ID, Timestamp: new Date().toISOString() }
40
- );
41
- }
42
-
43
- // Try to ensure session exists (upsert with minimal data)
44
- // If project doesn't exist, auto-create it to prevent silent session loss
45
- if (project_id && user_id) {
46
- const sessionUpsertQuery = `
47
- INSERT INTO rapport.sessions (
48
- session_id,
49
- project_id,
50
- email_address,
51
- started_at,
52
- session_data
53
- ) VALUES (
54
- $1, $2, $3, NOW(), '{}'::jsonb
55
- )
56
- ON CONFLICT (session_id) DO NOTHING
57
- `;
58
-
59
- try {
60
- await executeQuery(sessionUpsertQuery, [session_id, project_id, user_id]);
61
- } catch (sessionError) {
62
- // FK constraint on project_id — auto-create the project and retry
63
- if (sessionError.code === '23503' && sessionError.constraint && sessionError.constraint.includes('project_id')) {
64
- console.log(`[sessionStandardsPost] Project ${project_id} not found, auto-creating`);
65
- try {
66
- // Look up user's company_id
67
- const entResult = await executeQuery(
68
- `SELECT company_id FROM rapport.user_entitlements WHERE email_address = $1 LIMIT 1`,
69
- [user_id]
70
- );
71
- if (entResult.rowCount > 0) {
72
- const company_id = entResult.rows[0].company_id;
73
- // Derive a readable project name from the project_id
74
- // e.g. prj_pareidolia_main_1770727596802 → pareidolia main
75
- const projectName = project_id
76
- .replace(/^prj_/, '')
77
- .replace(/_\d+$/, '')
78
- .replace(/_/g, ' ');
79
-
80
- await executeQuery(`
81
- INSERT INTO rapport.projects (project_id, company_id, project_name, private)
82
- VALUES ($1, $2, $3, false)
83
- ON CONFLICT (project_id) DO NOTHING
84
- `, [project_id, company_id, projectName]);
85
-
86
- // Retry session upsert
87
- await executeQuery(sessionUpsertQuery, [session_id, project_id, user_id]);
88
- console.log(`[sessionStandardsPost] Auto-created project ${project_id} under ${company_id}`);
89
- } else {
90
- console.error(`[sessionStandardsPost] No entitlement found for ${user_id}, cannot auto-create project`);
91
- }
92
- } catch (autoCreateError) {
93
- console.error('[sessionStandardsPost] Auto-create project failed:', autoCreateError.message);
94
- }
95
- } else {
96
- console.error('[sessionStandardsPost] Session upsert failed:', sessionError.message);
97
- }
98
- }
99
- }
100
-
101
- // Record each standard shown
102
- const recordedStandards = [];
103
- let errors = 0;
104
-
105
- for (const standard of standards) {
106
- const standardId = standard.pattern_id || standard.element;
107
- const standardName = standard.title || standard.element || standardId;
108
- const relevanceScore = standard.relevance_score || standard.score || 0;
109
-
110
- if (!standardId) {
111
- errors++;
112
- continue;
113
- }
114
-
115
- const insertQuery = `
116
- INSERT INTO rapport.session_standards (
117
- session_id,
118
- standard_id,
119
- standard_name,
120
- relevance_score,
121
- created_at
122
- ) VALUES (
123
- $1, $2, $3, $4, NOW()
124
- )
125
- ON CONFLICT (session_id, standard_id) DO UPDATE SET
126
- relevance_score = EXCLUDED.relevance_score,
127
- created_at = NOW()
128
- RETURNING id
129
- `;
130
-
131
- try {
132
- const result = await executeQuery(insertQuery, [
133
- session_id,
134
- standardId,
135
- standardName,
136
- relevanceScore
137
- ]);
138
-
139
- recordedStandards.push({
140
- id: result.rows[0]?.id,
141
- standard_id: standardId,
142
- relevance_score: relevanceScore
143
- });
144
- } catch (insertError) {
145
- // Standard might not exist or FK constraint failed
146
- console.error(`[sessionStandardsPost] Failed to record standard ${standardId}:`, insertError.message);
147
- errors++;
148
- }
149
- }
150
-
151
- return createSuccessResponse(
152
- {
153
- Records: recordedStandards,
154
- recorded: recordedStandards.length,
155
- errors: errors
156
- },
157
- `Recorded ${recordedStandards.length} standard(s)`,
158
- {
159
- Total_Records: recordedStandards.length,
160
- Request_ID,
161
- Timestamp: new Date().toISOString()
162
- }
163
- );
164
-
165
- } catch (error) {
166
- console.error('Handler Error:', error);
167
- return handleError(error);
168
- }
169
- }
170
-
171
- exports.handler = wrapHandler(recordSessionStandards);
@@ -1,185 +0,0 @@
1
- /**
2
- * Standards Catalog Get Handler
3
- * Returns the standards catalog manifest based on subscription tier
4
- *
5
- * GET /api/standards/catalog
6
- * Auth: Cognito JWT required
7
- * Query params:
8
- * - catalog_id: Override catalog selection
9
- * - tech_stack: Comma-separated list of detected technologies for recommendations
10
- *
11
- * Enterprise tier: Full proprietary standards (equilateral-v1)
12
- * Other tiers: Open standards only (equilateral-open-v1)
13
- */
14
-
15
- const { wrapHandler, executeQuery, createSuccessResponse, createErrorResponse } = require('./helpers');
16
-
17
- // Enterprise tiers that get full proprietary standards
18
- const ENTERPRISE_TIERS = ['enterprise', 'enterprise_private', 'enterprise_team'];
19
-
20
- // Tech stack to category recommendations mapping
21
- const TECH_TO_CATEGORIES = {
22
- // Languages/Frameworks
23
- 'react': ['frontend-development'],
24
- 'vue': ['frontend-development'],
25
- 'angular': ['frontend-development'],
26
- 'typescript': ['frontend-development'],
27
- 'node.js': ['serverless-saas-aws'],
28
- 'nodejs': ['serverless-saas-aws'],
29
- 'express': ['serverless-saas-aws'],
30
-
31
- // Infrastructure
32
- 'aws sam': ['serverless-saas-aws'],
33
- 'aws lambda': ['serverless-saas-aws'],
34
- 'lambda': ['serverless-saas-aws'],
35
- 'serverless': ['serverless-saas-aws'],
36
- 'cloudformation': ['serverless-saas-aws'],
37
- 'api gateway': ['serverless-saas-aws'],
38
-
39
- // Databases
40
- 'postgresql': ['database-patterns', 'memory-systems'],
41
- 'postgres': ['database-patterns', 'memory-systems'],
42
- 'dynamodb': ['serverless-saas-aws'],
43
-
44
- // Testing
45
- 'jest': ['frontend-development'],
46
-
47
- // Multi-agent
48
- 'claude': ['multi-agent-orchestration'],
49
- 'openai': ['multi-agent-orchestration'],
50
- 'langchain': ['multi-agent-orchestration'],
51
- };
52
-
53
- /**
54
- * Get recommended categories based on detected tech stack
55
- * @param {string} techStackParam - Comma-separated tech stack string
56
- * @returns {string[]} - Unique list of recommended category keys
57
- */
58
- function getRecommendations(techStackParam) {
59
- if (!techStackParam) return [];
60
-
61
- const technologies = techStackParam.split(',').map(t => t.trim().toLowerCase());
62
- const recommendations = new Set();
63
-
64
- for (const tech of technologies) {
65
- const categories = TECH_TO_CATEGORIES[tech];
66
- if (categories) {
67
- categories.forEach(cat => recommendations.add(cat));
68
- }
69
- }
70
-
71
- return Array.from(recommendations);
72
- }
73
-
74
- async function getCatalog({ requestContext, queryStringParameters }) {
75
- try {
76
- const email = requestContext.authorizer?.claims?.email || requestContext.authorizer?.jwt?.claims?.email;
77
-
78
- if (!email) {
79
- return createErrorResponse(401, 'Authentication required');
80
- }
81
-
82
- // Get user's subscription tier
83
- const userResult = await executeQuery(`
84
- SELECT c.subscription_tier
85
- FROM rapport.users u
86
- LEFT JOIN rapport.clients c ON u.client_id = c.client_id
87
- WHERE u.email_address = $1 AND u.active = true
88
- `, [email]);
89
-
90
- const subscriptionTier = userResult.rows[0]?.subscription_tier || 'free';
91
- const isEnterprise = ENTERPRISE_TIERS.includes(subscriptionTier);
92
-
93
- // Get tech stack recommendations if provided
94
- const techStack = queryStringParameters?.tech_stack;
95
- const recommendations = getRecommendations(techStack);
96
-
97
- // Determine which catalog to return based on tier
98
- // Enterprise gets full catalog, others get open standards
99
- const catalogId = queryStringParameters?.catalog_id ||
100
- (isEnterprise ? 'equilateral-v1' : 'equilateral-open-v1');
101
-
102
- const result = await executeQuery(`
103
- SELECT
104
- catalog_id,
105
- version,
106
- source_url,
107
- updated_at,
108
- total_standards,
109
- total_layers,
110
- categories,
111
- layers,
112
- critical_alerts
113
- FROM rapport.standards_catalog
114
- WHERE catalog_id = $1
115
- `, [catalogId]);
116
-
117
- if (result.rowCount === 0) {
118
- // Fall back to open standards if requested catalog not found
119
- const fallbackResult = await executeQuery(`
120
- SELECT
121
- catalog_id,
122
- version,
123
- source_url,
124
- updated_at,
125
- total_standards,
126
- total_layers,
127
- categories,
128
- layers,
129
- critical_alerts
130
- FROM rapport.standards_catalog
131
- WHERE catalog_id = 'equilateral-open-v1'
132
- `);
133
-
134
- if (fallbackResult.rowCount === 0) {
135
- return createErrorResponse(404, 'Standards catalog not found', {
136
- catalog_id: catalogId,
137
- hint: 'Run migration or sync catalog first'
138
- });
139
- }
140
-
141
- const catalog = fallbackResult.rows[0];
142
- return createSuccessResponse({
143
- catalog_id: catalog.catalog_id,
144
- version: catalog.version,
145
- source_url: catalog.source_url,
146
- updated_at: catalog.updated_at,
147
- subscription_tier: subscriptionTier,
148
- is_enterprise: false,
149
- recommendations,
150
- summary: {
151
- total_standards: catalog.total_standards,
152
- total_layers: catalog.total_layers
153
- },
154
- categories: catalog.categories,
155
- layers: catalog.layers,
156
- critical_alerts: catalog.critical_alerts
157
- }, 'Open standards catalog retrieved');
158
- }
159
-
160
- const catalog = result.rows[0];
161
-
162
- return createSuccessResponse({
163
- catalog_id: catalog.catalog_id,
164
- version: catalog.version,
165
- source_url: catalog.source_url,
166
- updated_at: catalog.updated_at,
167
- subscription_tier: subscriptionTier,
168
- is_enterprise: isEnterprise,
169
- recommendations,
170
- summary: {
171
- total_standards: catalog.total_standards,
172
- total_layers: catalog.total_layers
173
- },
174
- categories: catalog.categories,
175
- layers: catalog.layers,
176
- critical_alerts: catalog.critical_alerts
177
- }, isEnterprise ? 'Full standards catalog retrieved' : 'Open standards catalog retrieved');
178
-
179
- } catch (error) {
180
- console.error('Catalog Get Error:', error);
181
- return createErrorResponse(500, 'Failed to retrieve standards catalog');
182
- }
183
- }
184
-
185
- exports.handler = wrapHandler(getCatalog);
@@ -1,120 +0,0 @@
1
- /**
2
- * Standards Catalog Sync Handler
3
- * Imports/updates the standards catalog from manifest.json
4
- *
5
- * POST /api/standards/catalog/sync
6
- * Body: { manifest } - The manifest.json content
7
- * Auth: Cognito JWT required (admin only)
8
- */
9
-
10
- const { wrapHandler, executeQuery, createSuccessResponse, createErrorResponse } = require('./helpers');
11
-
12
- async function syncCatalog({ body, requestContext }) {
13
- try {
14
- const email = requestContext.authorizer?.claims?.email || requestContext.authorizer?.jwt?.claims?.email;
15
-
16
- if (!email) {
17
- return createErrorResponse(401, 'Authentication required');
18
- }
19
-
20
- const { manifest, catalog_id = 'equilateral-v1', source_url } = body || {};
21
-
22
- if (!manifest) {
23
- return createErrorResponse(400, 'manifest is required');
24
- }
25
-
26
- // Validate manifest structure
27
- if (!manifest.version || !manifest.categories || !manifest.layers) {
28
- return createErrorResponse(400, 'Invalid manifest: missing version, categories, or layers');
29
- }
30
-
31
- // Extract metadata
32
- const totalStandards = manifest.metadata?.totalStandards || 0;
33
- const totalLayers = manifest.layers?.length || 0;
34
-
35
- // Build categories object with descriptions
36
- const categories = {};
37
- if (manifest.categories) {
38
- for (const [key, description] of Object.entries(manifest.categories)) {
39
- categories[key] = {
40
- name: key.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
41
- description: description,
42
- // Count files in this category from layers
43
- standards_count: 0
44
- };
45
- }
46
- }
47
-
48
- // Count standards per category from layers
49
- if (manifest.layers) {
50
- for (const layer of manifest.layers) {
51
- if (layer.files) {
52
- for (const file of layer.files) {
53
- const category = file.split('/')[0];
54
- if (categories[category]) {
55
- categories[category].standards_count++;
56
- }
57
- }
58
- }
59
- }
60
- }
61
-
62
- // Upsert catalog
63
- const result = await executeQuery(`
64
- INSERT INTO rapport.standards_catalog (
65
- catalog_id,
66
- version,
67
- source_url,
68
- manifest,
69
- total_standards,
70
- total_layers,
71
- categories,
72
- layers,
73
- critical_alerts,
74
- updated_at
75
- ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW())
76
- ON CONFLICT (catalog_id) DO UPDATE SET
77
- version = EXCLUDED.version,
78
- source_url = EXCLUDED.source_url,
79
- manifest = EXCLUDED.manifest,
80
- total_standards = EXCLUDED.total_standards,
81
- total_layers = EXCLUDED.total_layers,
82
- categories = EXCLUDED.categories,
83
- layers = EXCLUDED.layers,
84
- critical_alerts = EXCLUDED.critical_alerts,
85
- updated_at = NOW()
86
- RETURNING catalog_id, version, updated_at
87
- `, [
88
- catalog_id,
89
- manifest.version,
90
- source_url || manifest.metadata?.repository || null,
91
- JSON.stringify(manifest),
92
- totalStandards,
93
- totalLayers,
94
- JSON.stringify(categories),
95
- JSON.stringify(manifest.layers),
96
- JSON.stringify(manifest.criticalAlerts || [])
97
- ]);
98
-
99
- const synced = result.rows[0];
100
-
101
- return createSuccessResponse({
102
- catalog_id: synced.catalog_id,
103
- version: synced.version,
104
- updated_at: synced.updated_at,
105
- summary: {
106
- total_standards: totalStandards,
107
- total_layers: totalLayers,
108
- total_categories: Object.keys(categories).length,
109
- critical_alerts: (manifest.criticalAlerts || []).length
110
- },
111
- categories: Object.keys(categories)
112
- }, 'Standards catalog synced successfully');
113
-
114
- } catch (error) {
115
- console.error('Catalog Sync Error:', error);
116
- return createErrorResponse(500, 'Failed to sync standards catalog');
117
- }
118
- }
119
-
120
- exports.handler = wrapHandler(syncCatalog);
@@ -1,89 +0,0 @@
1
- /**
2
- * Discoveries Get Handler
3
- * Returns discovery review queue for a project
4
- *
5
- * GET /api/standards/discoveries?project_id=xxx&status=proposed
6
- * Auth: Cognito JWT required
7
- */
8
-
9
- const { wrapHandler, executeQuery, createSuccessResponse, createErrorResponse, verifyProjectAccess } = require('./helpers');
10
-
11
- async function getDiscoveries({ queryStringParameters, requestContext }) {
12
- try {
13
- const email = requestContext.authorizer?.claims?.email || requestContext.authorizer?.jwt?.claims?.email;
14
-
15
- if (!email) {
16
- return createErrorResponse(401, 'Authentication required');
17
- }
18
-
19
- const projectId = (queryStringParameters || {}).project_id;
20
- const status = (queryStringParameters || {}).status;
21
-
22
- if (!projectId) {
23
- return createErrorResponse(400, 'project_id is required');
24
- }
25
-
26
- // Verify user has access to project (collaborator or company member)
27
- const projectAccess = await verifyProjectAccess(projectId, email);
28
- if (!projectAccess) {
29
- return createErrorResponse(403, 'Access denied to project');
30
- }
31
-
32
- // Build query with optional status filter
33
- let query = `
34
- SELECT
35
- discovery_id,
36
- project_id,
37
- pattern_name,
38
- pattern_description,
39
- confidence,
40
- discovery_type,
41
- status,
42
- evidence,
43
- reason,
44
- reason_code,
45
- created_at,
46
- updated_at
47
- FROM rapport.onboarding_discoveries
48
- WHERE project_id = $1
49
- `;
50
- const params = [projectId];
51
-
52
- if (status) {
53
- query += ` AND status = $2`;
54
- params.push(status);
55
- }
56
-
57
- query += ` ORDER BY confidence DESC, created_at DESC`;
58
-
59
- const result = await executeQuery(query, params);
60
-
61
- // Map DB columns to frontend Discovery interface
62
- const records = result.rows.map(row => ({
63
- id: row.discovery_id,
64
- project_id: row.project_id,
65
- name: row.pattern_name,
66
- description: row.pattern_description || '',
67
- confidence: parseFloat(row.confidence) || 0,
68
- source: 'github',
69
- category: row.discovery_type || 'Architecture',
70
- status: row.status || 'proposed',
71
- rule_text: null,
72
- action_type: null,
73
- evidence: row.evidence || null,
74
- created_at: row.created_at,
75
- updated_at: row.updated_at
76
- }));
77
-
78
- return createSuccessResponse({
79
- records,
80
- total: result.rowCount
81
- }, `Found ${result.rowCount} discoveries`);
82
-
83
- } catch (error) {
84
- console.error('Discoveries Get Error:', error);
85
- return createErrorResponse(500, 'Failed to load discoveries');
86
- }
87
- }
88
-
89
- exports.handler = wrapHandler(getDiscoveries);
@@ -1,129 +0,0 @@
1
- /**
2
- * Project Standards Get Handler
3
- * Returns standards preferences for a project
4
- *
5
- * GET /api/projects/standards?project_id=xxx
6
- * Auth: Cognito JWT required
7
- */
8
-
9
- const { wrapHandler, executeQuery, createSuccessResponse, createErrorResponse, verifyProjectAccess } = require('./helpers');
10
-
11
- async function getProjectStandards({ queryStringParameters, pathParameters, requestContext }) {
12
- try {
13
- const email = requestContext.authorizer?.claims?.email || requestContext.authorizer?.jwt?.claims?.email;
14
-
15
- if (!email) {
16
- return createErrorResponse(401, 'Authentication required');
17
- }
18
-
19
- const projectId = pathParameters?.projectId || (queryStringParameters || {}).project_id;
20
-
21
- if (!projectId) {
22
- return createErrorResponse(400, 'projectId is required');
23
- }
24
-
25
- // Verify user has access to project (collaborator or company member)
26
- const projectAccess = await verifyProjectAccess(projectId, email);
27
- if (!projectAccess) {
28
- return createErrorResponse(403, 'Access denied to project');
29
- }
30
-
31
- const projectName = projectAccess.project_name;
32
-
33
- // Get project standards preferences
34
- const prefsResult = await executeQuery(`
35
- SELECT
36
- ps.catalog_id,
37
- ps.enabled_categories,
38
- ps.standard_overrides,
39
- ps.critical_overrides,
40
- ps.modified_by,
41
- ps.modified_at,
42
- sc.version as catalog_version,
43
- sc.categories as available_categories,
44
- sc.layers as available_layers,
45
- sc.critical_alerts,
46
- sc.total_standards
47
- FROM rapport.project_standards ps
48
- JOIN rapport.standards_catalog sc ON ps.catalog_id = sc.catalog_id
49
- WHERE ps.project_id = $1
50
- `, [projectId]);
51
-
52
- // If no preferences exist, return defaults with catalog info
53
- if (prefsResult.rowCount === 0) {
54
- const catalogResult = await executeQuery(`
55
- SELECT
56
- catalog_id,
57
- version,
58
- categories,
59
- layers,
60
- critical_alerts,
61
- total_standards
62
- FROM rapport.standards_catalog
63
- WHERE catalog_id = 'equilateral-v1'
64
- `);
65
-
66
- if (catalogResult.rowCount === 0) {
67
- return createErrorResponse(404, 'Standards catalog not found');
68
- }
69
-
70
- const catalog = catalogResult.rows[0];
71
-
72
- // Default: all categories enabled
73
- const defaultCategories = {};
74
- if (catalog.categories) {
75
- for (const key of Object.keys(catalog.categories)) {
76
- defaultCategories[key] = true;
77
- }
78
- }
79
-
80
- return createSuccessResponse({
81
- project_id: projectId,
82
- project_name: projectName,
83
- catalog_id: catalog.catalog_id,
84
- catalog_version: catalog.version,
85
- has_custom_preferences: false,
86
- preferences: {
87
- enabled_categories: defaultCategories,
88
- standard_overrides: {},
89
- critical_overrides: {}
90
- },
91
- catalog: {
92
- categories: catalog.categories,
93
- layers: catalog.layers,
94
- critical_alerts: catalog.critical_alerts,
95
- total_standards: catalog.total_standards
96
- }
97
- }, 'Default standards preferences');
98
- }
99
-
100
- const prefs = prefsResult.rows[0];
101
-
102
- return createSuccessResponse({
103
- project_id: projectId,
104
- project_name: projectName,
105
- catalog_id: prefs.catalog_id,
106
- catalog_version: prefs.catalog_version,
107
- has_custom_preferences: true,
108
- preferences: {
109
- enabled_categories: prefs.enabled_categories || {},
110
- standard_overrides: prefs.standard_overrides || {},
111
- critical_overrides: prefs.critical_overrides || {}
112
- },
113
- catalog: {
114
- categories: prefs.available_categories,
115
- layers: prefs.available_layers,
116
- critical_alerts: prefs.critical_alerts,
117
- total_standards: prefs.total_standards
118
- },
119
- modified_by: prefs.modified_by,
120
- modified_at: prefs.modified_at
121
- }, 'Project standards preferences retrieved');
122
-
123
- } catch (error) {
124
- console.error('Project Standards Get Error:', error);
125
- return createErrorResponse(500, 'Failed to retrieve project standards');
126
- }
127
- }
128
-
129
- exports.handler = wrapHandler(getProjectStandards);