@dataflint/mcp-server 1.0.15 → 1.0.21

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 (68) hide show
  1. package/dist/auth/auth0-service.d.ts.map +1 -1
  2. package/dist/auth/auth0-service.js +27 -13
  3. package/dist/auth/auth0-service.js.map +1 -1
  4. package/dist/auth/errors.d.ts +86 -0
  5. package/dist/auth/errors.d.ts.map +1 -0
  6. package/dist/auth/errors.js +144 -0
  7. package/dist/auth/errors.js.map +1 -0
  8. package/dist/auth/index.d.ts +1 -0
  9. package/dist/auth/index.d.ts.map +1 -1
  10. package/dist/auth/index.js +10 -1
  11. package/dist/auth/index.js.map +1 -1
  12. package/dist/auth/secrets/aws-secrets-provider.d.ts.map +1 -1
  13. package/dist/auth/secrets/aws-secrets-provider.js +3 -1
  14. package/dist/auth/secrets/aws-secrets-provider.js.map +1 -1
  15. package/dist/dataflint-server-service.d.ts +7 -2
  16. package/dist/dataflint-server-service.d.ts.map +1 -1
  17. package/dist/dataflint-server-service.js +86 -15
  18. package/dist/dataflint-server-service.js.map +1 -1
  19. package/dist/errors.d.ts +55 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +185 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/index.d.ts +6 -3
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +21 -9
  26. package/dist/index.js.map +1 -1
  27. package/dist/server.d.ts +1 -1
  28. package/dist/server.d.ts.map +1 -1
  29. package/dist/server.js +2 -2
  30. package/dist/server.js.map +1 -1
  31. package/dist/standalone/config.js +1667 -280
  32. package/dist/standalone/config.js.map +7 -1
  33. package/dist/standalone/logger.js +2 -2
  34. package/dist/standalone/logger.js.map +1 -1
  35. package/dist/standalone/server.js +3 -3
  36. package/dist/standalone/server.js.map +1 -1
  37. package/dist/standalone/stdio-transport.d.ts +1 -1
  38. package/dist/standalone/stdio-transport.d.ts.map +1 -1
  39. package/dist/standalone/stdio-transport.js +2 -2
  40. package/dist/standalone/stdio-transport.js.map +1 -1
  41. package/dist/test-helpers.d.ts +27 -0
  42. package/dist/test-helpers.d.ts.map +1 -0
  43. package/dist/test-helpers.js +101 -0
  44. package/dist/test-helpers.js.map +1 -0
  45. package/dist/tools/base.d.ts +16 -0
  46. package/dist/tools/base.d.ts.map +1 -1
  47. package/dist/tools/base.js +16 -0
  48. package/dist/tools/base.js.map +1 -1
  49. package/dist/tools/core-tools.d.ts.map +1 -1
  50. package/dist/tools/core-tools.js +4 -4
  51. package/dist/tools/core-tools.js.map +1 -1
  52. package/dist/tools/expertise-tools.d.ts.map +1 -1
  53. package/dist/tools/expertise-tools.js +5 -5
  54. package/dist/tools/expertise-tools.js.map +1 -1
  55. package/dist/tools/findings-tools.d.ts.map +1 -1
  56. package/dist/tools/findings-tools.js +4 -4
  57. package/dist/tools/findings-tools.js.map +1 -1
  58. package/dist/tools/highlight-tools.d.ts.map +1 -1
  59. package/dist/tools/highlight-tools.js +8 -10
  60. package/dist/tools/highlight-tools.js.map +1 -1
  61. package/dist/tools/listing-tools.d.ts.map +1 -1
  62. package/dist/tools/listing-tools.js +1 -1
  63. package/dist/tools/listing-tools.js.map +1 -1
  64. package/dist/types.d.ts +3 -3
  65. package/dist/types.d.ts.map +1 -1
  66. package/dist/types.js +3 -3
  67. package/dist/types.js.map +1 -1
  68. package/package.json +3 -2
@@ -1,317 +1,1704 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+
28
+ // dist/auth/customer-auth-configs.js
29
+ var require_customer_auth_configs = __commonJS({
30
+ "dist/auth/customer-auth-configs.js"(exports2) {
31
+ "use strict";
32
+ Object.defineProperty(exports2, "__esModule", { value: true });
33
+ exports2.customerAuthConfigs = void 0;
34
+ exports2.customerAuthConfigs = {
35
+ // Customer domain hash → Auth0 configuration
36
+ "857064adfec4e0e5e37be8afef397155db006bb6009d1b395388d9174eb40795": {
37
+ clientId: "CWvpqujjEV2aoRSDVWFSh1U6HQALygB0",
38
+ domainProducer: (customerDomain) => `https://dataflint-${customerDomain}.us.auth0.com/`
39
+ },
40
+ cafe6e0af028d729afd3c4a386482621af90e8e117b1216f2bbc08e86a5e9445: {
41
+ clientId: "HRLICLhE0BP4AeZ8dSPAoDHFmMZVacxi"
42
+ },
43
+ "1613f29ea956158d2ad56a10780feb45d78755819565e76c4bf0d9069d17aab9": {
44
+ clientId: "CnyJJKVqes0Y0uU57GreAeaPbJlm4l4w"
45
+ },
46
+ eae8e3404182477f008479b38a6629ee86b23cefe2c418c5dc5c2f0d02af5475: {
47
+ clientId: "etY3z44ssWohe77PEBIMPzktW4BmvWGT"
48
+ },
49
+ // dataflint-demo (added from commit f38928c)
50
+ cc1677626e05d82b301cc83c22a850eac849555e704f288083108d79f600cea1: {
51
+ clientId: "u9W23NGvlV58W2N9WXMMhsM12bKK8oGI"
52
+ }
53
+ };
54
+ }
55
+ });
56
+
57
+ // dist/auth/types.js
58
+ var require_types = __commonJS({
59
+ "dist/auth/types.js"(exports2) {
60
+ "use strict";
61
+ Object.defineProperty(exports2, "__esModule", { value: true });
62
+ exports2.M2MType = exports2.AuthStrategyType = void 0;
63
+ var AuthStrategyType;
64
+ (function(AuthStrategyType2) {
65
+ AuthStrategyType2["SERVICE_ACCOUNT"] = "service_account";
66
+ AuthStrategyType2["AUTH0_M2M"] = "auth0_m2m";
67
+ AuthStrategyType2["AUTH0_USER"] = "auth0_user";
68
+ })(AuthStrategyType || (exports2.AuthStrategyType = AuthStrategyType = {}));
69
+ var M2MType;
70
+ (function(M2MType2) {
71
+ M2MType2["NONE"] = "none";
72
+ M2MType2["SERVICE_ACCOUNT"] = "service_account";
73
+ M2MType2["AUTH0_M2M"] = "auth0_m2m";
74
+ })(M2MType || (exports2.M2MType = M2MType = {}));
75
+ }
76
+ });
77
+
78
+ // dist/auth/errors.js
79
+ var require_errors = __commonJS({
80
+ "dist/auth/errors.js"(exports2) {
81
+ "use strict";
82
+ Object.defineProperty(exports2, "__esModule", { value: true });
83
+ exports2.NetworkError = exports2.ConfigError = exports2.AuthError = exports2.DataFlintError = exports2.ErrorCode = void 0;
84
+ var ErrorCode;
85
+ (function(ErrorCode2) {
86
+ ErrorCode2["AUTH_NOT_INITIALIZED"] = "AUTH_NOT_INITIALIZED";
87
+ ErrorCode2["AUTH_TOKEN_EXPIRED"] = "AUTH_TOKEN_EXPIRED";
88
+ ErrorCode2["AUTH_TOKEN_INVALID"] = "AUTH_TOKEN_INVALID";
89
+ ErrorCode2["AUTH_REFRESH_FAILED"] = "AUTH_REFRESH_FAILED";
90
+ ErrorCode2["AUTH_LOGIN_REQUIRED"] = "AUTH_LOGIN_REQUIRED";
91
+ ErrorCode2["AUTH_TIMEOUT"] = "AUTH_TIMEOUT";
92
+ ErrorCode2["CONFIG_MISSING"] = "CONFIG_MISSING";
93
+ ErrorCode2["CONFIG_INVALID"] = "CONFIG_INVALID";
94
+ ErrorCode2["CONFIG_DOMAIN_NOT_FOUND"] = "CONFIG_DOMAIN_NOT_FOUND";
95
+ ErrorCode2["NETWORK_UNAVAILABLE"] = "NETWORK_UNAVAILABLE";
96
+ ErrorCode2["NETWORK_TIMEOUT"] = "NETWORK_TIMEOUT";
97
+ ErrorCode2["NETWORK_DNS_FAILED"] = "NETWORK_DNS_FAILED";
98
+ ErrorCode2["API_UNAUTHORIZED"] = "API_UNAUTHORIZED";
99
+ ErrorCode2["API_FORBIDDEN"] = "API_FORBIDDEN";
100
+ ErrorCode2["API_NOT_FOUND"] = "API_NOT_FOUND";
101
+ ErrorCode2["API_RATE_LIMITED"] = "API_RATE_LIMITED";
102
+ ErrorCode2["API_SERVER_ERROR"] = "API_SERVER_ERROR";
103
+ ErrorCode2["API_BAD_REQUEST"] = "API_BAD_REQUEST";
104
+ ErrorCode2["SERVICE_NOT_STARTED"] = "SERVICE_NOT_STARTED";
105
+ ErrorCode2["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
106
+ ErrorCode2["UNKNOWN"] = "UNKNOWN";
107
+ })(ErrorCode || (exports2.ErrorCode = ErrorCode = {}));
108
+ var DataFlintError = class extends Error {
109
+ cause;
110
+ constructor(message, cause) {
111
+ super(message);
112
+ this.cause = cause;
113
+ this.name = this.constructor.name;
114
+ if (Error.captureStackTrace) {
115
+ Error.captureStackTrace(this, this.constructor);
116
+ }
117
+ }
118
+ /**
119
+ * Get a user-friendly error message with action
120
+ */
121
+ getUserMessage() {
122
+ return `${this.message}. ${this.userAction}`;
123
+ }
124
+ };
125
+ exports2.DataFlintError = DataFlintError;
126
+ var AuthError = class _AuthError extends DataFlintError {
127
+ code;
128
+ isRetryable;
129
+ userAction;
130
+ constructor(code, message, userAction, isRetryable = false, cause) {
131
+ super(message, cause);
132
+ this.code = code;
133
+ this.isRetryable = isRetryable;
134
+ this.userAction = userAction;
135
+ }
136
+ static tokenExpired(cause) {
137
+ return new _AuthError(ErrorCode.AUTH_TOKEN_EXPIRED, "Your session has expired", 'Please click "Login" to authenticate again.', false, cause);
138
+ }
139
+ static tokenInvalid(cause) {
140
+ return new _AuthError(ErrorCode.AUTH_TOKEN_INVALID, "Authentication token is invalid", 'Please click "Login" to authenticate again.', false, cause);
141
+ }
142
+ static refreshFailed(cause) {
143
+ return new _AuthError(ErrorCode.AUTH_REFRESH_FAILED, "Failed to refresh authentication", 'Please click "Login" to authenticate again.', false, cause);
144
+ }
145
+ static loginRequired() {
146
+ return new _AuthError(ErrorCode.AUTH_LOGIN_REQUIRED, "Authentication required", 'Please run "DataFlint: Login" from the command palette.', false);
147
+ }
148
+ static timeout(cause) {
149
+ return new _AuthError(ErrorCode.AUTH_TIMEOUT, "Authentication timed out", "Please check your internet connection and try again.", true, cause);
150
+ }
151
+ static notInitialized() {
152
+ return new _AuthError(ErrorCode.AUTH_NOT_INITIALIZED, "Authentication service not initialized", 'Please run "DataFlint: Restart Server" to reinitialize.', true);
153
+ }
154
+ };
155
+ exports2.AuthError = AuthError;
156
+ var ConfigError = class _ConfigError extends DataFlintError {
157
+ code;
158
+ isRetryable = false;
159
+ userAction;
160
+ constructor(code, message, userAction, cause) {
161
+ super(message, cause);
162
+ this.code = code;
163
+ this.userAction = userAction;
164
+ }
165
+ static missing(field) {
166
+ return new _ConfigError(ErrorCode.CONFIG_MISSING, `Missing required configuration: ${field}`, 'Please check your DataFlint settings. Run "DataFlint: Show Debug Information" for details.');
167
+ }
168
+ static invalid(field, value, expected) {
169
+ return new _ConfigError(ErrorCode.CONFIG_INVALID, `Invalid configuration for ${field}: "${value}"`, `Expected ${expected}. Please check your DataFlint settings.`);
170
+ }
171
+ static customerDomainNotFound(domain) {
172
+ return new _ConfigError(ErrorCode.CONFIG_DOMAIN_NOT_FOUND, `Customer domain "${domain}" is not configured`, "Please contact support to set up your organization's domain, or remove the customer domain setting.");
173
+ }
174
+ };
175
+ exports2.ConfigError = ConfigError;
176
+ var NetworkError = class _NetworkError extends DataFlintError {
177
+ code;
178
+ isRetryable = true;
179
+ userAction;
180
+ constructor(code, message, userAction, cause) {
181
+ super(message, cause);
182
+ this.code = code;
183
+ this.userAction = userAction;
184
+ }
185
+ static unavailable(cause) {
186
+ return new _NetworkError(ErrorCode.NETWORK_UNAVAILABLE, "Cannot connect to server", "Please check your internet connection and try again.", cause);
187
+ }
188
+ static timeout(cause) {
189
+ return new _NetworkError(ErrorCode.NETWORK_TIMEOUT, "Request timed out", "The server took too long to respond. Please check your connection and try again.", cause);
190
+ }
191
+ static dnsFailed(host, cause) {
192
+ return new _NetworkError(ErrorCode.NETWORK_DNS_FAILED, `Cannot resolve hostname: ${host}`, "Please check your internet connection and DNS settings.", cause);
193
+ }
194
+ };
195
+ exports2.NetworkError = NetworkError;
196
+ }
17
197
  });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
198
+
199
+ // dist/auth/auth0-service.js
200
+ var require_auth0_service = __commonJS({
201
+ "dist/auth/auth0-service.js"(exports2) {
202
+ "use strict";
203
+ var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
204
+ if (k2 === void 0) k2 = k;
205
+ var desc = Object.getOwnPropertyDescriptor(m, k);
206
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
207
+ desc = { enumerable: true, get: function() {
208
+ return m[k];
209
+ } };
210
+ }
211
+ Object.defineProperty(o, k2, desc);
212
+ }) : (function(o, m, k, k2) {
213
+ if (k2 === void 0) k2 = k;
214
+ o[k2] = m[k];
215
+ }));
216
+ var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
217
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
218
+ }) : function(o, v) {
219
+ o["default"] = v;
220
+ });
221
+ var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
222
+ var ownKeys = function(o) {
223
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
224
+ var ar = [];
225
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
226
+ return ar;
24
227
  };
