fraim 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
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * InstallerService - Generates installer scripts and dashboard HTML for the Get Started flow.
4
+ * Scripts are loaded from templates in scripts/installer/ and populated with token/baseUrl.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.InstallerService = void 0;
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
10
+ function getScriptsDir() {
11
+ // When running from dist: dist/services/ -> dist/../scripts = scripts
12
+ // When running from src with tsx: src/services/ -> src/../scripts = scripts
13
+ const candidates = [
14
+ (0, path_1.join)(process.cwd(), 'scripts', 'installer'),
15
+ (0, path_1.join)(__dirname, '..', '..', 'scripts', 'installer'),
16
+ (0, path_1.join)(__dirname, '..', '..', '..', 'scripts', 'installer')
17
+ ];
18
+ for (const dir of candidates) {
19
+ if ((0, fs_1.existsSync)(dir))
20
+ return dir;
21
+ }
22
+ return null;
23
+ }
24
+ /**
25
+ * Default marketing site base URL. All asset references and nav links in the
26
+ * layout shell resolve against this host. Overridable via FRAIM_MARKETING_URL.
27
+ *
28
+ * Issue #258: In production, the FRAIM server (Azure) does NOT ship fraim-pro/
29
+ * in its deploy package — the marketing site is deployed separately via GitHub
30
+ * Pages. Root-relative paths like `/css/styles.css` therefore 404 on the FRAIM
31
+ * host. Absolute URLs to the marketing site resolve correctly regardless of
32
+ * where the dashboard is served from.
33
+ */
34
+ const DEFAULT_MARKETING_BASE_URL = 'https://fraimworks.ai';
35
+ function getMarketingBaseUrl() {
36
+ const raw = process.env.FRAIM_MARKETING_URL || DEFAULT_MARKETING_BASE_URL;
37
+ // Normalize: strip trailing slash so we never emit double-slashes like
38
+ // `https://fraimworks.ai//css/styles.css`.
39
+ return raw.replace(/\/+$/, '');
40
+ }
41
+ function buildLayoutShell(marketingBaseUrl) {
42
+ const m = marketingBaseUrl;
43
+ return `<!DOCTYPE html>
44
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=5.0,user-scalable=yes">
45
+ <script>(function(){var t=localStorage.getItem('theme')||(window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');document.documentElement.setAttribute('data-theme',t);})();</script>
46
+ <title>{{TITLE}}</title><meta name="theme-color" content="#6366f1">
47
+ <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
48
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
49
+ <link rel="stylesheet" href="${m}/css/styles.css"></head><body>
50
+ <nav class="nav"><div class="nav-container"><div class="nav-logo"><a href="${m}/"><img src="${m}/images/fraim-logo.png" alt="FRAIM" class="logo-icon"/><span class="logo-text">FRAIM</span></a></div>
51
+ <div class="nav-links"><a href="${m}/#features">Features</a><a href="${m}/#how-it-works">How it Works</a><a href="${m}/pricing.html">Pricing</a><a href="${m}/#results">Results</a>
52
+ <button class="theme-toggle" id="theme-toggle" aria-label="Toggle dark mode"><span class="theme-icon">🌙</span></button>
53
+ <a href="${m}/" class="nav-cta join-waitlist-btn">Get Started</a></div></div></nav>
54
+ <main style="min-height:100vh;display:flex;align-items:center;justify-content:center;padding:80px 20px 40px">{{BODY}}</main>
55
+ <script src="${m}/js/script.js"></script></body></html>`;
56
+ }
57
+ class InstallerService {
58
+ constructor() {
59
+ this.scriptsDir = getScriptsDir();
60
+ }
61
+ requireScriptsDir() {
62
+ if (!this.scriptsDir) {
63
+ throw new Error('Installer scripts directory not found. Installer download is unavailable.');
64
+ }
65
+ return this.scriptsDir;
66
+ }
67
+ /**
68
+ * Build the HTML layout shell (nav, styles, theme) wrapping body content.
69
+ *
70
+ * Nav links and asset references resolve against the marketing site base URL
71
+ * (default https://fraimworks.ai, overridable via FRAIM_MARKETING_URL). See
72
+ * #258: the FRAIM server and marketing site live on different hosts in prod,
73
+ * so root-relative paths would 404.
74
+ */
75
+ layoutShell(title, bodyContent) {
76
+ return buildLayoutShell(getMarketingBaseUrl())
77
+ .replace('{{TITLE}}', title)
78
+ .replace('{{BODY}}', bodyContent);
79
+ }
80
+ /**
81
+ * Generate the dashboard card HTML (key, installer links, CLI command).
82
+ *
83
+ * Platform-specific install flows:
84
+ * - Windows: download-and-double-click .cmd file (no Gatekeeper equivalent blocks it)
85
+ * - Mac: copy-paste `curl | sh` one-liner. Downloaded .command files are blocked
86
+ * by Gatekeeper on Sequoia+ with no "Open Anyway" escape (see #256). Piping
87
+ * bytes through curl avoids the quarantine attribute entirely.
88
+ */
89
+ generateDashboardCard(_data, _baseUrl) {
90
+ return `<div class="container" style="max-width:520px;width:100%">
91
+ <div class="card" style="background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:16px;max-width:520px;width:100%;box-shadow:var(--shadow-lg);overflow:hidden">
92
+ <div class="card-header" style="padding:24px;background:linear-gradient(135deg,#22c55e 0%,#16a34a 100%);color:#fff;text-align:center;border-radius:16px 16px 0 0">
93
+ <div style="font-size:48px;margin-bottom:8px">&#x2705;</div><h2 style="font-size:20px;font-weight:700">Open Account to view your FRAIM key</h2><p style="font-size:14px;opacity:.9;margin-top:4px">Your key and install commands now live in Account.</p></div>
94
+ <div style="padding:24px">
95
+ <p style="font-size:14px;color:var(--text-muted);line-height:1.6;margin:0 0 20px">For security, FRAIM no longer displays API keys on this standalone page. Continue to Account, reveal the key when you need it, and generate fresh install commands there.</p>
96
+ <a href="/#account" class="btn-primary" style="display:block;padding:14px 20px;border-radius:10px;font-size:14px;font-weight:600;text-align:center;text-decoration:none">Open Account</a>
97
+ </div></div></div>`;
98
+ }
99
+ /**
100
+ * Generate an error page card (missing token, invalid token, etc.).
101
+ */
102
+ generateErrorCard(title, message, linkText, linkHref) {
103
+ return `<div class="container" style="text-align:center;max-width:400px">
104
+ <div class="card" style="background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:16px;padding:32px">
105
+ <h1 style="color:var(--error-color);margin-bottom:12px">${title}</h1><p style="color:var(--text-secondary)">${message}</p>
106
+ <p style="margin-top:16px"><a href="${linkHref}" class="btn-primary">${linkText}</a></p></div></div>`;
107
+ }
108
+ /**
109
+ * Generate the Mac installer script (.command) with the API key embedded.
110
+ */
111
+ generateMacScript(key, _baseUrl) {
112
+ const fraimCmd = `npx -y fraim@latest first-run --key=${key}`;
113
+ const templatePath = (0, path_1.join)(this.requireScriptsDir(), 'fraim-install-mac.template.sh');
114
+ const template = (0, fs_1.readFileSync)(templatePath, 'utf-8');
115
+ return template
116
+ .replace('{{FRAIM_CMD}}', fraimCmd)
117
+ .split('{{KEY}}').join(key);
118
+ }
119
+ /**
120
+ * Generate the Windows installer script (.cmd) with the API key embedded.
121
+ */
122
+ generateWindowsScript(key, _baseUrl) {
123
+ const fraimCmd = `npx -y fraim@latest first-run --key=${key}`;
124
+ const templatePath = (0, path_1.join)(this.requireScriptsDir(), 'fraim-install-win.template.cmd');
125
+ const template = (0, fs_1.readFileSync)(templatePath, 'utf-8');
126
+ return template
127
+ .replace('{{FRAIM_CMD}}', fraimCmd)
128
+ .split('{{KEY}}').join(key);
129
+ }
130
+ }
131
+ exports.InstallerService = InstallerService;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mcpOAuthStore = void 0;
4
+ const crypto_1 = require("crypto");
5
+ class McpOAuthStore {
6
+ constructor() {
7
+ this.codes = new Map();
8
+ }
9
+ store(entry) {
10
+ const code = (0, crypto_1.randomBytes)(32).toString('base64url');
11
+ this.codes.set(code, { ...entry, expiresAt: Date.now() + 5 * 60 * 1000 });
12
+ this.gc();
13
+ return code;
14
+ }
15
+ /** Retrieve and atomically delete the code. Returns null if not found or expired. */
16
+ consume(code) {
17
+ const entry = this.codes.get(code);
18
+ if (!entry)
19
+ return null;
20
+ this.codes.delete(code);
21
+ if (entry.expiresAt < Date.now())
22
+ return null;
23
+ return entry;
24
+ }
25
+ gc() {
26
+ const now = Date.now();
27
+ for (const [k, v] of this.codes) {
28
+ if (v.expiresAt < now)
29
+ this.codes.delete(k);
30
+ }
31
+ }
32
+ }
33
+ exports.mcpOAuthStore = new McpOAuthStore();