fraim-framework 2.0.177 → 2.0.180

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 (77) hide show
  1. package/dist/src/ai-hub/desktop-main.js +2 -2
  2. package/dist/src/ai-hub/server.js +50 -1
  3. package/dist/src/api/admin/payments.js +33 -0
  4. package/dist/src/api/admin/sales-leads.js +21 -0
  5. package/dist/src/api/payment/create-session.js +338 -0
  6. package/dist/src/api/payment/dashboard-link.js +149 -0
  7. package/dist/src/api/payment/session-details.js +31 -0
  8. package/dist/src/api/payment/webhook.js +587 -0
  9. package/dist/src/api/personas/me.js +29 -0
  10. package/dist/src/api/pricing/get-config.js +25 -0
  11. package/dist/src/api/sales/contact.js +44 -0
  12. package/dist/src/cli/commands/add-provider.js +74 -61
  13. package/dist/src/cli/commands/add-surface.js +128 -0
  14. package/dist/src/cli/commands/login.js +5 -69
  15. package/dist/src/cli/commands/setup.js +27 -347
  16. package/dist/src/cli/distribution/marketplace-bundles.js +580 -0
  17. package/dist/src/cli/fraim.js +2 -0
  18. package/dist/src/cli/mcp/ide-formats.js +5 -3
  19. package/dist/src/cli/mcp/mcp-server-registry.js +10 -3
  20. package/dist/src/cli/providers/local-provider-registry.js +2 -3
  21. package/dist/src/cli/setup/auto-mcp-setup.js +9 -32
  22. package/dist/src/cli/setup/ide-detector.js +34 -14
  23. package/dist/src/config/persona-capability-bundles.js +17 -13
  24. package/dist/src/db/payment-repository.js +61 -0
  25. package/dist/src/first-run/session-service.js +2 -2
  26. package/dist/src/fraim/config-loader.js +11 -0
  27. package/dist/src/fraim/db-service.js +2387 -0
  28. package/dist/src/fraim/issues.js +152 -0
  29. package/dist/src/fraim/template-processor.js +184 -0
  30. package/dist/src/fraim/utils/request-utils.js +23 -0
  31. package/dist/src/local-mcp-server/stdio-server.js +28 -4
  32. package/dist/src/local-mcp-server/usage-collector.js +24 -0
  33. package/dist/src/middleware/auth.js +266 -0
  34. package/dist/src/middleware/cors-config.js +111 -0
  35. package/dist/src/middleware/logger.js +116 -0
  36. package/dist/src/middleware/rate-limit.js +110 -0
  37. package/dist/src/middleware/reject-query-api-key.js +45 -0
  38. package/dist/src/middleware/security-headers.js +41 -0
  39. package/dist/src/middleware/telemetry.js +134 -0
  40. package/dist/src/models/payment.js +2 -0
  41. package/dist/src/routes/analytics.js +1447 -0
  42. package/dist/src/routes/app-routes.js +32 -0
  43. package/dist/src/routes/auth-routes.js +505 -0
  44. package/dist/src/routes/oauth-routes.js +325 -0
  45. package/dist/src/routes/payment-routes.js +186 -0
  46. package/dist/src/routes/persona-catalog-routes.js +84 -0
  47. package/dist/src/services/admin-service.js +229 -0
  48. package/dist/src/services/audit-log-persistence.js +60 -0
  49. package/dist/src/services/audit-log.js +69 -0
  50. package/dist/src/services/cookie-service.js +129 -0
  51. package/dist/src/services/dashboard-access.js +27 -0
  52. package/dist/src/services/demo-seed-service.js +139 -0
  53. package/dist/src/services/email-code.js +23 -0
  54. package/dist/src/services/email-service-clean.js +782 -0
  55. package/dist/src/services/email-service.js +951 -0
  56. package/dist/src/services/installer-service.js +131 -0
  57. package/dist/src/services/mcp-oauth-store.js +33 -0
  58. package/dist/src/services/mcp-service.js +823 -0
  59. package/dist/src/services/oauth-helpers.js +127 -0
  60. package/dist/src/services/org-service.js +89 -0
  61. package/dist/src/services/persona-entitlement-service.js +288 -0
  62. package/dist/src/services/provider-service.js +215 -0
  63. package/dist/src/services/registry-service.js +628 -0
  64. package/dist/src/services/session-service.js +86 -0
  65. package/dist/src/services/trial-reminder-service.js +120 -0
  66. package/dist/src/services/usage-analytics-service.js +419 -0
  67. package/dist/src/services/workspace-identity.js +21 -0
  68. package/dist/src/types/analytics.js +2 -0
  69. package/dist/src/utils/payment-calculator.js +52 -0
  70. package/extensions/office-word/favicon.ico +0 -0
  71. package/extensions/office-word/icon-64.png +0 -0
  72. package/extensions/office-word/manifest.xml +33 -0
  73. package/extensions/office-word/taskpane.html +242 -0
  74. package/package.json +14 -3
  75. package/public/ai-hub/index.html +14 -2
  76. package/public/ai-hub/script.js +340 -66
  77. package/public/ai-hub/styles.css +83 -0