25
228
  return ownKeys(o);
26
- };
27
- return function (mod) {
229
+ };
230
+ return function(mod) {
28
231
  if (mod && mod.__esModule) return mod;
29
232
  var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
233
+ if (mod != null) {
234
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
235
+ }
236
+ __setModuleDefault2(result, mod);
32
237
  return result;
238
+ };
239
+ })();
240
+ Object.defineProperty(exports2, "__esModule", { value: true });
241
+ exports2.Auth0Service = void 0;
242
+ var http = __importStar2(require("http"));
243
+ var openid_client_1 = require("openid-client");
244
+ var url_1 = require("url");
245
+ var errors_1 = require_errors();
246
+ var AUTH_DISCOVERY_TIMEOUT_MS = 1e4;
247
+ openid_client_1.custom.setHttpOptionsDefaults({
248
+ timeout: AUTH_DISCOVERY_TIMEOUT_MS
249
+ });
250
+ var noopLogger = {
251
+ info: () => {
252
+ },
253
+ warn: () => {
254
+ },
255
+ error: () => {
256
+ },
257
+ debug: () => {
258
+ }
33
259
  };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.StandaloneConfigService = void 0;
37
- const fs = __importStar(require("node:fs"));
38
- const fsPromises = __importStar(require("node:fs/promises"));
39
- const path = __importStar(require("node:path"));
40
- const os = __importStar(require("node:os"));
41
- const crypto = __importStar(require("node:crypto"));
42
- const zod_1 = require("zod");
43
- const types_1 = require("../types");
44
- const index_js_1 = require("../auth/index.js");
45
- const logger_1 = require("../logger");
46
- // Constants
47
- const DEFAULT_CLIENT_ID_FOR_HASH = "default";
48
- const HASH_PREFIX_LENGTH = 8;
49
- const DEFAULT_ADMIN_COMPANY_DOMAIN = "none";
50
- const DEFAULT_SERVER_URL = "https://api.dataflint.io";
51
- const DEFAULT_AUTH_DOMAIN = "https://dataflint.us.auth0.com/";
52
- const DEFAULT_AUDIENCE = "https://api.dataflint.io";
53
- const DEFAULT_SCOPE = "openid profile email offline_access";
54
- const DEFAULT_PUBLIC_CLIENT_ID = "1NdbhkYoLyqQWtevBNal1BozB9pSZe3g";
55
- const CREDENTIALS_DIR_MODE = 0o700;
56
- const CREDENTIALS_FILE_MODE = 0o600;
57
- // Zod schema for config file validation
58
- const StandaloneConfigSchema = zod_1.z
59
- .object({
60
- serverUrl: zod_1.z.string().url().optional(),
61
- authDomain: zod_1.z.string().optional(),
62
- clientId: zod_1.z.string().optional(),
63
- audience: zod_1.z.string().optional(),
64
- scope: zod_1.z.string().optional(),
65
- credentialsPath: zod_1.z.string().optional(),
66
- adminCompanyDomain: zod_1.z.string().optional(),
67
- customerDomain: zod_1.z.string().optional(),
68
- m2mTokenPath: zod_1.z.string().optional(),
69
- m2mSecretName: zod_1.z.string().optional(),
70
- tenantId: zod_1.z.string().optional(),
71
- })
72
- .strict();
73
- class StandaloneConfigService {
74
- config;
75
- credentialsPath;
76
- m2mMode;
77
- constructor(config = {}) {
78
- this.config = this.mergeWithDefaults(config);
79
- this.m2mMode = this.detectM2MMode();
80
- this.validateM2MConfig();
81
- this.credentialsPath =
82
- config.credentialsPath || this.defaultCredentialsPath();
83
- this.ensureDataflintDirectory();
84
- }
85
- defaultCredentialsPath() {
86
- const hash = crypto
87
- .createHash("sha256")
88
- .update(this.config.clientId || DEFAULT_CLIENT_ID_FOR_HASH)
89
- .digest("hex")
90
- .substring(0, HASH_PREFIX_LENGTH);
91
- return path.join(os.homedir(), ".dataflint", `credentials-${hash}.json`);
92
- }
93
- ensureDataflintDirectory() {
94
- const dir = path.dirname(this.credentialsPath);
95
- if (!fs.existsSync(dir)) {
96
- fs.mkdirSync(dir, { recursive: true, mode: CREDENTIALS_DIR_MODE });
260
+ var Auth0Service = class {
261
+ config;
262
+ redirectUri;
263
+ callbackPort;
264
+ client = null;
265
+ issuer = null;
266
+ initialized = false;
267
+ openUrlHandler;
268
+ logger;
269
+ constructor(openUrlHandler, configProvider, logger, callbackPort = 11334) {
270
+ this.logger = logger || noopLogger;
271
+ this.openUrlHandler = openUrlHandler;
272
+ this.config = {
273
+ ...configProvider(),
274
+ scope: configProvider().scope || "openid profile email"
275
+ };
276
+ this.callbackPort = callbackPort;
277
+ this.redirectUri = `http://localhost:${callbackPort}/callback`;
278
+ this.logger.info(`Auth0Service initialized for domain: ${this.config.domain}`);
279
+ }
280
+ /**
281
+ * Initialize the Auth0 client by discovering the issuer metadata
282
+ */
283
+ async initialize() {
284
+ if (this.initialized) {
285
+ this.logger.debug("Auth0 client already initialized");
286
+ return;
97
287
  }
98
- }
99
- detectM2MMode() {
100
- const tokenPath = this.config.m2mTokenPath;
101
- const secretName = this.config.m2mSecretName;
102
- const tenantId = this.config.tenantId;
103
- const logger = logger_1.Logger.getInstance();
104
- if (tokenPath) {
105
- logger.info("M2M mode: Service Account");
106
- return { type: types_1.M2MType.SERVICE_ACCOUNT, tokenPath, tenantId };
107
- }
108
- if (secretName) {
109
- logger.info("M2M mode: Auth0 M2M");
110
- return { type: types_1.M2MType.AUTH0_M2M, secretName, tenantId };
111
- }
112
- return { type: types_1.M2MType.NONE };
113
- }
114
- validateM2MConfig() {
115
- if (this.m2mMode.type !== types_1.M2MType.NONE && !this.config.serverUrl) {
116
- throw new Error("DATAFLINT_SERVER_URL is required in M2M mode");
288
+ try {
289
+ const issuerUrl = this.config.domain.startsWith("http") ? this.config.domain : `https://${this.config.domain}`;
290
+ this.logger.info(`Attempting to discover Auth0 issuer at: ${issuerUrl}`);
291
+ this.logger.debug(`Discovery URL will be: ${issuerUrl}`);
292
+ this.issuer = await openid_client_1.Issuer.discover(issuerUrl);
293
+ this.logger.info(`Auth0 issuer discovered successfully: ${this.issuer.issuer}`);
294
+ this.client = new this.issuer.Client({
295
+ client_id: this.config.clientId,
296
+ redirect_uris: [this.redirectUri],
297
+ response_types: ["code"],
298
+ token_endpoint_auth_method: "none"
299
+ // Public client, no client secret required
300
+ });
301
+ this.initialized = true;
302
+ this.logger.info("Auth0 client initialized successfully");
303
+ } catch (error) {
304
+ this.logger.error("Failed to initialize Auth0 client", error);
305
+ this.logger.error(`Auth0 domain: ${this.config.domain}`);
306
+ this.logger.error(`Client ID: ${this.config.clientId}`);
307
+ this.logger.error(`Constructed issuer URL: ${this.config.domain.startsWith("http") ? this.config.domain : `https://${this.config.domain}`}`);
308
+ if (error instanceof Error) {
309
+ const message = error.message.toLowerCase();
310
+ if (message.includes("404") || message.includes("not found")) {
311
+ throw errors_1.ConfigError.invalid("Auth0 domain", this.config.domain, "a valid Auth0 domain (e.g., your-tenant.auth0.com)");
312
+ }
313
+ if (message.includes("enotfound") || message.includes("getaddrinfo")) {
314
+ throw errors_1.NetworkError.dnsFailed(this.config.domain, error);
315
+ }
316
+ if (message.includes("timeout") || message.includes("etimedout")) {
317
+ throw errors_1.AuthError.timeout(error);
318
+ }
319
+ if (message.includes("econnrefused") || message.includes("econnreset")) {
320
+ throw errors_1.NetworkError.unavailable(error);
321
+ }
322
+ }
323
+ throw new errors_1.AuthError("AUTH_NOT_INITIALIZED", `Auth0 initialization failed: ${error instanceof Error ? error.message : String(error)}`, "Please check your internet connection and Auth0 configuration.", false, error instanceof Error ? error : void 0);
117
324
  }
118
- }
119
- loadFileConfig() {
120
- const configFilePath = path.join(os.homedir(), ".dataflint", "config.json");
121
- if (!fs.existsSync(configFilePath)) {
122
- return {};
325
+ }
326
+ /**
327
+ * Start the authentication flow
328
+ */
329
+ async authenticate() {
330
+ if (!this.client) {
331
+ await this.initialize();
123
332
  }
124
- const logger = logger_1.Logger.getInstance();
333
+ if (!this.client) {
334
+ throw errors_1.AuthError.notInitialized();
335
+ }
336
+ const codeVerifier = openid_client_1.generators.codeVerifier();
337
+ const codeChallenge = openid_client_1.generators.codeChallenge(codeVerifier);
338
+ const authUrl = this.client.authorizationUrl({
339
+ scope: this.config.scope,
340
+ code_challenge: codeChallenge,
341
+ code_challenge_method: "S256",
342
+ ...this.config.audience && { audience: this.config.audience }
343
+ });
344
+ this.logger.info("Opening browser for authentication...");
125
345
  try {
126
- const rawContent = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
127
- const result = StandaloneConfigSchema.safeParse(rawContent);
128
- if (!result.success) {
129
- logger.warn(`Invalid config file format at ${configFilePath}: ${result.error.issues.map((i) => i.message).join(", ")}`);
130
- return {};
346
+ await this.openUrlHandler(authUrl);
347
+ } catch (error) {
348
+ this.logger.error("Failed to open browser", error);
349
+ this.logger.info(`Please manually navigate to: ${authUrl}`);
350
+ }
351
+ return new Promise((resolve, reject) => {
352
+ const server = http.createServer(async (req, res) => {
353
+ var _a;
354
+ try {
355
+ if (!((_a = req.url) == null ? void 0 : _a.startsWith("/callback"))) {
356
+ res.writeHead(404, { "Content-Type": "text/plain" });
357
+ res.end("Not Found");
358
+ return;
359
+ }
360
+ const callbackUrl = new url_1.URL(`http://localhost:${this.callbackPort}${req.url}`);
361
+ const params = this.client.callbackParams(callbackUrl.toString());
362
+ const tokenSet = await this.client.callback(this.redirectUri, params, {
363
+ code_verifier: codeVerifier
364
+ });
365
+ const authResult = this.processTokenSet(tokenSet);
366
+ res.writeHead(200, { "Content-Type": "text/html" });
367
+ res.end(`
368
+ <html>
369
+ <body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;">
370
+ <h2 style="color: #4CAF50;">Authentication Successful!</h2>
371
+ <p>You can now close this tab and return to VS Code/Cursor.</p>
372
+ <script>
373
+ setTimeout(() => {
374
+ window.close();
375
+ }, 3000);
376
+ </script>
377
+ </body>
378
+ </html>
379
+ `);
380
+ server.close();
381
+ resolve(authResult);
382
+ } catch (error) {
383
+ this.logger.error("Authentication callback error", error);
384
+ res.writeHead(400, { "Content-Type": "text/html" });
385
+ res.end(`
386
+ <html>
387
+ <body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;">
388
+ <h2 style="color: #f44336;">Authentication Failed</h2>
389
+ <p>Error: ${error}</p>
390
+ <p>Please try again.</p>
391
+ </body>
392
+ </html>
393
+ `);
394
+ server.close();
395
+ reject(error);
131
396
  }
132
- return result.data;
397
+ });
398
+ server.listen(this.callbackPort, () => {
399
+ this.logger.info(`Listening for Auth0 callback on http://localhost:${this.callbackPort}/callback`);
400
+ });
401
+ setTimeout(() => {
402
+ server.close();
403
+ reject(errors_1.AuthError.timeout());
404
+ }, 3e5);
405
+ });
406
+ }
407
+ /**
408
+ * Get user information using the access token
409
+ */
410
+ async getUserInfo(accessToken) {
411
+ if (!this.client) {
412
+ throw errors_1.AuthError.notInitialized();
133
413
  }
134
- catch (error) {
135
- logger.warn(`Failed to parse config file at ${configFilePath}: ${error instanceof Error ? error.message : String(error)}`);
136
- return {};
414
+ try {
415
+ this.logger.info("Fetching user information...");
416
+ const userInfo = await this.client.userinfo(accessToken);
417
+ this.logger.info("User information retrieved successfully");
418
+ this.logger.debug(`User ID: ${userInfo.sub}`);
419
+ return userInfo;
420
+ } catch (error) {
421
+ this.logger.error("Failed to get user info", error);
422
+ throw error;
137
423
  }
138
- }
139
- mergeWithDefaults(config) {
140
- const envConfig = {
141
- serverUrl: process.env.DATAFLINT_SERVER_URL,
142
- authDomain: process.env.DATAFLINT_AUTH_DOMAIN,
143
- clientId: process.env.DATAFLINT_CLIENT_ID,
144
- audience: process.env.DATAFLINT_AUDIENCE,
145
- scope: process.env.DATAFLINT_SCOPE,
146
- adminCompanyDomain: process.env.DATAFLINT_ADMIN_COMPANY_DOMAIN,
147
- customerDomain: process.env.DATAFLINT_CUSTOMER_DOMAIN,
148
- m2mTokenPath: process.env.M2M_SA_TOKEN_PATH,
149
- m2mSecretName: process.env.M2M_AUTH0_SECRET_NAME,
150
- tenantId: process.env.TENANT_ID,
424
+ }
425
+ /**
426
+ * Refresh the access token using refresh token
427
+ */
428
+ async refreshToken(refreshToken) {
429
+ if (!this.client) {
430
+ throw errors_1.AuthError.notInitialized();
431
+ }
432
+ try {
433
+ this.logger.info("Refreshing access token...");
434
+ const tokenSet = await this.client.refresh(refreshToken);
435
+ const result = this.processTokenSet(tokenSet);
436
+ this.logger.info("Token refresh completed successfully");
437
+ return result;
438
+ } catch (error) {
439
+ this.logger.error("Token refresh failed", error);
440
+ throw error;
441
+ }
442
+ }
443
+ /**
444
+ * Process token set and return structured result
445
+ */
446
+ processTokenSet(tokenSet) {
447
+ var _a;
448
+ const result = {
449
+ accessToken: tokenSet.access_token,
450
+ idToken: tokenSet.id_token,
451
+ refreshToken: tokenSet.refresh_token
151
452
  };
152
- const fileConfig = this.loadFileConfig();
153
- const logger = logger_1.Logger.getInstance();
154
- const customerDomain = config.customerDomain ||
155
- envConfig.customerDomain ||
156
- fileConfig.customerDomain;
157
- if (customerDomain) {
158
- // Customer domain provided - resolve customer-specific config
159
- logger.info(`Customer domain detected: ${customerDomain}`);
160
- const customerConfig = (0, index_js_1.getCustomerAuthConfig)(customerDomain);
161
- if (!customerConfig) {
162
- logger.error(`Unknown customer domain: ${customerDomain}`);
163
- throw new Error(`Unknown customer domain: "${customerDomain}". ` +
164
- `This customer is not registered in the system. ` +
165
- `Please check the domain name or contact support.`);
166
- }
167
- logger.info(`Using customer-specific configuration:`);
168
- logger.info(`Server URL: ${customerConfig.serverUrl}`);
169
- logger.info(`Auth0 Domain: ${customerConfig.domain}`);
170
- logger.info(`Client ID: ${customerConfig.clientId.substring(0, 8)}...`);
171
- // Return customer-specific configuration
172
- // Customer config takes precedence over everything else
173
- return {
174
- serverUrl: customerConfig.serverUrl,
175
- authDomain: customerConfig.domain,
176
- clientId: customerConfig.clientId,
177
- audience: customerConfig.audience,
178
- scope: DEFAULT_SCOPE,
179
- // Credentials path only configurable via CLI argument for security
180
- credentialsPath: config.credentialsPath,
181
- adminCompanyDomain: config.adminCompanyDomain ||
182
- envConfig.adminCompanyDomain ||
183
- fileConfig.adminCompanyDomain ||
184
- DEFAULT_ADMIN_COMPANY_DOMAIN,
185
- customerDomain: customerDomain,
186
- m2mTokenPath: config.m2mTokenPath ||
187
- envConfig.m2mTokenPath ||
188
- fileConfig.m2mTokenPath,
189
- m2mSecretName: config.m2mSecretName ||
190
- envConfig.m2mSecretName ||
191
- fileConfig.m2mSecretName,
192
- tenantId: config.tenantId ||
193
- envConfig.tenantId ||
194
- fileConfig.tenantId,
195
- };
453
+ if (tokenSet.expires_at) {
454
+ result.expiresAt = new Date(tokenSet.expires_at * 1e3);
455
+ }
456
+ this.logger.info("Authentication tokens processed successfully");
457
+ this.logger.debug(`Access Token: ${(_a = result.accessToken) == null ? void 0 : _a.substring(0, 20)}...`);
458
+ this.logger.debug(`ID Token: ${result.idToken ? "Present" : "Not provided"}`);
459
+ this.logger.debug(`Refresh Token: ${result.refreshToken ? "Present" : "Not provided"}`);
460
+ this.logger.debug(`Expires At: ${result.expiresAt}`);
461
+ return result;
462
+ }
463
+ /**
464
+ * Check if a token is expired
465
+ */
466
+ isTokenExpired(authResult) {
467
+ if (!authResult.expiresAt) {
468
+ this.logger.debug("No expiration time available, considering token valid");
469
+ return false;
470
+ }
471
+ const expiresAt = authResult.expiresAt instanceof Date ? authResult.expiresAt : new Date(authResult.expiresAt);
472
+ const now = /* @__PURE__ */ new Date();
473
+ const buffer = 5 * 60 * 1e3;
474
+ const isExpired = expiresAt.getTime() - buffer < now.getTime();
475
+ if (isExpired) {
476
+ this.logger.warn("Access token is expired or will expire soon");
477
+ } else {
478
+ this.logger.debug("Access token is still valid");
196
479
  }
197
- // No customer domain - use existing merge logic
198
- logger.info(`No customer domain - using default/explicit configuration`);
480
+ return isExpired;
481
+ }
482
+ /**
483
+ * Logout (revoke tokens if supported)
484
+ */
485
+ async logout(accessToken) {
486
+ if (!this.client) {
487
+ throw errors_1.AuthError.notInitialized();
488
+ }
489
+ try {
490
+ await this.client.revoke(accessToken);
491
+ this.logger.info("Token revoked successfully");
492
+ } catch (error) {
493
+ this.logger.error("Failed to revoke token", error);
494
+ }
495
+ }
496
+ };
497
+ exports2.Auth0Service = Auth0Service;
498
+ }
499
+ });
500
+
501
+ // dist/auth/auth0-m2m-service.js
502
+ var require_auth0_m2m_service = __commonJS({
503
+ "dist/auth/auth0-m2m-service.js"(exports2) {
504
+ "use strict";
505
+ Object.defineProperty(exports2, "__esModule", { value: true });
506
+ exports2.Auth0M2MService = void 0;
507
+ var types_12 = require_types();
508
+ var noopLogger = {
509
+ info: () => {
510
+ },
511
+ warn: () => {
512
+ },
513
+ error: () => {
514
+ },
515
+ debug: () => {
516
+ }
517
+ };
518
+ var Auth0M2MService = class _Auth0M2MService {
519
+ credentials;
520
+ tenantId;
521
+ tokenCache = null;
522
+ logger;
523
+ initialized = false;
524
+ /**
525
+ * Token expiry buffer in milliseconds (5 minutes)
526
+ * Tokens will be refreshed this long before actual expiration
527
+ */
528
+ static EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
529
+ constructor(credentials, tenantId, logger) {
530
+ this.credentials = credentials;
531
+ this.tenantId = tenantId;
532
+ this.logger = logger || noopLogger;
533
+ const clientIdPrefix = credentials.client_id.substring(0, 8);
534
+ this.logger.info(`Auth0M2MService created for client: ${clientIdPrefix}...`);
535
+ }
536
+ /**
537
+ * Get the strategy type identifier
538
+ */
539
+ getType() {
540
+ return types_12.AuthStrategyType.AUTH0_M2M;
541
+ }
542
+ /**
543
+ * Initialize the M2M service
544
+ * Validates credentials format and performs initial token fetch
545
+ */
546
+ async initialize() {
547
+ if (this.initialized) {
548
+ this.logger.debug("Auth0M2MService already initialized");
549
+ return;
550
+ }
551
+ this.logger.info("Initializing Auth0M2MService...");
552
+ if (!this.credentials.client_id || !this.credentials.client_secret) {
553
+ throw new Error("M2M credentials missing client_id or client_secret");
554
+ }
555
+ if (!this.credentials.domain) {
556
+ throw new Error("M2M credentials missing domain");
557
+ }
558
+ if (!this.credentials.audience) {
559
+ throw new Error("M2M credentials missing audience");
560
+ }
561
+ await this.fetchNewToken();
562
+ this.initialized = true;
563
+ this.logger.info("Auth0M2MService initialized successfully");
564
+ }
565
+ /**
566
+ * Get a valid access token, fetching a new one if cache is expired
567
+ */
568
+ async getToken() {
569
+ const now = Date.now();
570
+ if (this.tokenCache && now < this.tokenCache.expiresAt - _Auth0M2MService.EXPIRY_BUFFER_MS) {
571
+ this.logger.debug("Using cached M2M token");
572
+ return this.tokenCache.accessToken;
573
+ }
574
+ this.logger.info("M2M token expired or not cached, fetching new token...");
575
+ await this.fetchNewToken();
576
+ return this.tokenCache.accessToken;
577
+ }
578
+ /**
579
+ * Force refresh the token by clearing cache and fetching a new one
580
+ */
581
+ async refreshToken() {
582
+ this.logger.info("Force refreshing M2M token...");
583
+ this.tokenCache = null;
584
+ await this.fetchNewToken();
585
+ this.logger.info("M2M token refreshed");
586
+ }
587
+ /**
588
+ * Check if currently authenticated (credentials are valid)
589
+ */
590
+ async isAuthenticated() {
591
+ try {
592
+ await this.getToken();
593
+ return true;
594
+ } catch {
595
+ return false;
596
+ }
597
+ }
598
+ /**
599
+ * Get user information for the M2M client
600
+ * Returns synthetic user info since M2M clients don't have traditional user profiles
601
+ */
602
+ async getUserInfo() {
603
+ const clientIdPrefix = this.credentials.client_id.substring(0, 8);
199
604
  return {
200
- serverUrl: config.serverUrl ||
201
- envConfig.serverUrl ||
202
- fileConfig.serverUrl ||
203
- DEFAULT_SERVER_URL,
204
- authDomain: config.authDomain ||
205
- envConfig.authDomain ||
206
- fileConfig.authDomain ||
207
- DEFAULT_AUTH_DOMAIN,
208
- clientId: config.clientId ||
209
- envConfig.clientId ||
210
- fileConfig.clientId ||
211
- DEFAULT_PUBLIC_CLIENT_ID,
212
- audience: config.audience ||
213
- envConfig.audience ||
214
- fileConfig.audience ||
215
- DEFAULT_AUDIENCE,
216
- scope: config.scope ||
217
- envConfig.scope ||
218
- fileConfig.scope ||
219
- DEFAULT_SCOPE,
220
- adminCompanyDomain: config.adminCompanyDomain ||
221
- envConfig.adminCompanyDomain ||
222
- fileConfig.adminCompanyDomain ||
223
- DEFAULT_ADMIN_COMPANY_DOMAIN,
224
- // Credentials path only configurable via CLI argument for security
225
- credentialsPath: config.credentialsPath,
226
- customerDomain: undefined,
227
- m2mTokenPath: config.m2mTokenPath ||
228
- envConfig.m2mTokenPath ||
229
- fileConfig.m2mTokenPath,
230
- m2mSecretName: config.m2mSecretName ||
231
- envConfig.m2mSecretName ||
232
- fileConfig.m2mSecretName,
233
- tenantId: config.tenantId || envConfig.tenantId || fileConfig.tenantId,
605
+ sub: `m2m-client-${clientIdPrefix}`,
606
+ name: "M2M Client",
607
+ ...this.tenantId && { tenant_id: this.tenantId }
234
608
  };
235
- }
236
- // IConfigService interface implementation
237
- getServerUrl() {
238
- if (!this.config.serverUrl) {
239
- throw new Error("Server URL not configured. Set DATAFLINT_SERVER_URL environment variable or configure in ~/.dataflint/config.json");
609
+ }
610
+ /**
611
+ * Get the tenant ID associated with this M2M client
612
+ */
613
+ getTenantId() {
614
+ return this.tenantId;
615
+ }
616
+ /**
617
+ * Fetch a new token from Auth0 using client credentials grant
618
+ */
619
+ async fetchNewToken() {
620
+ const domain = this.credentials.domain.startsWith("http") ? this.credentials.domain : `https://${this.credentials.domain}`;
621
+ const tokenUrl = `${domain.replace(/\/$/, "")}/oauth/token`;
622
+ this.logger.debug(`Fetching M2M token from: ${tokenUrl}`);
623
+ const requestBody = {
624
+ grant_type: "client_credentials",
625
+ client_id: this.credentials.client_id,
626
+ client_secret: this.credentials.client_secret,
627
+ audience: this.credentials.audience
628
+ };
629
+ try {
630
+ const response = await fetch(tokenUrl, {
631
+ method: "POST",
632
+ headers: {
633
+ "Content-Type": "application/json"
634
+ },
635
+ body: JSON.stringify(requestBody)
636
+ });
637
+ if (!response.ok) {
638
+ this.logger.error(`M2M token request failed: ${response.status}`);
639
+ throw new Error(`Auth0 M2M token request failed with status ${response.status}`);
640
+ }
641
+ const tokenResponse = await response.json();
642
+ if (!tokenResponse.access_token) {
643
+ throw new Error("Auth0 response missing access_token");
644
+ }
645
+ const expiresIn = tokenResponse.expires_in || 3600;
646
+ const expiresAt = Date.now() + expiresIn * 1e3;
647
+ this.tokenCache = {
648
+ accessToken: tokenResponse.access_token,
649
+ expiresAt
650
+ };
651
+ const expiresInMinutes = Math.floor(expiresIn / 60);
652
+ this.logger.info(`M2M token obtained${this.tenantId ? ` for tenant ${this.tenantId}` : ""}: expires in ${expiresInMinutes} minutes`);
653
+ } catch (error) {
654
+ this.tokenCache = null;
655
+ if (error instanceof Error) {
656
+ this.logger.error("Failed to fetch M2M token", error);
657
+ throw error;
658
+ }
659
+ throw new Error(`Failed to fetch M2M token: ${error}`);
240
660
  }
241
- return this.config.serverUrl;
242
- }
243
- getEnvironment() {
244
- return "prod";
245
- }
246
- getCustomerDomain() {
247
- return this.config.customerDomain ?? null;
248
- }
249
- getAdminCompanyDomain() {
250
- return this.config.adminCompanyDomain ?? DEFAULT_ADMIN_COMPANY_DOMAIN;
251
- }
252
- getAuthConfig() {
253
- if (!this.config.authDomain) {
254
- throw new Error("Auth domain not configured. Set DATAFLINT_AUTH_DOMAIN environment variable or configure in ~/.dataflint/config.json");
661
+ }
662
+ };
663
+ exports2.Auth0M2MService = Auth0M2MService;
664
+ }
665
+ });
666
+
667
+ // dist/auth/service-account-service.js
668
+ var require_service_account_service = __commonJS({
669
+ "dist/auth/service-account-service.js"(exports2) {
670
+ "use strict";
671
+ var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
672
+ if (k2 === void 0) k2 = k;
673
+ var desc = Object.getOwnPropertyDescriptor(m, k);
674
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
675
+ desc = { enumerable: true, get: function() {
676
+ return m[k];
677
+ } };
678
+ }
679
+ Object.defineProperty(o, k2, desc);
680
+ }) : (function(o, m, k, k2) {
681
+ if (k2 === void 0) k2 = k;
682
+ o[k2] = m[k];
683
+ }));
684
+ var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
685
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
686
+ }) : function(o, v) {
687
+ o["default"] = v;
688
+ });
689
+ var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
690
+ var ownKeys = function(o) {
691
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
692
+ var ar = [];
693
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
694
+ return ar;
695
+ };
696
+ return ownKeys(o);
697
+ };
698
+ return function(mod) {
699
+ if (mod && mod.__esModule) return mod;
700
+ var result = {};
701
+ if (mod != null) {
702
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
255
703
  }
256
- if (!this.config.clientId) {
257
- throw new Error("Client ID not configured. Set DATAFLINT_CLIENT_ID environment variable or configure in ~/.dataflint/config.json");
704
+ __setModuleDefault2(result, mod);
705
+ return result;
706
+ };
707
+ })();
708
+ Object.defineProperty(exports2, "__esModule", { value: true });
709
+ exports2.ServiceAccountService = void 0;
710
+ var fs2 = __importStar2(require("fs"));
711
+ var types_12 = require_types();
712
+ var noopLogger = {
713
+ info: () => {
714
+ },
715
+ warn: () => {
716
+ },
717
+ error: () => {
718
+ },
719
+ debug: () => {
720
+ }
721
+ };
722
+ var ServiceAccountService = class {
723
+ tokenPath;
724
+ tenantId;
725
+ tokenCache = null;
726
+ logger;
727
+ constructor(tokenPath, tenantId, logger) {
728
+ this.tokenPath = tokenPath;
729
+ this.tenantId = tenantId;
730
+ this.logger = logger || noopLogger;
731
+ }
732
+ /**
733
+ * Get the strategy type identifier
734
+ */
735
+ getType() {
736
+ return types_12.AuthStrategyType.SERVICE_ACCOUNT;
737
+ }
738
+ /**
739
+ * Initialize the service account strategy
740
+ * Validates that the token file exists and is readable
741
+ */
742
+ async initialize() {
743
+ this.logger.info(`Initializing ServiceAccountService with token path: ${this.tokenPath}`);
744
+ if (!fs2.existsSync(this.tokenPath)) {
745
+ throw new Error(`Service account token file not found: ${this.tokenPath}`);
258
746
  }
259
- if (!this.config.audience) {
260
- throw new Error("Audience not configured. Set DATAFLINT_AUDIENCE environment variable or configure in ~/.dataflint/config.json");
747
+ await this.getToken();
748
+ this.logger.info("ServiceAccountService initialized successfully");
749
+ }
750
+ /**
751
+ * Get a valid access token, reading from file if cache is expired
752
+ */
753
+ async getToken() {
754
+ const now = Date.now();
755
+ const bufferMs = 5 * 60 * 1e3;
756
+ if (this.tokenCache && now < this.tokenCache.expiresAt - bufferMs) {
757
+ this.logger.debug("Using cached service account token");
758
+ return this.tokenCache.token;
261
759
  }
760
+ const rawToken = this.readTokenFromFile();
761
+ this.validateAndCacheToken(rawToken);
762
+ return this.tokenCache.token;
763
+ }
764
+ /**
765
+ * Force refresh the token by clearing cache and re-reading from file
766
+ */
767
+ async refreshToken() {
768
+ this.logger.info("Refreshing service account token...");
769
+ this.tokenCache = null;
770
+ await this.getToken();
771
+ this.logger.info("Service account token refreshed");
772
+ }
773
+ /**
774
+ * Check if currently authenticated (token file exists and is valid)
775
+ */
776
+ async isAuthenticated() {
777
+ try {
778
+ await this.getToken();
779
+ return true;
780
+ } catch {
781
+ return false;
782
+ }
783
+ }
784
+ /**
785
+ * Get user information for the service account
786
+ * Returns synthetic user info since service accounts don't have traditional user profiles
787
+ */
788
+ async getUserInfo() {
262
789
  return {
263
- domain: this.config.authDomain,
264
- clientId: this.config.clientId,
265
- audience: this.config.audience,
266
- scope: this.config.scope ?? DEFAULT_SCOPE,
790
+ sub: "m2m-service-account",
791
+ name: "M2M Service Account",
792
+ ...this.tenantId && { tenant_id: this.tenantId }
267
793
  };
268
- }
269
- async getAuthSecret() {
794
+ }
795
+ /**
796
+ * Get the tenant ID associated with this service account
797
+ */
798
+ getTenantId() {
799
+ return this.tenantId;
800
+ }
801
+ /**
802
+ * Read the token from the file system
803
+ */
804
+ readTokenFromFile() {
805
+ return fs2.readFileSync(this.tokenPath, "utf8");
806
+ }
807
+ /**
808
+ * Validate the token format and cache it with expiration
809
+ */
810
+ validateAndCacheToken(rawToken) {
811
+ const token = rawToken.trim();
812
+ if (!token) {
813
+ throw new Error("Service account token is empty");
814
+ }
815
+ const parts = token.split(".");
816
+ if (parts.length !== 3) {
817
+ throw new Error(`Invalid JWT format: expected 3 parts, got ${parts.length}`);
818
+ }
819
+ const expiresAt = this.extractExpiration(token);
820
+ const now = Date.now();
821
+ const expiresIn = Math.floor((expiresAt - now) / 1e3);
822
+ if (expiresAt <= now) {
823
+ throw new Error("Service account token is expired");
824
+ }
825
+ this.logger.info(`Service account token loaded${this.tenantId ? ` for tenant ${this.tenantId}` : ""}: expires in ${expiresIn}s (${new Date(expiresAt).toISOString()})`);
826
+ this.tokenCache = {
827
+ token,
828
+ expiresAt
829
+ };
830
+ }
831
+ /**
832
+ * Extract expiration time from JWT payload
833
+ */
834
+ extractExpiration(token) {
835
+ const parts = token.split(".");
270
836
  try {
271
- return await fsPromises.readFile(this.credentialsPath, "utf8");
837
+ const payload = parts[1];
838
+ const decoded = Buffer.from(payload, "base64url").toString("utf8");
839
+ const parsed = JSON.parse(decoded);
840
+ if (typeof parsed.exp === "number") {
841
+ return parsed.exp * 1e3;
842
+ }
843
+ this.logger.warn("JWT missing 'exp' field, using fallback expiration");
844
+ return Date.now() + 3e5;
845
+ } catch (error) {
846
+ this.logger.warn(`Failed to parse JWT expiration: ${error}, using fallback expiration`);
847
+ return Date.now() + 3e5;
848
+ }
849
+ }
850
+ };
851
+ exports2.ServiceAccountService = ServiceAccountService;
852
+ }
853
+ });
854
+
855
+ // dist/auth/secrets/aws-secrets-provider.js
856
+ var require_aws_secrets_provider = __commonJS({
857
+ "dist/auth/secrets/aws-secrets-provider.js"(exports2) {
858
+ "use strict";
859
+ Object.defineProperty(exports2, "__esModule", { value: true });
860
+ exports2.AWSSecretsProvider = void 0;
861
+ var noopLogger = {
862
+ info: () => {
863
+ },
864
+ warn: () => {
865
+ },
866
+ error: () => {
867
+ },
868
+ debug: () => {
869
+ }
870
+ };
871
+ var AWSSecretsProvider = class {
872
+ logger;
873
+ region;
874
+ constructor(logger) {
875
+ this.logger = logger || noopLogger;
876
+ this.region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
877
+ }
878
+ /**
879
+ * Get the provider name for logging
880
+ */
881
+ getName() {
882
+ return "AWS Secrets Manager";
883
+ }
884
+ /**
885
+ * Check if running in AWS environment with credentials available
886
+ */
887
+ async isAvailable() {
888
+ const hasRegion = !!(process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION);
889
+ const hasExecutionEnv = !!process.env.AWS_EXECUTION_ENV;
890
+ const hasCredentials = !!(process.env.AWS_ACCESS_KEY_ID || process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI || process.env.AWS_WEB_IDENTITY_TOKEN_FILE);
891
+ const isAWSEnvironment = hasRegion && (hasExecutionEnv || hasCredentials);
892
+ if (isAWSEnvironment) {
893
+ this.logger.debug("AWS environment detected");
894
+ } else {
895
+ this.logger.debug("Not in AWS environment");
272
896
  }
273
- catch (error) {
274
- const nodeError = error;
275
- if (nodeError.code === "ENOENT") {
276
- // File doesn't exist - this is expected, not an error
277
- return undefined;
897
+ return isAWSEnvironment;
898
+ }
899
+ /**
900
+ * Load Auth0 M2M credentials from AWS Secrets Manager
901
+ *
902
+ * @param secretName - The name or ARN of the secret in Secrets Manager
903
+ * @returns M2M credentials or null if not found
904
+ */
905
+ async loadAuth0M2MCredentials(secretName) {
906
+ this.logger.info(`Loading M2M credentials from AWS Secrets Manager: ${secretName}`);
907
+ try {
908
+ const { SecretsManagerClient, GetSecretValueCommand } = (
909
+ // @ts-expect-error - @aws-sdk/client-secrets-manager is an optional runtime dependency
910
+ await import("@aws-sdk/client-secrets-manager")
911
+ );
912
+ const client = new SecretsManagerClient({
913
+ region: this.region
914
+ });
915
+ const command = new GetSecretValueCommand({
916
+ SecretId: secretName
917
+ });
918
+ const response = await client.send(command);
919
+ if (!response.SecretString) {
920
+ this.logger.error("Secret value is empty or binary");
921
+ return null;
922
+ }
923
+ const secretValue = JSON.parse(response.SecretString);
924
+ if (!secretValue.client_id || !secretValue.client_secret || !secretValue.audience || !secretValue.domain) {
925
+ this.logger.error("Secret missing required fields (client_id, client_secret, audience, domain)");
926
+ return null;
927
+ }
928
+ this.logger.info("M2M credentials loaded from AWS Secrets Manager");
929
+ return {
930
+ client_id: secretValue.client_id,
931
+ client_secret: secretValue.client_secret,
932
+ audience: secretValue.audience,
933
+ domain: secretValue.domain
934
+ };
935
+ } catch (error) {
936
+ if (error instanceof Error) {
937
+ if (error.name === "ResourceNotFoundException") {
938
+ this.logger.warn(`Secret not found: ${secretName}`);
939
+ return null;
940
+ }
941
+ if (error.message.includes("Cannot find module")) {
942
+ this.logger.warn("AWS SDK not available - @aws-sdk/client-secrets-manager not installed");
943
+ return null;
278
944
  }
279
- logger_1.Logger.getInstance().warn(`Failed to read credentials from ${this.credentialsPath}: ${nodeError.message}`);
280
- return undefined;
945
+ this.logger.error("Failed to load secret from AWS", error);
946
+ }
947
+ return null;
281
948
  }
282
- }
283
- async setAuthSecret(value) {
284
- // Ensure directory exists
285
- this.ensureDataflintDirectory();
286
- // Write with restricted permissions (600)
287
- await fsPromises.writeFile(this.credentialsPath, value, {
288
- mode: CREDENTIALS_FILE_MODE,
289
- encoding: "utf8",
290
- });
291
- }
292
- async deleteAuthSecret() {
949
+ }
950
+ };
951
+ exports2.AWSSecretsProvider = AWSSecretsProvider;
952
+ }
953
+ });
954
+
955
+ // dist/auth/secrets/local-file-secrets-provider.js
956
+ var require_local_file_secrets_provider = __commonJS({
957
+ "dist/auth/secrets/local-file-secrets-provider.js"(exports2) {
958
+ "use strict";
959
+ var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
960
+ if (k2 === void 0) k2 = k;
961
+ var desc = Object.getOwnPropertyDescriptor(m, k);
962
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
963
+ desc = { enumerable: true, get: function() {
964
+ return m[k];
965
+ } };
966
+ }
967
+ Object.defineProperty(o, k2, desc);
968
+ }) : (function(o, m, k, k2) {
969
+ if (k2 === void 0) k2 = k;
970
+ o[k2] = m[k];
971
+ }));
972
+ var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
973
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
974
+ }) : function(o, v) {
975
+ o["default"] = v;
976
+ });
977
+ var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
978
+ var ownKeys = function(o) {
979
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
980
+ var ar = [];
981
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
982
+ return ar;
983
+ };
984
+ return ownKeys(o);
985
+ };
986
+ return function(mod) {
987
+ if (mod && mod.__esModule) return mod;
988
+ var result = {};
989
+ if (mod != null) {
990
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
991
+ }
992
+ __setModuleDefault2(result, mod);
993
+ return result;
994
+ };
995
+ })();
996
+ Object.defineProperty(exports2, "__esModule", { value: true });
997
+ exports2.LocalFileSecretsProvider = void 0;
998
+ var fs2 = __importStar2(require("fs"));
999
+ var path2 = __importStar2(require("path"));
1000
+ var os2 = __importStar2(require("os"));
1001
+ var noopLogger = {
1002
+ info: () => {
1003
+ },
1004
+ warn: () => {
1005
+ },
1006
+ error: () => {
1007
+ },
1008
+ debug: () => {
1009
+ }
1010
+ };
1011
+ var LocalFileSecretsProvider = class {
1012
+ logger;
1013
+ environment;
1014
+ secretFilePath;
1015
+ constructor(environment, logger) {
1016
+ this.logger = logger || noopLogger;
1017
+ this.environment = environment;
1018
+ this.secretFilePath = path2.join(os2.homedir(), ".dataflint", `m2m_secret.${environment}.json`);
1019
+ }
1020
+ /**
1021
+ * Get the provider name for logging
1022
+ */
1023
+ getName() {
1024
+ return "Local File";
1025
+ }
1026
+ /**
1027
+ * Check if the local secret file exists
1028
+ */
1029
+ async isAvailable() {
1030
+ const exists = fs2.existsSync(this.secretFilePath);
1031
+ if (exists) {
1032
+ this.logger.debug(`Local M2M secret file found: ${this.secretFilePath}`);
1033
+ } else {
1034
+ this.logger.debug(`Local M2M secret file not found: ${this.secretFilePath}`);
1035
+ }
1036
+ return exists;
1037
+ }
1038
+ /**
1039
+ * Load Auth0 M2M credentials from local file
1040
+ *
1041
+ * @param _secretName - Ignored, uses environment-based file path
1042
+ * @returns M2M credentials or null if not found or invalid
1043
+ */
1044
+ async loadAuth0M2MCredentials(_secretName) {
1045
+ this.logger.info(`Loading M2M credentials from local file: ${this.secretFilePath}`);
293
1046
  try {
294
- await fsPromises.unlink(this.credentialsPath);
1047
+ if (!fs2.existsSync(this.secretFilePath)) {
1048
+ this.logger.debug("Local secret file does not exist");
1049
+ return null;
1050
+ }
1051
+ const stats = fs2.statSync(this.secretFilePath);
1052
+ const mode = stats.mode & 511;
1053
+ if (mode !== 384) {
1054
+ this.logger.warn(`Secret file has insecure permissions: ${mode.toString(8)}. Should be 600.`);
1055
+ }
1056
+ const content = fs2.readFileSync(this.secretFilePath, "utf8");
1057
+ const secretValue = JSON.parse(content);
1058
+ if (!secretValue.client_id || !secretValue.client_secret || !secretValue.audience || !secretValue.domain) {
1059
+ this.logger.error("Local secret file missing required fields (client_id, client_secret, audience, domain)");
1060
+ return null;
1061
+ }
1062
+ this.logger.info("M2M credentials loaded from local file");
1063
+ return {
1064
+ client_id: secretValue.client_id,
1065
+ client_secret: secretValue.client_secret,
1066
+ audience: secretValue.audience,
1067
+ domain: secretValue.domain
1068
+ };
1069
+ } catch (error) {
1070
+ if (error instanceof SyntaxError) {
1071
+ this.logger.error("Failed to parse local secret file as JSON");
1072
+ } else {
1073
+ this.logger.error("Failed to load local secret file", error);
1074
+ }
1075
+ return null;
295
1076
  }
296
- catch (error) {
297
- const nodeError = error;
298
- if (nodeError.code === "ENOENT") {
299
- // File doesn't exist - nothing to delete
300
- return;
301
- }
302
- logger_1.Logger.getInstance().warn(`Failed to delete credentials at ${this.credentialsPath}: ${nodeError.message}`);
1077
+ }
1078
+ /**
1079
+ * Get the path to the secret file (for diagnostics)
1080
+ */
1081
+ getSecretFilePath() {
1082
+ return this.secretFilePath;
1083
+ }
1084
+ };
1085
+ exports2.LocalFileSecretsProvider = LocalFileSecretsProvider;
1086
+ }
1087
+ });
1088
+
1089
+ // dist/auth/secrets/secrets-provider.js
1090
+ var require_secrets_provider = __commonJS({
1091
+ "dist/auth/secrets/secrets-provider.js"(exports2) {
1092
+ "use strict";
1093
+ Object.defineProperty(exports2, "__esModule", { value: true });
1094
+ exports2.SecretsProvider = void 0;
1095
+ var aws_secrets_provider_1 = require_aws_secrets_provider();
1096
+ var local_file_secrets_provider_1 = require_local_file_secrets_provider();
1097
+ var noopLogger = {
1098
+ info: () => {
1099
+ },
1100
+ warn: () => {
1101
+ },
1102
+ error: () => {
1103
+ },
1104
+ debug: () => {
1105
+ }
1106
+ };
1107
+ var SecretsProvider = class {
1108
+ logger;
1109
+ providers;
1110
+ environment;
1111
+ constructor(environment, logger) {
1112
+ this.logger = logger || noopLogger;
1113
+ this.environment = environment;
1114
+ this.providers = [
1115
+ new aws_secrets_provider_1.AWSSecretsProvider(logger),
1116
+ new local_file_secrets_provider_1.LocalFileSecretsProvider(environment, logger)
1117
+ ];
1118
+ }
1119
+ /**
1120
+ * Get the provider name for logging
1121
+ */
1122
+ getName() {
1123
+ return "Composite Secrets Provider";
1124
+ }
1125
+ /**
1126
+ * Check if any provider is available
1127
+ */
1128
+ async isAvailable() {
1129
+ for (const provider of this.providers) {
1130
+ if (await provider.isAvailable()) {
1131
+ this.logger.debug(`Secrets provider available: ${provider.getName()}`);
1132
+ return true;
1133
+ }
1134
+ }
1135
+ this.logger.debug("No secrets providers available");
1136
+ return false;
1137
+ }
1138
+ /**
1139
+ * Load Auth0 M2M credentials from the first available provider
1140
+ *
1141
+ * @param secretName - The name of the secret (used for AWS, ignored for local file)
1142
+ * @returns M2M credentials or null if not found in any provider
1143
+ */
1144
+ async loadAuth0M2MCredentials(secretName) {
1145
+ this.logger.info("Attempting to load M2M credentials...");
1146
+ for (const provider of this.providers) {
1147
+ const providerName = provider.getName();
1148
+ if (!await provider.isAvailable()) {
1149
+ this.logger.debug(`Provider not available: ${providerName}`);
1150
+ continue;
1151
+ }
1152
+ this.logger.info(`Trying provider: ${providerName}`);
1153
+ const credentials = await provider.loadAuth0M2MCredentials(secretName);
1154
+ if (credentials) {
1155
+ this.logger.info(`M2M credentials loaded from: ${providerName}`);
1156
+ return credentials;
1157
+ }
1158
+ this.logger.debug(`No credentials found in provider: ${providerName}`);
303
1159
  }
1160
+ this.logger.info("No M2M credentials found in any provider");
1161
+ return null;
1162
+ }
1163
+ /**
1164
+ * Get the default secret name for M2M credentials based on environment
1165
+ *
1166
+ * @param environment - The environment (prod, staging, local)
1167
+ * @returns The default secret name
1168
+ */
1169
+ static getDefaultSecretName(environment) {
1170
+ return `auth0_m2m_databricks_loader_${environment}`;
1171
+ }
1172
+ };
1173
+ exports2.SecretsProvider = SecretsProvider;
1174
+ }
1175
+ });
1176
+
1177
+ // dist/auth/secrets/index.js
1178
+ var require_secrets = __commonJS({
1179
+ "dist/auth/secrets/index.js"(exports2) {
1180
+ "use strict";
1181
+ Object.defineProperty(exports2, "__esModule", { value: true });
1182
+ exports2.SecretsProvider = exports2.LocalFileSecretsProvider = exports2.AWSSecretsProvider = void 0;
1183
+ var aws_secrets_provider_1 = require_aws_secrets_provider();
1184
+ Object.defineProperty(exports2, "AWSSecretsProvider", { enumerable: true, get: function() {
1185
+ return aws_secrets_provider_1.AWSSecretsProvider;
1186
+ } });
1187
+ var local_file_secrets_provider_1 = require_local_file_secrets_provider();
1188
+ Object.defineProperty(exports2, "LocalFileSecretsProvider", { enumerable: true, get: function() {
1189
+ return local_file_secrets_provider_1.LocalFileSecretsProvider;
1190
+ } });
1191
+ var secrets_provider_1 = require_secrets_provider();
1192
+ Object.defineProperty(exports2, "SecretsProvider", { enumerable: true, get: function() {
1193
+ return secrets_provider_1.SecretsProvider;
1194
+ } });
1195
+ }
1196
+ });
1197
+
1198
+ // dist/auth/auth-strategy-factory.js
1199
+ var require_auth_strategy_factory = __commonJS({
1200
+ "dist/auth/auth-strategy-factory.js"(exports2) {
1201
+ "use strict";
1202
+ Object.defineProperty(exports2, "__esModule", { value: true });
1203
+ exports2.AuthStrategyFactory = void 0;
1204
+ var types_12 = require_types();
1205
+ var service_account_service_1 = require_service_account_service();
1206
+ var auth0_m2m_service_1 = require_auth0_m2m_service();
1207
+ var secrets_1 = require_secrets();
1208
+ var noopLogger = {
1209
+ info: () => {
1210
+ },
1211
+ warn: () => {
1212
+ },
1213
+ error: () => {
1214
+ },
1215
+ debug: () => {
1216
+ }
1217
+ };
1218
+ var AuthStrategyFactory = class {
1219
+ configProvider;
1220
+ logger;
1221
+ constructor(configProvider, logger) {
1222
+ this.configProvider = configProvider;
1223
+ this.logger = logger || noopLogger;
1224
+ }
1225
+ async createStrategy() {
1226
+ const m2mMode = this.configProvider.getM2MMode();
1227
+ switch (m2mMode.type) {
1228
+ case types_12.M2MType.SERVICE_ACCOUNT:
1229
+ return this.buildServiceAccountStrategy(m2mMode);
1230
+ case types_12.M2MType.AUTH0_M2M:
1231
+ return await this.buildAuth0M2MStrategy(m2mMode);
1232
+ default:
1233
+ this.logger.info("Using interactive OAuth flow");
1234
+ return {
1235
+ strategy: null,
1236
+ strategyType: types_12.AuthStrategyType.AUTH0_USER
1237
+ };
1238
+ }
1239
+ }
1240
+ buildServiceAccountStrategy(mode) {
1241
+ this.logger.info(`Service Account mode: ${mode.tokenPath}`);
1242
+ return {
1243
+ strategy: new service_account_service_1.ServiceAccountService(mode.tokenPath, mode.tenantId, this.logger),
1244
+ strategyType: types_12.AuthStrategyType.SERVICE_ACCOUNT
1245
+ };
1246
+ }
1247
+ async buildAuth0M2MStrategy(mode) {
1248
+ const secretsProvider = new secrets_1.SecretsProvider(this.configProvider.getEnvironment(), this.logger);
1249
+ if (!await secretsProvider.isAvailable()) {
1250
+ throw new Error(`Auth0 M2M mode requires a secrets provider. M2M_AUTH0_SECRET_NAME is set to "${mode.secretName}" but no secrets provider is available. Ensure AWS credentials are configured or use Service Account mode instead.`);
1251
+ }
1252
+ const credentials = await secretsProvider.loadAuth0M2MCredentials(mode.secretName);
1253
+ if (!credentials) {
1254
+ throw new Error(`Auth0 M2M credentials not found: "${mode.secretName}". Ensure the secret exists and contains valid Auth0 M2M credentials.`);
1255
+ }
1256
+ this.logger.info(`Auth0 M2M mode: ${mode.secretName}`);
1257
+ return {
1258
+ strategy: new auth0_m2m_service_1.Auth0M2MService(credentials, mode.tenantId, this.logger),
1259
+ strategyType: types_12.AuthStrategyType.AUTH0_M2M
1260
+ };
1261
+ }
1262
+ async isM2MAvailable() {
1263
+ const mode = this.configProvider.getM2MMode();
1264
+ if (mode.type === types_12.M2MType.SERVICE_ACCOUNT) {
1265
+ return true;
1266
+ }
1267
+ if (mode.type === types_12.M2MType.AUTH0_M2M) {
1268
+ const secretsProvider = new secrets_1.SecretsProvider(this.configProvider.getEnvironment(), this.logger);
1269
+ return secretsProvider.isAvailable();
1270
+ }
1271
+ return false;
1272
+ }
1273
+ };
1274
+ exports2.AuthStrategyFactory = AuthStrategyFactory;
1275
+ }
1276
+ });
1277
+
1278
+ // dist/auth/index.js
1279
+ var require_auth = __commonJS({
1280
+ "dist/auth/index.js"(exports2) {
1281
+ "use strict";
1282
+ var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
1283
+ if (k2 === void 0) k2 = k;
1284
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1285
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1286
+ desc = { enumerable: true, get: function() {
1287
+ return m[k];
1288
+ } };
1289
+ }
1290
+ Object.defineProperty(o, k2, desc);
1291
+ }) : (function(o, m, k, k2) {
1292
+ if (k2 === void 0) k2 = k;
1293
+ o[k2] = m[k];
1294
+ }));
1295
+ var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
1296
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1297
+ }) : function(o, v) {
1298
+ o["default"] = v;
1299
+ });
1300
+ var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
1301
+ var ownKeys = function(o) {
1302
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1303
+ var ar = [];
1304
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1305
+ return ar;
1306
+ };
1307
+ return ownKeys(o);
1308
+ };
1309
+ return function(mod) {
1310
+ if (mod && mod.__esModule) return mod;
1311
+ var result = {};
1312
+ if (mod != null) {
1313
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
1314
+ }
1315
+ __setModuleDefault2(result, mod);
1316
+ return result;
1317
+ };
1318
+ })();
1319
+ Object.defineProperty(exports2, "__esModule", { value: true });
1320
+ exports2.NetworkError = exports2.ConfigError = exports2.AuthError = exports2.DataFlintError = exports2.ErrorCode = exports2.SecretsProvider = exports2.LocalFileSecretsProvider = exports2.AWSSecretsProvider = exports2.AuthStrategyFactory = exports2.ServiceAccountService = exports2.Auth0M2MService = exports2.Auth0Service = exports2.M2MType = exports2.AuthStrategyType = exports2.customerAuthConfigs = void 0;
1321
+ exports2.getCustomerAuthConfig = getCustomerAuthConfig;
1322
+ var crypto2 = __importStar2(require("node:crypto"));
1323
+ var customer_auth_configs_1 = require_customer_auth_configs();
1324
+ Object.defineProperty(exports2, "customerAuthConfigs", { enumerable: true, get: function() {
1325
+ return customer_auth_configs_1.customerAuthConfigs;
1326
+ } });
1327
+ function getCustomerAuthConfig(customerDomain) {
1328
+ var _a;
1329
+ const customerHash = crypto2.createHash("sha256").update(customerDomain).digest("hex");
1330
+ const customerConfig = customer_auth_configs_1.customerAuthConfigs[customerHash];
1331
+ if (!customerConfig) {
1332
+ return null;
1333
+ }
1334
+ return {
1335
+ // Use custom Auth0 domain if domainProducer is defined, otherwise use default
1336
+ domain: ((_a = customerConfig.domainProducer) == null ? void 0 : _a.call(customerConfig, customerDomain)) || "https://dataflint.us.auth0.com/",
1337
+ // Customer-specific Auth0 client ID
1338
+ clientId: customerConfig.clientId,
1339
+ // Customer-specific API audience
1340
+ audience: `https://api.${customerDomain}.dataflint.io`,
1341
+ // Customer-specific server URL
1342
+ serverUrl: `https://api.${customerDomain}.dataflint.io`
1343
+ };
1344
+ }
1345
+ var types_12 = require_types();
1346
+ Object.defineProperty(exports2, "AuthStrategyType", { enumerable: true, get: function() {
1347
+ return types_12.AuthStrategyType;
1348
+ } });
1349
+ Object.defineProperty(exports2, "M2MType", { enumerable: true, get: function() {
1350
+ return types_12.M2MType;
1351
+ } });
1352
+ var auth0_service_1 = require_auth0_service();
1353
+ Object.defineProperty(exports2, "Auth0Service", { enumerable: true, get: function() {
1354
+ return auth0_service_1.Auth0Service;
1355
+ } });
1356
+ var auth0_m2m_service_1 = require_auth0_m2m_service();
1357
+ Object.defineProperty(exports2, "Auth0M2MService", { enumerable: true, get: function() {
1358
+ return auth0_m2m_service_1.Auth0M2MService;
1359
+ } });
1360
+ var service_account_service_1 = require_service_account_service();
1361
+ Object.defineProperty(exports2, "ServiceAccountService", { enumerable: true, get: function() {
1362
+ return service_account_service_1.ServiceAccountService;
1363
+ } });
1364
+ var auth_strategy_factory_1 = require_auth_strategy_factory();
1365
+ Object.defineProperty(exports2, "AuthStrategyFactory", { enumerable: true, get: function() {
1366
+ return auth_strategy_factory_1.AuthStrategyFactory;
1367
+ } });
1368
+ var secrets_1 = require_secrets();
1369
+ Object.defineProperty(exports2, "AWSSecretsProvider", { enumerable: true, get: function() {
1370
+ return secrets_1.AWSSecretsProvider;
1371
+ } });
1372
+ Object.defineProperty(exports2, "LocalFileSecretsProvider", { enumerable: true, get: function() {
1373
+ return secrets_1.LocalFileSecretsProvider;
1374
+ } });
1375
+ Object.defineProperty(exports2, "SecretsProvider", { enumerable: true, get: function() {
1376
+ return secrets_1.SecretsProvider;
1377
+ } });
1378
+ var errors_1 = require_errors();
1379
+ Object.defineProperty(exports2, "ErrorCode", { enumerable: true, get: function() {
1380
+ return errors_1.ErrorCode;
1381
+ } });
1382
+ Object.defineProperty(exports2, "DataFlintError", { enumerable: true, get: function() {
1383
+ return errors_1.DataFlintError;
1384
+ } });
1385
+ Object.defineProperty(exports2, "AuthError", { enumerable: true, get: function() {
1386
+ return errors_1.AuthError;
1387
+ } });
1388
+ Object.defineProperty(exports2, "ConfigError", { enumerable: true, get: function() {
1389
+ return errors_1.ConfigError;
1390
+ } });
1391
+ Object.defineProperty(exports2, "NetworkError", { enumerable: true, get: function() {
1392
+ return errors_1.NetworkError;
1393
+ } });
1394
+ }
1395
+ });
1396
+
1397
+ // dist/types.js
1398
+ var require_types2 = __commonJS({
1399
+ "dist/types.js"(exports2) {
1400
+ "use strict";
1401
+ Object.defineProperty(exports2, "__esModule", { value: true });
1402
+ exports2.M2MType = exports2.AuthStrategyType = void 0;
1403
+ var index_12 = require_auth();
1404
+ Object.defineProperty(exports2, "AuthStrategyType", { enumerable: true, get: function() {
1405
+ return index_12.AuthStrategyType;
1406
+ } });
1407
+ Object.defineProperty(exports2, "M2MType", { enumerable: true, get: function() {
1408
+ return index_12.M2MType;
1409
+ } });
1410
+ }
1411
+ });
1412
+
1413
+ // dist/logger.js
1414
+ var require_logger = __commonJS({
1415
+ "dist/logger.js"(exports2) {
1416
+ "use strict";
1417
+ Object.defineProperty(exports2, "__esModule", { value: true });
1418
+ exports2.Logger = void 0;
1419
+ var LOGGER_KEY = "__dataflint_mcp_logger__";
1420
+ var Logger = class {
1421
+ static setInstance(logger) {
1422
+ globalThis[LOGGER_KEY] = logger;
1423
+ }
1424
+ static getInstance() {
1425
+ const instance = globalThis[LOGGER_KEY];
1426
+ if (!instance) {
1427
+ throw new Error("Logger not initialized. Call Logger.setInstance() first.");
1428
+ }
1429
+ return instance;
1430
+ }
1431
+ static clear() {
1432
+ globalThis[LOGGER_KEY] = void 0;
1433
+ }
1434
+ };
1435
+ exports2.Logger = Logger;
1436
+ }
1437
+ });
1438
+
1439
+ // dist/standalone/config.js
1440
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
1441
+ if (k2 === void 0) k2 = k;
1442
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1443
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1444
+ desc = { enumerable: true, get: function() {
1445
+ return m[k];
1446
+ } };
1447
+ }
1448
+ Object.defineProperty(o, k2, desc);
1449
+ }) : (function(o, m, k, k2) {
1450
+ if (k2 === void 0) k2 = k;
1451
+ o[k2] = m[k];
1452
+ }));
1453
+ var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
1454
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1455
+ }) : function(o, v) {
1456
+ o["default"] = v;
1457
+ });
1458
+ var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
1459
+ var ownKeys = function(o) {
1460
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1461
+ var ar = [];
1462
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1463
+ return ar;
1464
+ };
1465
+ return ownKeys(o);
1466
+ };
1467
+ return function(mod) {
1468
+ if (mod && mod.__esModule) return mod;
1469
+ var result = {};
1470
+ if (mod != null) {
1471
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1472
+ }
1473
+ __setModuleDefault(result, mod);
1474
+ return result;
1475
+ };
1476
+ })();
1477
+ Object.defineProperty(exports, "__esModule", { value: true });
1478
+ exports.StandaloneConfigService = void 0;
1479
+ var fs = __importStar(require("node:fs"));
1480
+ var fsPromises = __importStar(require("node:fs/promises"));
1481
+ var path = __importStar(require("node:path"));
1482
+ var os = __importStar(require("node:os"));
1483
+ var crypto = __importStar(require("node:crypto"));
1484
+ var zod_1 = require("zod");
1485
+ var types_1 = require_types2();
1486
+ var index_1 = require_auth();
1487
+ var logger_1 = require_logger();
1488
+ var DEFAULT_CLIENT_ID_FOR_HASH = "default";
1489
+ var HASH_PREFIX_LENGTH = 8;
1490
+ var DEFAULT_ADMIN_COMPANY_DOMAIN = "none";
1491
+ var DEFAULT_SERVER_URL = "https://api.dataflint.io";
1492
+ var DEFAULT_AUTH_DOMAIN = "https://dataflint.us.auth0.com/";
1493
+ var DEFAULT_AUDIENCE = "https://api.dataflint.io";
1494
+ var DEFAULT_SCOPE = "openid profile email offline_access";
1495
+ var DEFAULT_PUBLIC_CLIENT_ID = "1NdbhkYoLyqQWtevBNal1BozB9pSZe3g";
1496
+ var CREDENTIALS_DIR_MODE = 448;
1497
+ var CREDENTIALS_FILE_MODE = 384;
1498
+ var StandaloneConfigSchema = zod_1.z.object({
1499
+ serverUrl: zod_1.z.string().url().optional(),
1500
+ authDomain: zod_1.z.string().optional(),
1501
+ clientId: zod_1.z.string().optional(),
1502
+ audience: zod_1.z.string().optional(),
1503
+ scope: zod_1.z.string().optional(),
1504
+ credentialsPath: zod_1.z.string().optional(),
1505
+ adminCompanyDomain: zod_1.z.string().optional(),
1506
+ customerDomain: zod_1.z.string().optional(),
1507
+ m2mTokenPath: zod_1.z.string().optional(),
1508
+ m2mSecretName: zod_1.z.string().optional(),
1509
+ tenantId: zod_1.z.string().optional()
1510
+ }).strict();
1511
+ var StandaloneConfigService = class {
1512
+ config;
1513
+ credentialsPath;
1514
+ m2mMode;
1515
+ constructor(config = {}) {
1516
+ this.config = this.mergeWithDefaults(config);
1517
+ this.m2mMode = this.detectM2MMode();
1518
+ this.validateM2MConfig();
1519
+ this.credentialsPath = config.credentialsPath || this.defaultCredentialsPath();
1520
+ this.ensureDataflintDirectory();
1521
+ }
1522
+ defaultCredentialsPath() {
1523
+ const hash = crypto.createHash("sha256").update(this.config.clientId || DEFAULT_CLIENT_ID_FOR_HASH).digest("hex").substring(0, HASH_PREFIX_LENGTH);
1524
+ return path.join(os.homedir(), ".dataflint", `credentials-${hash}.json`);
1525
+ }
1526
+ ensureDataflintDirectory() {
1527
+ const dir = path.dirname(this.credentialsPath);
1528
+ if (!fs.existsSync(dir)) {
1529
+ fs.mkdirSync(dir, { recursive: true, mode: CREDENTIALS_DIR_MODE });
1530
+ }
1531
+ }
1532
+ detectM2MMode() {
1533
+ const tokenPath = this.config.m2mTokenPath;
1534
+ const secretName = this.config.m2mSecretName;
1535
+ const tenantId = this.config.tenantId;
1536
+ const logger = logger_1.Logger.getInstance();
1537
+ if (tokenPath) {
1538
+ logger.info("M2M mode: Service Account");
1539
+ return { type: types_1.M2MType.SERVICE_ACCOUNT, tokenPath, tenantId };
1540
+ }
1541
+ if (secretName) {
1542
+ logger.info("M2M mode: Auth0 M2M");
1543
+ return { type: types_1.M2MType.AUTH0_M2M, secretName, tenantId };
1544
+ }
1545
+ return { type: types_1.M2MType.NONE };
1546
+ }
1547
+ validateM2MConfig() {
1548
+ if (this.m2mMode.type !== types_1.M2MType.NONE && !this.config.serverUrl) {
1549
+ throw new Error("DATAFLINT_SERVER_URL is required in M2M mode");
304
1550
  }
305
- getSendSourceCode() {
306
- const envValue = process.env.DATAFLINT_SEND_SOURCE_CODE;
307
- return envValue?.toLowerCase() === "true";
1551
+ }
1552
+ loadFileConfig() {
1553
+ const configFilePath = path.join(os.homedir(), ".dataflint", "config.json");
1554
+ if (!fs.existsSync(configFilePath)) {
1555
+ return {};
308
1556
  }
309
- getM2MMode() {
310
- return this.m2mMode;
1557
+ const logger = logger_1.Logger.getInstance();
1558
+ try {
1559
+ const rawContent = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
1560
+ const result = StandaloneConfigSchema.safeParse(rawContent);
1561
+ if (!result.success) {
1562
+ logger.warn(`Invalid config file format at ${configFilePath}: ${result.error.issues.map((i) => i.message).join(", ")}`);
1563
+ return {};
1564
+ }
1565
+ return result.data;
1566
+ } catch (error) {
1567
+ logger.warn(`Failed to parse config file at ${configFilePath}: ${error instanceof Error ? error.message : String(error)}`);
1568
+ return {};
1569
+ }
1570
+ }
1571
+ mergeWithDefaults(config) {
1572
+ const envConfig = {
1573
+ serverUrl: process.env.DATAFLINT_SERVER_URL,
1574
+ authDomain: process.env.DATAFLINT_AUTH_DOMAIN,
1575
+ clientId: process.env.DATAFLINT_CLIENT_ID,
1576
+ audience: process.env.DATAFLINT_AUDIENCE,
1577
+ scope: process.env.DATAFLINT_SCOPE,
1578
+ adminCompanyDomain: process.env.DATAFLINT_ADMIN_COMPANY_DOMAIN,
1579
+ customerDomain: process.env.DATAFLINT_CUSTOMER_DOMAIN,
1580
+ m2mTokenPath: process.env.M2M_SA_TOKEN_PATH,
1581
+ m2mSecretName: process.env.M2M_AUTH0_SECRET_NAME,
1582
+ tenantId: process.env.TENANT_ID
1583
+ };
1584
+ const fileConfig = this.loadFileConfig();
1585
+ const logger = logger_1.Logger.getInstance();
1586
+ const customerDomain = config.customerDomain || envConfig.customerDomain || fileConfig.customerDomain;
1587
+ if (customerDomain) {
1588
+ logger.info(`Customer domain detected: ${customerDomain}`);
1589
+ const customerConfig = (0, index_1.getCustomerAuthConfig)(customerDomain);
1590
+ if (!customerConfig) {
1591
+ logger.error(`Unknown customer domain: ${customerDomain}`);
1592
+ throw new Error(`Unknown customer domain: "${customerDomain}". This customer is not registered in the system. Please check the domain name or contact support.`);
1593
+ }
1594
+ logger.info(`Using customer-specific configuration:`);
1595
+ logger.info(`Server URL: ${customerConfig.serverUrl}`);
1596
+ logger.info(`Auth0 Domain: ${customerConfig.domain}`);
1597
+ logger.info(`Client ID: ${customerConfig.clientId.substring(0, 8)}...`);
1598
+ return {
1599
+ serverUrl: customerConfig.serverUrl,
1600
+ authDomain: customerConfig.domain,
1601
+ clientId: customerConfig.clientId,
1602
+ audience: customerConfig.audience,
1603
+ scope: DEFAULT_SCOPE,
1604
+ // Credentials path only configurable via CLI argument for security
1605
+ credentialsPath: config.credentialsPath,
1606
+ adminCompanyDomain: config.adminCompanyDomain || envConfig.adminCompanyDomain || fileConfig.adminCompanyDomain || DEFAULT_ADMIN_COMPANY_DOMAIN,
1607
+ customerDomain,
1608
+ m2mTokenPath: config.m2mTokenPath || envConfig.m2mTokenPath || fileConfig.m2mTokenPath,
1609
+ m2mSecretName: config.m2mSecretName || envConfig.m2mSecretName || fileConfig.m2mSecretName,
1610
+ tenantId: config.tenantId || envConfig.tenantId || fileConfig.tenantId
1611
+ };
1612
+ }
1613
+ logger.info(`No customer domain - using default/explicit configuration`);
1614
+ return {
1615
+ serverUrl: config.serverUrl || envConfig.serverUrl || fileConfig.serverUrl || DEFAULT_SERVER_URL,
1616
+ authDomain: config.authDomain || envConfig.authDomain || fileConfig.authDomain || DEFAULT_AUTH_DOMAIN,
1617
+ clientId: config.clientId || envConfig.clientId || fileConfig.clientId || DEFAULT_PUBLIC_CLIENT_ID,
1618
+ audience: config.audience || envConfig.audience || fileConfig.audience || DEFAULT_AUDIENCE,
1619
+ scope: config.scope || envConfig.scope || fileConfig.scope || DEFAULT_SCOPE,
1620
+ adminCompanyDomain: config.adminCompanyDomain || envConfig.adminCompanyDomain || fileConfig.adminCompanyDomain || DEFAULT_ADMIN_COMPANY_DOMAIN,
1621
+ // Credentials path only configurable via CLI argument for security
1622
+ credentialsPath: config.credentialsPath,
1623
+ customerDomain: void 0,
1624
+ m2mTokenPath: config.m2mTokenPath || envConfig.m2mTokenPath || fileConfig.m2mTokenPath,
1625
+ m2mSecretName: config.m2mSecretName || envConfig.m2mSecretName || fileConfig.m2mSecretName,
1626
+ tenantId: config.tenantId || envConfig.tenantId || fileConfig.tenantId
1627
+ };
1628
+ }
1629
+ // IConfigService interface implementation
1630
+ getServerUrl() {
1631
+ if (!this.config.serverUrl) {
1632
+ throw new Error("Server URL not configured. Set DATAFLINT_SERVER_URL environment variable or configure in ~/.dataflint/config.json");
1633
+ }
1634
+ return this.config.serverUrl;
1635
+ }
1636
+ getEnvironment() {
1637
+ return "prod";
1638
+ }
1639
+ getCustomerDomain() {
1640
+ return this.config.customerDomain ?? null;
1641
+ }
1642
+ getAdminCompanyDomain() {
1643
+ return this.config.adminCompanyDomain ?? DEFAULT_ADMIN_COMPANY_DOMAIN;
1644
+ }
1645
+ getAuthConfig() {
1646
+ if (!this.config.authDomain) {
1647
+ throw new Error("Auth domain not configured. Set DATAFLINT_AUTH_DOMAIN environment variable or configure in ~/.dataflint/config.json");
1648
+ }
1649
+ if (!this.config.clientId) {
1650
+ throw new Error("Client ID not configured. Set DATAFLINT_CLIENT_ID environment variable or configure in ~/.dataflint/config.json");
1651
+ }
1652
+ if (!this.config.audience) {
1653
+ throw new Error("Audience not configured. Set DATAFLINT_AUDIENCE environment variable or configure in ~/.dataflint/config.json");
1654
+ }
1655
+ return {
1656
+ domain: this.config.authDomain,
1657
+ clientId: this.config.clientId,
1658
+ audience: this.config.audience,
1659
+ scope: this.config.scope ?? DEFAULT_SCOPE
1660
+ };
1661
+ }
1662
+ async getAuthSecret() {
1663
+ try {
1664
+ return await fsPromises.readFile(this.credentialsPath, "utf8");
1665
+ } catch (error) {
1666
+ const nodeError = error;
1667
+ if (nodeError.code === "ENOENT") {
1668
+ return void 0;
1669
+ }
1670
+ logger_1.Logger.getInstance().warn(`Failed to read credentials from ${this.credentialsPath}: ${nodeError.message}`);
1671
+ return void 0;
311
1672
  }
312
- getTenantId() {
313
- return this.config.tenantId;
1673
+ }
1674
+ async setAuthSecret(value) {
1675
+ this.ensureDataflintDirectory();
1676
+ await fsPromises.writeFile(this.credentialsPath, value, {
1677
+ mode: CREDENTIALS_FILE_MODE,
1678
+ encoding: "utf8"
1679
+ });
1680
+ }
1681
+ async deleteAuthSecret() {
1682
+ try {
1683
+ await fsPromises.unlink(this.credentialsPath);
1684
+ } catch (error) {
1685
+ const nodeError = error;
1686
+ if (nodeError.code === "ENOENT") {
1687
+ return;
1688
+ }
1689
+ logger_1.Logger.getInstance().warn(`Failed to delete credentials at ${this.credentialsPath}: ${nodeError.message}`);
314
1690
  }
315
- }
1691
+ }
1692
+ getSendSourceCode() {
1693
+ const envValue = process.env.DATAFLINT_SEND_SOURCE_CODE;
1694
+ return (envValue == null ? void 0 : envValue.toLowerCase()) === "true";
1695
+ }
1696
+ getM2MMode() {
1697
+ return this.m2mMode;
1698
+ }
1699
+ getTenantId() {
1700
+ return this.config.tenantId;
1701
+ }
1702
+ };
316
1703
  exports.StandaloneConfigService = StandaloneConfigService;
317
- //# sourceMappingURL=config.js.map
1704
+ //# sourceMappingURL=config.js.map