@@ -44,17 +44,7 @@ const prompts_1 = __importDefault(require("prompts"));
44
44
  const ide_detector_1 = require("./ide-detector");
45
45
  const mcp_config_generator_1 = require("./mcp-config-generator");
46
46
  const codex_local_config_1 = require("./codex-local-config");
47
- const provider_registry_1 = require("../providers/provider-registry");
48
- const normalizePlatformTokens = (tokenInput) => {
49
- if (!tokenInput)
50
- return {};
51
- if (typeof tokenInput === 'string') {
52
- return tokenInput ? { github: tokenInput } : {};
53
- }
54
- return tokenInput;
55
- };
56
- const promptForIDESelection = async (detectedIDEs, tokenInput) => {
57
- const tokens = normalizePlatformTokens(tokenInput);
47
+ const promptForIDESelection = async (detectedIDEs) => {
58
48
  if (process.env.FRAIM_NON_INTERACTIVE) {
59
49
  console.log(chalk_1.default.yellow(`\nℹ️ Non-interactive mode: configuring all detected IDEs (${detectedIDEs.length})`));
60
50
  return detectedIDEs;
@@ -70,17 +60,8 @@ const promptForIDESelection = async (detectedIDEs, tokenInput) => {
70
60
  console.log(chalk_1.default.blue('FRAIM will add these MCP servers to selected IDEs:'));
71
61
  console.log(chalk_1.default.gray(' • fraim (required for FRAIM jobs)'));
72
62
  console.log(chalk_1.default.gray(' • git (version control integration)'));
73
- // Show configured provider MCP servers dynamically
74
- const allProviderIds = await (0, provider_registry_1.getAllProviderIds)();
75
- for (const providerId of allProviderIds) {
76
- if (tokens[providerId]) {
77
- const provider = await (0, provider_registry_1.getProvider)(providerId);
78
- if (provider) {
79
- console.log(chalk_1.default.gray(` - ${providerId} (${provider.displayName} API access)`));
80
- }
81
- }
82
- }
83
63
  console.log(chalk_1.default.gray(' • playwright (browser automation)'));
64
+ console.log(chalk_1.default.blue('\n💡 Run "fraim add-provider <provider>" after setup to connect GitHub, GitLab, Jira, or other tools.'));
84
65
  console.log(chalk_1.default.yellow('\n💡 Existing MCP servers will be preserved - only missing servers will be added.'));
85
66
  const response = await (0, prompts_1.default)({
86
67
  type: 'text',
@@ -153,8 +134,7 @@ const validateSetupResults = async (configuredIDEs) => {
153
134
  }
154
135
  };
155
136
  exports.validateSetupResults = validateSetupResults;
156
- const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
157
- const tokens = normalizePlatformTokens(tokenInput);
137
+ const configureIDEMCP = async (ide, fraimKey) => {
158
138
  const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
159
139
  console.log(chalk_1.default.blue(`🔧 Configuring ${ide.name}...`));
160
140
  // Create backup
@@ -185,11 +165,9 @@ const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
185
165
  existingTomlContent = fs_1.default.readFileSync(configPath, 'utf8');
186
166
  console.log(chalk_1.default.gray(` 📋 Found existing TOML config`));
187
167
  }
188
- const newTomlContent = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, tokens, providerConfigs);
168
+ const newTomlContent = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, {});
189
169
  const { getAllMCPServerIds } = await Promise.resolve().then(() => __importStar(require('../mcp/mcp-server-registry')));
190
- const baseServerIds = getAllMCPServerIds();
191
- const providerServerIds = Object.keys(tokens).filter(id => tokens[id]);
192
- const serversToAdd = [...baseServerIds, ...providerServerIds];
170
+ const serversToAdd = getAllMCPServerIds();
193
171
  const mergeResult = (0, mcp_config_generator_1.mergeTomlMCPServers)(existingTomlContent, newTomlContent, serversToAdd);
194
172
  fs_1.default.writeFileSync(configPath, mergeResult.content);
195
173
  mergeResult.addedServers.forEach(server => {
@@ -204,7 +182,7 @@ const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
204
182
  }
205
183
  else {
206
184
  // For JSON configs - intelligent merging
207
- const newConfig = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, tokens, providerConfigs);
185
+ const newConfig = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, {});
208
186
  const newMCPServers = newConfig[serversKey] || newConfig.mcpServers || {};
209
187
  // Merge MCP servers intelligently
210
188
  const mergedMCPServers = { ...existingMCPServers };
@@ -251,8 +229,7 @@ const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
251
229
  console.log(chalk_1.default.green(` ✅ ${status} local Codex config: ${localResult.path}`));
252
230
  }
253
231
  };
254
- const autoConfigureMCP = async (fraimKey, tokenInput, selectedIDEs, providerConfigs) => {
255
- const tokens = normalizePlatformTokens(tokenInput);
232
+ const autoConfigureMCP = async (fraimKey, selectedIDEs) => {
256
233
  const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
257
234
  if (detectedIDEs.length === 0 && (!selectedIDEs || selectedIDEs.length === 0)) {
258
235
  console.log(chalk_1.default.yellow('⚠️ No supported IDEs detected.'));
@@ -294,7 +271,7 @@ const autoConfigureMCP = async (fraimKey, tokenInput, selectedIDEs, providerConf
294
271
  }
295
272
  else {
296
273
  // Interactive selection
297
- idesToConfigure = await (0, exports.promptForIDESelection)(detectedIDEs, tokens);
274
+ idesToConfigure = await (0, exports.promptForIDESelection)(detectedIDEs);
298
275
  }
299
276
  if (idesToConfigure.length === 0) {
300
277
  console.log(chalk_1.default.yellow('⚠️ No IDEs selected for configuration.'));
@@ -308,7 +285,7 @@ const autoConfigureMCP = async (fraimKey, tokenInput, selectedIDEs, providerConf
308
285
  };
309
286
  for (const ide of idesToConfigure) {
310
287
  try {
311
- await configureIDEMCP(ide, fraimKey, tokens, providerConfigs);
288
+ await configureIDEMCP(ide, fraimKey);
312
289
  results.successful.push(ide.name);
313
290
  }
314
291
  catch (error) {
@@ -24,15 +24,25 @@ const checkMultiplePaths = (paths) => {
24
24
  return paths.some(p => fs_1.default.existsSync(expandPath(p)));
25
25
  };
26
26
  // Issue #646 (Bug 2): a config directory left behind after uninstall (e.g. ~/.cursor,
27
- // ~/Library/Application Support/Cursor) made config-surface detection report a GUI app
28
- // as "Installed" when it was not. On macOS an installed GUI app keeps its .app bundle,
29
- // which is the reliable signal. So on macOS we require app-bundle evidence for GUI apps;
30
- // on Windows/Linux we keep the existing config-surface check unchanged (no reported
31
- // false-positive there, and those install paths are not validated on this platform).
32
- const macAppBundlePaths = (appName) => [
27
+ // ~/Library/Application Support/Cursor) made config-surface detection report Cursor
28
+ // as "Installed" when it was not. App evidence is the reliable signal for Cursor;
29
+ // other GUI surfaces keep their existing config-surface checks for compatibility
30
+ // with the #640 first-run detection contract.
31
+ const appBundlePaths = (appName) => [
33
32
  `/Applications/${appName}.app`,
34
33
  `~/Applications/${appName}.app`,
35
34
  ];
35
+ const windowsUserAppPaths = (appName) => {
36
+ switch (appName) {
37
+ case 'Cursor':
38
+ return [
39
+ '~/AppData/Local/Programs/Cursor/Cursor.exe',
40
+ '~/AppData/Local/Cursor/Cursor.exe',
41
+ ];
42
+ default:
43
+ return [];
44
+ }
45
+ };
36
46
  // Issue #646 follow-up: a user may run a GUI app from a non-standard location
37
47
  // (e.g. straight from a mounted DMG: /Volumes/.../Cursor.app) that the
38
48
  // /Applications checks miss. A running process of the app is definitive proof it
@@ -48,10 +58,19 @@ const isMacAppRunning = (appName) => {
48
58
  const result = (0, child_process_1.spawnSync)('pgrep', ['-f', `${appName}.app/Contents`], { encoding: 'utf8', timeout: 1500 });
49
59
  return result.status === 0 && Boolean((result.stdout || '').trim());
50
60
  };
51
- const guiAppDetect = (configSurfaceCheck, macAppName) => {
61
+ const hasAppEvidence = (appName) => {
62
+ const evidencePaths = process.platform === 'win32'
63
+ ? [...appBundlePaths(appName), ...windowsUserAppPaths(appName)]
64
+ : appBundlePaths(appName);
65
+ return checkMultiplePaths(evidencePaths) || isMacAppRunning(appName);
66
+ };
67
+ const guiAppDetect = (configSurfaceCheck, appName, options = {}) => {
52
68
  return () => {
69
+ if (options.requireAppEvidence) {
70
+ return hasAppEvidence(appName);
71
+ }
53
72
  if (process.platform === 'darwin') {
54
- return checkMultiplePaths(macAppBundlePaths(macAppName)) || isMacAppRunning(macAppName);
73
+ return hasAppEvidence(appName);
55
74
  }
56
75
  return configSurfaceCheck();
57
76
  };
@@ -81,12 +100,12 @@ const detectVSCode = () => {
81
100
  ];
82
101
  return checkMultiplePaths(paths);
83
102
  };
84
- const detectCursor = () => {
103
+ const detectCursorMcpConfig = () => {
85
104
  const paths = [
86
- '~/.cursor',
87
- '~/Library/Application Support/Cursor',
88
- '~/AppData/Roaming/Cursor',
89
- '~/.config/Cursor'
105
+ '~/.cursor/mcp.json',
106
+ '~/Library/Application Support/Cursor/mcp.json',
107
+ '~/AppData/Roaming/Cursor/mcp.json',
108
+ '~/.config/Cursor/mcp.json'
90
109
  ];
91
110
  return checkMultiplePaths(paths);
92
111
  };
@@ -104,6 +123,7 @@ const detectGeminiCli = () => {
104
123
  };
105
124
  const detectGeminiSurface = () => {
106
125
  const paths = [
126
+ '~/.gemini',
107
127
  '~/.gemini/settings.json',
108
128
  '~/AppData/Roaming/gemini/settings.json',
109
129
  '~/.config/gemini/settings.json'
@@ -196,7 +216,7 @@ exports.IDE_CONFIGS = [
196
216
  configType: 'kiro',
197
217
  adapterConfigType: 'cursor',
198
218
  invocationProfile: 'cursor-mention',
199
- detectMethod: guiAppDetect(detectCursor, 'Cursor'),
219
+ detectMethod: () => detectCursorMcpConfig() || hasAppEvidence('Cursor'),
200
220
  alternativePaths: [
201
221
  '~/Library/Application Support/Cursor/mcp.json',
202
222
  '~/AppData/Roaming/Cursor/mcp.json',
@@ -40,7 +40,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
40
40
  personaKey: 'beza',
41
41
  bundleId: 'persona-beza-core',
42
42
  catalogMetadata: buildCatalogMetadata('beza', ['competitive-analysis', 'review-business-strategy', 'business-plan-creation']),
43
- protectedJobs: ['competitive-analysis', 'review-business-strategy', 'business-plan-creation', 'problem-statement-crystallization', 'business-idea-validation-and-scoping', 'founder-market-fit-analysis', 'rfp-response-preparation', 'aws-activate-credits-application', 'community-funding-preparation', 'fundraising-prospect-discovery', 'google-cloud-credits-application', 'investor-pitch-preparation', 'microsoft-azure-credits-application', 'review-funding-preparation', 'advisory-board-development', 'advisor-interview', 'advisory-board-selection'],
43
+ protectedJobs: ['competitive-analysis', 'review-business-strategy', 'business-plan-creation', 'problem-statement-crystallization', 'business-idea-validation-and-scoping', 'founder-market-fit-analysis', 'community-funding-preparation', 'fundraising-prospect-discovery', 'investor-pitch-preparation', 'review-funding-preparation', 'advisory-board-development', 'advisor-interview', 'advisory-board-selection', 'blue-sky-brainstorming', 'domain-registration-research'],
44
44
  protectedAliases: ['business-strategy', 'company-strategy'],
45
45
  defaultHireMode: 'job',
46
46
  lockCopy: 'Hire BeZa to unlock business strategy work for this request.'
@@ -49,7 +49,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
49
49
  personaKey: 'pam',
50
50
  bundleId: 'persona-pam-core',
51
51
  catalogMetadata: buildCatalogMetadata('pam', ['feature-specification', 'technical-design', 'issue-preparation']),
52
- protectedJobs: ['feature-specification', 'technical-design', 'issue-preparation', 'implementation-design-review', 'issue-retrospective', 'work-completion', 'scrum-sprint-planning', 'mvp-validation-plan'],
52
+ protectedJobs: ['feature-specification', 'technical-design', 'issue-preparation', 'implementation-design-review', 'issue-retrospective', 'work-completion', 'scrum-sprint-planning', 'mvp-validation-plan', 'sprint-planning', 'customer-prospect-discovery', 'interview-preparation', 'participant-recruitment', 'process-interview-notes', 'review-customer-development', 'triage-customer-needs'],
53
53
  protectedAliases: ['product-management', 'product-spec'],
54
54
  defaultHireMode: 'job',
55
55
  lockCopy: 'Hire PaM to unlock product-management work for this request.'
@@ -58,7 +58,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
58
58
  personaKey: 'swen',
59
59
  bundleId: 'persona-swen-core',
60
60
  catalogMetadata: buildCatalogMetadata('swen', ['feature-implementation', 'code-refactoring', 'pr-iteration']),
61
- protectedJobs: ['feature-implementation', 'code-refactoring', 'pr-iteration', 'mobile-app-development', 'mcp-server-creation', 'cloud-application-deployment', 'cloud-cost-optimization', 'cloud-performance-diagnosis', 'route-llm-spend-to-cloud-credits', 'set-up-cloud-cost-alerts', 'gitlabs-to-github', 'system-migration', 'cross-cloud-migration', 'data-pipeline-design', 'data-quality-monitoring', 'data-platform-architecture', 'write-dev-docs', 'database-schema-design'],
61
+ protectedJobs: ['feature-implementation', 'code-refactoring', 'pr-iteration', 'mobile-app-development', 'mcp-server-creation', 'cloud-application-deployment', 'cloud-cost-optimization', 'cloud-performance-diagnosis', 'route-llm-spend-to-cloud-credits', 'set-up-cloud-cost-alerts', 'gitlabs-to-github', 'system-migration', 'cross-cloud-migration', 'data-pipeline-design', 'data-quality-monitoring', 'data-platform-architecture', 'write-dev-docs', 'database-schema-design', 'create-architecture', 'project-scaffolding', 'codebase-analysis-and-ideation', 'github-org-setup', 'google-workspace-setup', 'mobile-app-rejection-response', 'mobile-app-submission', 'publish-mcp-app', 'application-replication-workflow'],
62
62
  protectedAliases: ['software-engineering', 'implementation'],
63
63
  defaultHireMode: 'job',
64
64
  lockCopy: 'Hire SWEn to unlock software-engineering delivery for this request.'
@@ -76,7 +76,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
76
76
  personaKey: 'huxley',
77
77
  bundleId: 'persona-huxley-core',
78
78
  catalogMetadata: buildCatalogMetadata('huxley', ['design-system-creation', 'user-facing-prototyping', 'ux-research-synthesis']),
79
- protectedJobs: ['design-system-creation', 'user-facing-prototyping', 'website-creation', 'linkedin-carousel-from-deck', 'brand-creation', 'branding-quality-audit', 'ux-research-synthesis', 'user-journey-mapping'],
79
+ protectedJobs: ['design-system-creation', 'user-facing-prototyping', 'website-creation', 'brand-creation', 'branding-quality-audit', 'ux-research-synthesis', 'user-journey-mapping'],
80
80
  protectedAliases: ['ux-design', 'brand-design'],
81
81
  defaultHireMode: 'job',
82
82
  lockCopy: 'Hire hUXley to unlock design-system, UX research, and brand design work for this request.'
@@ -85,7 +85,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
85
85
  personaKey: 'gautam',
86
86
  bundleId: 'persona-gautam-core',
87
87
  catalogMetadata: buildCatalogMetadata('gautam', ['analyze-revenue-system', 'build-gtm-motion', 'ppc-campaign-management']),
88
- protectedJobs: ['pricing-strategy-definition', 'marketing-strategy-definition', 'product-launch-management', 'customer-prospect-discovery', 'evangelist-content-development', 'funnel-analysis', 'growth-loop-design', 'analyze-revenue-system', 'design-gtm-system', 'build-gtm-motion', 'build-gtm-stack', 'plan-gtm-team', 'marketing-content-creation', 'ppc-campaign-management', 'paid-social-strategy', 'ad-performance-analysis', 'tracking-and-attribution-setup', 'developer-advocacy', 'seo-strategy', 'marketing-analytics-review'],
88
+ protectedJobs: ['pricing-strategy-definition', 'marketing-strategy-definition', 'product-launch-management', 'evangelist-content-development', 'funnel-analysis', 'growth-loop-design', 'analyze-revenue-system', 'design-gtm-system', 'build-gtm-motion', 'build-gtm-stack', 'plan-gtm-team', 'marketing-content-creation', 'ppc-campaign-management', 'paid-social-strategy', 'ad-performance-analysis', 'tracking-and-attribution-setup', 'developer-advocacy', 'seo-strategy', 'marketing-analytics-review', 'linkedin-company-page-setup', 'x-account-setup', 'social-engagement-campaign', 'thought-leadership-engagement', 'promo-video-creation', 'linkedin-carousel-from-deck'],
89
89
  protectedAliases: ['gtm', 'marketing'],
90
90
  defaultHireMode: 'job',
91
91
  lockCopy: 'Hire GauTaM to unlock go-to-market and paid media work for this request.'
@@ -94,7 +94,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
94
94
  personaKey: 'cela',
95
95
  bundleId: 'persona-cela-core',
96
96
  catalogMetadata: buildCatalogMetadata('cela', ['contract-review-analysis', 'nda-creation', 'saas-contract-package-creation']),
97
- protectedJobs: ['contract-review-analysis', 'nda-creation', 'saas-contract-package-creation', 'trademark-registration-management', 'provisional-patent-application-creation', 'opensign-cloud-esign-dispatch', 'w9-creation', 'invoice-generation', 'entity-type-selection', 'state-incorporation-filing', 'business-tax-registration', 'ein-application', 'cap-table-construction', 'founder-and-equity-agreements', 'ip-assignment-agreement-creation', 'employment-structure-decision', 'business-banking-setup'],
97
+ protectedJobs: ['contract-review-analysis', 'nda-creation', 'saas-contract-package-creation', 'trademark-registration-management', 'provisional-patent-application-creation', 'opensign-cloud-esign-dispatch', 'w9-creation', 'entity-type-selection', 'state-incorporation-filing', 'business-tax-registration', 'ein-application', 'cap-table-construction', 'founder-and-equity-agreements', 'ip-assignment-agreement-creation', 'employment-structure-decision'],
98
98
  protectedAliases: ['legal', 'counsel'],
99
99
  defaultHireMode: 'job',
100
100
  lockCopy: 'Hire CELiA to unlock legal workflow support for this request.'
@@ -103,7 +103,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
103
103
  personaKey: 'sekhar',
104
104
  bundleId: 'persona-sekhar-core',
105
105
  catalogMetadata: buildCatalogMetadata('sekhar', ['security-review', 'ai-native-security-setup', 'security-findings-command-center']),
106
- protectedJobs: ['security-review', 'ai-native-security-setup', 'security-findings-command-center', 'vulnerability-triage-and-remediation', 'production-readiness-review', 'compliance-review', 'compliance-continuous-monitoring', 'compliance-policy-authoring', 'compliance-questionnaire-response', 'compliance-requirements-detection', 'generate-audit-evidence', 'regulation-evidence-management', 'soc2-evidence-management'],
106
+ protectedJobs: ['security-review', 'ai-native-security-setup', 'security-findings-command-center', 'vulnerability-triage-and-remediation', 'compliance-review', 'compliance-continuous-monitoring', 'compliance-policy-authoring', 'compliance-questionnaire-response', 'compliance-requirements-detection', 'generate-audit-evidence', 'regulation-evidence-management', 'soc2-evidence-management'],
107
107
  protectedAliases: ['security', 'appsec'],
108
108
  defaultHireMode: 'job',
109
109
  lockCopy: 'Hire SEChar to unlock security setup, review, and findings-command work for this request.'
@@ -112,7 +112,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
112
112
  personaKey: 'ashley',
113
113
  bundleId: 'persona-ashley-core',
114
114
  catalogMetadata: buildCatalogMetadata('ashley', ['executive-assistant', 'weekly-operating-review', 'send-thank-you-notes']),
115
- protectedJobs: ['executive-assistant', 'weekly-operating-review', 'send-thank-you-notes', 'send-newsletter', 'analyze-transcript', 'send-stakeholder-update', 'portfolio-impact-report'],
115
+ protectedJobs: ['executive-assistant', 'weekly-operating-review', 'send-thank-you-notes', 'send-newsletter', 'analyze-transcript', 'send-stakeholder-update'],
116
116
  protectedAliases: ['executive-assistant', 'operations-assistant'],
117
117
  defaultHireMode: 'job',
118
118
  lockCopy: 'Hire AshLey to unlock executive-assistant work for this request.'
@@ -121,7 +121,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
121
121
  personaKey: 'mandy',
122
122
  bundleId: 'persona-mandy-core',
123
123
  catalogMetadata: buildCatalogMetadata('mandy', ['fully-delegate', 'project-plan-creation', 'stakeholder-status-reporting']),
124
- protectedJobs: ['fully-delegate', 'delivery-governance-review', 'project-plan-creation', 'stakeholder-status-reporting', 'experiment-tracking', 'cross-functional-dependency-management'],
124
+ protectedJobs: ['fully-delegate', 'delivery-governance-review', 'project-plan-creation', 'stakeholder-status-reporting', 'experiment-tracking', 'cross-functional-dependency-management', 'portfolio-impact-report'],
125
125
  protectedAliases: ['manager', 'team-lead', 'orchestrator'],
126
126
  defaultHireMode: 'job',
127
127
  lockCopy: 'Hire MANdy to unlock autonomous multi-role orchestration — MANdy plans the job sequence, runs sub-agents in parallel, coaches them through verification loops, and hands back a synthesized DRAFT for your approval.'
@@ -175,7 +175,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
175
175
  personaKey: 'casey',
176
176
  bundleId: 'persona-casey-core',
177
177
  catalogMetadata: buildCatalogMetadata('casey', ['support-case-resolution', 'support-sop-operationalization', 'support-system-operationalization', 'support-playbook-evaluation']),
178
- protectedJobs: ['crm-account-health-review', 'crm-case-resolution', 'customer-health-review', 'loyalty-program-management', 'survey-campaign-management', 'support-queue-management', 'support-case-resolution', 'support-sop-operationalization', 'support-system-operationalization', 'support-playbook-evaluation'],
178
+ protectedJobs: ['crm-account-health-review', 'crm-case-resolution', 'customer-health-review', 'loyalty-program-management', 'survey-campaign-management', 'support-queue-management', 'support-case-resolution', 'support-sop-operationalization', 'support-system-operationalization', 'support-playbook-evaluation', 'user-survey-management'],
179
179
  protectedAliases: ['customer-success', 'customer-support', 'csm', 'support'],
180
180
  defaultHireMode: 'job',
181
181
  lockCopy: 'Hire CaSey to unlock customer success and support work for this request.'
@@ -205,7 +205,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
205
205
  personaKey: 'mona',
206
206
  bundleId: 'persona-mona-core',
207
207
  catalogMetadata: buildCatalogMetadata('mona', ['financial-analysis', 'fpa-and-forecasting', 'monthly-close-review']),
208
- protectedJobs: ['financial-analysis', 'fpa-and-forecasting', 'monthly-close-review', 'tax-strategy-planning'],
208
+ protectedJobs: ['financial-analysis', 'fpa-and-forecasting', 'monthly-close-review', 'tax-strategy-planning', 'aws-activate-credits-application', 'google-cloud-credits-application', 'microsoft-azure-credits-application', 'invoice-generation', 'business-banking-setup'],
209
209
  protectedAliases: ['finance', 'financial-modeling', 'fpa', 'bookkeeping'],
210
210
  defaultHireMode: 'job',
211
211
  lockCopy: 'Hire MONa to unlock financial modeling, FP&A, and tax strategy work for this request.'
@@ -214,7 +214,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
214
214
  personaKey: 'sreya',
215
215
  bundleId: 'persona-sreya-core',
216
216
  catalogMetadata: buildCatalogMetadata('sreya', ['slo-design-and-implementation', 'incident-response', 'reliability-review']),
217
- protectedJobs: ['slo-design-and-implementation', 'incident-response', 'reliability-review'],
217
+ protectedJobs: ['slo-design-and-implementation', 'incident-response', 'reliability-review', 'production-readiness-review'],
218
218
  protectedAliases: ['sre', 'reliability', 'incident-response', 'on-call'],
219
219
  defaultHireMode: 'job',
220
220
  lockCopy: 'Hire SREya to unlock SLO governance, incident response, and production reliability work for this request.'
@@ -231,7 +231,8 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
231
231
  'procurement-negotiation-prep',
232
232
  'purchase-approval-and-po-package',
233
233
  'equipment-acceptance-and-supplier-retrospective',
234
- 'supplier-performance-review'
234
+ 'supplier-performance-review',
235
+ 'rfp-response-preparation'
235
236
  ],
236
237
  protectedAliases: ['procurement', 'sourcing', 'purchasing', 'supplier-management'],
237
238
  defaultHireMode: 'job',
@@ -266,6 +267,9 @@ function getPersonaCapabilityBundle(personaKey) {
266
267
  return exports.PERSONA_CAPABILITY_BUNDLES[personaKey];
267
268
  }
268
269
  function getProtectedPersonaForJob(jobName) {
270
+ if (isFreeJob(jobName)) {
271
+ return null;
272
+ }
269
273
  return PROTECTED_JOB_TO_PERSONA.get(jobName) || null;
270
274
  }
271
275
  function listPersonaCapabilityBundles() {
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PaymentRepository = void 0;
4
+ const COLLECTION_NAME = 'fraim_payments';
5
+ class PaymentRepository {
6
+ constructor(client, dbName = 'fraim') {
7
+ this.db = client.db(dbName);
8
+ this.collection = this.db.collection(COLLECTION_NAME);
9
+ }
10
+ async ensureIndexes() {
11
+ await this.collection.createIndex({ email: 1 });
12
+ await this.collection.createIndex({ timestamp: -1 });
13
+ await this.collection.createIndex({ status: 1 });
14
+ await this.collection.createIndex({ stripeCustomerId: 1 });
15
+ }
16
+ async createPayment(payment) {
17
+ const result = await this.collection.insertOne(payment);
18
+ return { ...payment, _id: result.insertedId.toString() };
19
+ }
20
+ async updatePaymentStatus(stripePaymentIntentId, status, metadata) {
21
+ const result = await this.collection.updateOne({ stripePaymentIntentId }, {
22
+ $set: {
23
+ status,
24
+ ...(metadata && { metadata })
25
+ }
26
+ });
27
+ return result.modifiedCount > 0;
28
+ }
29
+ async getPaymentById(id) {
30
+ return await this.collection.findOne({ _id: id });
31
+ }
32
+ async getPaymentByStripePaymentIntent(stripePaymentIntentId) {
33
+ return await this.collection.findOne({ stripePaymentIntentId });
34
+ }
35
+ async getPaymentsByEmail(email) {
36
+ return await this.collection.find({ email }).sort({ timestamp: -1 }).toArray();
37
+ }
38
+ async listPayments(filters) {
39
+ const query = {};
40
+ if (filters.plan)
41
+ query.plan = filters.plan;
42
+ if (filters.status)
43
+ query.status = filters.status;
44
+ if (filters.startDate || filters.endDate) {
45
+ query.timestamp = {};
46
+ if (filters.startDate)
47
+ query.timestamp.$gte = filters.startDate;
48
+ if (filters.endDate)
49
+ query.timestamp.$lte = filters.endDate;
50
+ }
51
+ const total = await this.collection.countDocuments(query);
52
+ const payments = await this.collection
53
+ .find(query)
54
+ .sort({ timestamp: -1 })
55
+ .skip(filters.offset || 0)
56
+ .limit(filters.limit || 50)
57
+ .toArray();
58
+ return { payments, total };
59
+ }
60
+ }
61
+ exports.PaymentRepository = PaymentRepository;
@@ -607,12 +607,12 @@ class FirstRunSessionService {
607
607
  persistShellPath();
608
608
  const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
609
609
  if (detectedIDEs.length > 0) {
610
- await (0, auto_mcp_setup_1.autoConfigureMCP)(this.key, {}, detectedIDEs.map((ide) => ide.name), {});
610
+ await (0, auto_mcp_setup_1.autoConfigureMCP)(this.key, detectedIDEs.map((ide) => ide.name));
611
611
  }
612
612
  // Write config.json after autoConfigureMCP so detectRowsOnLoad can use its
613
613
  // existence as a signal that IDE setup completed. Writing it before would cause
614
614
  // the wizard to mark this row 'ok' on retry before IDEs are actually configured.
615
- (0, setup_1.saveGlobalConfig)(this.key, 'conversational', {}, {});
615
+ (0, setup_1.saveGlobalConfig)(this.key, 'conversational');
616
616
  const { syncUserLevelArtifacts } = await Promise.resolve().then(() => __importStar(require('../cli/setup/user-level-sync')));
617
617
  await syncUserLevelArtifacts();
618
618
  const { installSlashCommands, installGlobalRules } = await Promise.resolve().then(() => __importStar(require('../cli/setup/ide-global-integration')));
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRepositoryInfo = exports.getConfigValue = exports.loadFraimConfig = void 0;
4
+ /**
5
+ * Backward-compatible re-export.
6
+ * Canonical config loader lives in src/core/config-loader.ts.
7
+ */
8
+ var config_loader_1 = require("../core/config-loader");
9
+ Object.defineProperty(exports, "loadFraimConfig", { enumerable: true, get: function () { return config_loader_1.loadFraimConfig; } });
10
+ Object.defineProperty(exports, "getConfigValue", { enumerable: true, get: function () { return config_loader_1.getConfigValue; } });
11
+ Object.defineProperty(exports, "getRepositoryInfo", { enumerable: true, get: function () { return config_loader_1.getRepositoryInfo; } });