cyrus-ai 0.2.49 → 0.2.50
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.
- package/dist/src/Application.d.ts +3 -1
- package/dist/src/Application.d.ts.map +1 -1
- package/dist/src/Application.js +14 -16
- package/dist/src/Application.js.map +1 -1
- package/dist/src/app.js +42 -7
- package/dist/src/app.js.map +1 -1
- package/dist/src/services/Logger.d.ts +8 -1
- package/dist/src/services/Logger.d.ts.map +1 -1
- package/dist/src/services/Logger.js +9 -0
- package/dist/src/services/Logger.js.map +1 -1
- package/dist/src/services/SentryErrorReporter.d.ts +67 -0
- package/dist/src/services/SentryErrorReporter.d.ts.map +1 -0
- package/dist/src/services/SentryErrorReporter.js +125 -0
- package/dist/src/services/SentryErrorReporter.js.map +1 -0
- package/dist/src/services/createErrorReporter.d.ts +33 -0
- package/dist/src/services/createErrorReporter.d.ts.map +1 -0
- package/dist/src/services/createErrorReporter.js +130 -0
- package/dist/src/services/createErrorReporter.js.map +1 -0
- package/dist/src/services/sentryScrubber.d.ts +29 -0
- package/dist/src/services/sentryScrubber.d.ts.map +1 -0
- package/dist/src/services/sentryScrubber.js +175 -0
- package/dist/src/services/sentryScrubber.js.map +1 -0
- package/package.json +8 -7
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ErrorReporter } from "cyrus-core";
|
|
1
2
|
import { GitService, SharedApplicationServer } from "cyrus-edge-worker";
|
|
2
3
|
import { ConfigService } from "./services/ConfigService.js";
|
|
3
4
|
import { Logger } from "./services/Logger.js";
|
|
@@ -12,12 +13,13 @@ export declare class Application {
|
|
|
12
13
|
readonly worker: WorkerService;
|
|
13
14
|
readonly logger: Logger;
|
|
14
15
|
readonly version: string;
|
|
16
|
+
readonly errorReporter: ErrorReporter;
|
|
15
17
|
private envWatcher?;
|
|
16
18
|
private configWatcher?;
|
|
17
19
|
private isInSetupWaitingMode;
|
|
18
20
|
private isInIdleMode;
|
|
19
21
|
private readonly envFilePath;
|
|
20
|
-
constructor(cyrusHome: string, customEnvPath?: string, version?: string);
|
|
22
|
+
constructor(cyrusHome: string, customEnvPath?: string, version?: string, errorReporter?: ErrorReporter);
|
|
21
23
|
/**
|
|
22
24
|
* Load environment variables from the configured env file path
|
|
23
25
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../src/Application.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../src/Application.ts"],"names":[],"mappings":"AAEA,OAAO,EAEN,KAAK,aAAa,EAGlB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAGxE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAI5D;;GAEG;AACH,qBAAa,WAAW;aAcN,SAAS,EAAE,MAAM;IAblC,SAAgB,MAAM,EAAE,aAAa,CAAC;IACtC,SAAgB,GAAG,EAAE,UAAU,CAAC;IAChC,SAAgB,MAAM,EAAE,aAAa,CAAC;IACtC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,aAAa,EAAE,aAAa,CAAC;IAC7C,OAAO,CAAC,UAAU,CAAC,CAA2B;IAC9C,OAAO,CAAC,aAAa,CAAC,CAA2B;IACjD,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAGpB,SAAS,EAAE,MAAM,EACjC,aAAa,CAAC,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,MAAM,EAChB,aAAa,GAAE,aAAuC;IAmCvD;;OAEG;IACH,OAAO,CAAC,WAAW;IASnB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsB3B;;;;;OAKG;IACH,OAAO,CAAC,yBAAyB;IAsBjC;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,mBAAmB,IAAI,OAAO;IAI9B;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAQ1D;;OAEG;IACH,sBAAsB,IAAI,IAAI;IAK9B;;OAEG;IACH,cAAc,IAAI,IAAI;IAKtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0D1B;;OAEG;YACW,sBAAsB;IA2BpC;;OAEG;YACW,sBAAsB;IA6CpC;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB/B;;OAEG;IACH,mBAAmB,IAAI,IAAI;CAqC3B"}
|
package/dist/src/Application.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, watch } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import { DEFAULT_PROXY_URL } from "cyrus-core";
|
|
3
|
+
import { DEFAULT_PROXY_URL, NoopErrorReporter, } from "cyrus-core";
|
|
4
4
|
import { GitService, SharedApplicationServer } from "cyrus-edge-worker";
|
|
5
5
|
import dotenv from "dotenv";
|
|
6
6
|
import { DEFAULT_SERVER_PORT, parsePort } from "./config/constants.js";
|
|
@@ -19,17 +19,20 @@ export class Application {
|
|
|
19
19
|
worker;
|
|
20
20
|
logger;
|
|
21
21
|
version;
|
|
22
|
+
errorReporter;
|
|
22
23
|
envWatcher;
|
|
23
24
|
configWatcher;
|
|
24
25
|
isInSetupWaitingMode = false;
|
|
25
26
|
isInIdleMode = false;
|
|
26
27
|
envFilePath;
|
|
27
|
-
constructor(cyrusHome, customEnvPath, version) {
|
|
28
|
+
constructor(cyrusHome, customEnvPath, version, errorReporter = new NoopErrorReporter()) {
|
|
28
29
|
this.cyrusHome = cyrusHome;
|
|
29
30
|
// Initialize logger first
|
|
30
31
|
this.logger = new Logger();
|
|
31
32
|
// Store version
|
|
32
33
|
this.version = version || "unknown";
|
|
34
|
+
// Error reporter (Sentry or noop). Injected so tests can supply a fake.
|
|
35
|
+
this.errorReporter = errorReporter;
|
|
33
36
|
// Determine the env file path: use custom path if provided, otherwise default to ~/.cyrus/.env
|
|
34
37
|
this.envFilePath = customEnvPath || join(cyrusHome, ".env");
|
|
35
38
|
// Ensure required directories exist
|
|
@@ -254,6 +257,8 @@ export class Application {
|
|
|
254
257
|
this.configWatcher.close();
|
|
255
258
|
}
|
|
256
259
|
await this.worker.stop();
|
|
260
|
+
// Flush any buffered Sentry events before exiting
|
|
261
|
+
await this.errorReporter.flush(2000).catch(() => false);
|
|
257
262
|
process.exit(0);
|
|
258
263
|
}
|
|
259
264
|
/**
|
|
@@ -268,12 +273,11 @@ export class Application {
|
|
|
268
273
|
this.logger.info("\nReceived SIGTERM, shutting down gracefully...");
|
|
269
274
|
void this.shutdown();
|
|
270
275
|
});
|
|
271
|
-
// Handle uncaught exceptions and unhandled promise rejections
|
|
276
|
+
// Handle uncaught exceptions and unhandled promise rejections.
|
|
277
|
+
// Logger.error forwards the Error arg to the global ErrorReporter, so we
|
|
278
|
+
// don't need to call captureException explicitly here.
|
|
272
279
|
process.on("uncaughtException", (error) => {
|
|
273
|
-
this.logger.error(`🚨 Uncaught Exception: ${error.message}
|
|
274
|
-
this.logger.error(`Error type: ${error.constructor.name}`);
|
|
275
|
-
this.logger.error(`Stack: ${error.stack}`);
|
|
276
|
-
this.logger.error("This error was caught by the global handler, preventing application crash");
|
|
280
|
+
this.logger.error(`🚨 Uncaught Exception: ${error.message} (type: ${error.constructor.name}). This error was caught by the global handler, preventing application crash.`, error);
|
|
277
281
|
// Attempt graceful shutdown but don't wait indefinitely
|
|
278
282
|
this.shutdown().finally(() => {
|
|
279
283
|
this.logger.error("Process exiting due to uncaught exception");
|
|
@@ -281,15 +285,9 @@ export class Application {
|
|
|
281
285
|
});
|
|
282
286
|
});
|
|
283
287
|
process.on("unhandledRejection", (reason, promise) => {
|
|
284
|
-
|
|
285
|
-
this.logger.error(
|
|
286
|
-
|
|
287
|
-
// Log stack trace if reason is an Error
|
|
288
|
-
if (reason instanceof Error && reason.stack) {
|
|
289
|
-
this.logger.error(`Stack: ${reason.stack}`);
|
|
290
|
-
}
|
|
291
|
-
// Log the error but don't exit the process for promise rejections
|
|
292
|
-
// as they might be recoverable
|
|
288
|
+
const error = reason instanceof Error ? reason : new Error(String(reason));
|
|
289
|
+
this.logger.error(`🚨 Unhandled Promise Rejection at: ${promise}. This rejection was caught by the global handler, continuing operation.`, error);
|
|
290
|
+
// Don't exit for promise rejections — they might be recoverable.
|
|
293
291
|
});
|
|
294
292
|
}
|
|
295
293
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Application.js","sourceRoot":"","sources":["../../src/Application.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"Application.js","sourceRoot":"","sources":["../../src/Application.ts"],"names":[],"mappings":"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"}
|
package/dist/src/app.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { Command } from "commander";
|
|
7
|
+
import { setGlobalErrorReporter } from "cyrus-core";
|
|
8
|
+
import dotenv from "dotenv";
|
|
7
9
|
import { Application } from "./Application.js";
|
|
8
10
|
import { AuthCommand } from "./commands/AuthCommand.js";
|
|
9
11
|
import { CheckTokensCommand } from "./commands/CheckTokensCommand.js";
|
|
@@ -11,6 +13,7 @@ import { RefreshTokenCommand } from "./commands/RefreshTokenCommand.js";
|
|
|
11
13
|
import { SelfAddRepoCommand } from "./commands/SelfAddRepoCommand.js";
|
|
12
14
|
import { SelfAuthCommand } from "./commands/SelfAuthCommand.js";
|
|
13
15
|
import { StartCommand } from "./commands/StartCommand.js";
|
|
16
|
+
import { createErrorReporter } from "./services/createErrorReporter.js";
|
|
14
17
|
// Get the directory of the current module for reading package.json
|
|
15
18
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
19
|
const __dirname = dirname(__filename);
|
|
@@ -18,6 +21,17 @@ const __dirname = dirname(__filename);
|
|
|
18
21
|
// When compiled, this is in dist/src/, so we need to go up two levels
|
|
19
22
|
const packageJsonPath = resolve(__dirname, "..", "..", "package.json");
|
|
20
23
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
24
|
+
// Pre-load env vars from the resolved .env file before initialising Sentry, so
|
|
25
|
+
// that CYRUS_SENTRY_DISABLED / CYRUS_SENTRY_DSN take effect on the first run.
|
|
26
|
+
// We re-resolve the path inside Application using the same precedence (CLI
|
|
27
|
+
// flag wins); this preliminary load only honours CYRUS_HOME and the default.
|
|
28
|
+
preloadEnvForBootstrap();
|
|
29
|
+
// Initialise the error reporter as early as possible so that exceptions
|
|
30
|
+
// thrown by subsequent imports/bootstrap are captured. Install it as the
|
|
31
|
+
// process-wide reporter so that every Logger.error(...) call across the
|
|
32
|
+
// codebase forwards to Sentry automatically.
|
|
33
|
+
const errorReporter = createErrorReporter({ release: packageJson.version });
|
|
34
|
+
setGlobalErrorReporter(errorReporter);
|
|
21
35
|
// Setup Commander program
|
|
22
36
|
const program = new Command();
|
|
23
37
|
program
|
|
@@ -32,7 +46,7 @@ program
|
|
|
32
46
|
.description("Start the edge worker")
|
|
33
47
|
.action(async () => {
|
|
34
48
|
const opts = program.opts();
|
|
35
|
-
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version);
|
|
49
|
+
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version, errorReporter);
|
|
36
50
|
await new StartCommand(app).execute([]);
|
|
37
51
|
});
|
|
38
52
|
// Auth command
|
|
@@ -41,7 +55,7 @@ program
|
|
|
41
55
|
.description("Authenticate with Cyrus using auth key")
|
|
42
56
|
.action(async (authKey) => {
|
|
43
57
|
const opts = program.opts();
|
|
44
|
-
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version);
|
|
58
|
+
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version, errorReporter);
|
|
45
59
|
await new AuthCommand(app).execute([authKey]);
|
|
46
60
|
});
|
|
47
61
|
// Check tokens command
|
|
@@ -50,7 +64,7 @@ program
|
|
|
50
64
|
.description("Check the status of all Linear tokens")
|
|
51
65
|
.action(async () => {
|
|
52
66
|
const opts = program.opts();
|
|
53
|
-
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version);
|
|
67
|
+
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version, errorReporter);
|
|
54
68
|
await new CheckTokensCommand(app).execute([]);
|
|
55
69
|
});
|
|
56
70
|
// Refresh token command
|
|
@@ -59,7 +73,7 @@ program
|
|
|
59
73
|
.description("Refresh a specific Linear token")
|
|
60
74
|
.action(async () => {
|
|
61
75
|
const opts = program.opts();
|
|
62
|
-
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version);
|
|
76
|
+
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version, errorReporter);
|
|
63
77
|
await new RefreshTokenCommand(app).execute([]);
|
|
64
78
|
});
|
|
65
79
|
// Self-auth-linear command - Linear OAuth directly from CLI
|
|
@@ -68,7 +82,7 @@ program
|
|
|
68
82
|
.description("Authenticate with Linear OAuth directly")
|
|
69
83
|
.action(async () => {
|
|
70
84
|
const opts = program.opts();
|
|
71
|
-
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version);
|
|
85
|
+
const app = new Application(opts.cyrusHome, opts.envFile, packageJson.version, errorReporter);
|
|
72
86
|
await new SelfAuthCommand(app).execute([]);
|
|
73
87
|
});
|
|
74
88
|
// Self-add-repo command - Clone and add repository
|
|
@@ -95,8 +109,29 @@ program
|
|
|
95
109
|
await program.parseAsync(process.argv);
|
|
96
110
|
}
|
|
97
111
|
catch (error) {
|
|
112
|
+
errorReporter.captureException(error, { tags: { phase: "bootstrap" } });
|
|
113
|
+
await errorReporter.flush(2000).catch(() => false);
|
|
98
114
|
console.error("Fatal error:", error);
|
|
99
115
|
process.exit(1);
|
|
100
116
|
}
|
|
101
117
|
})();
|
|
118
|
+
/**
|
|
119
|
+
* Best-effort env preload so the error reporter can read its config before the
|
|
120
|
+
* full {@link Application} bootstrap. We honour `--env-file` only as a literal
|
|
121
|
+
* argv lookup (Commander hasn't parsed yet) and otherwise fall back to the
|
|
122
|
+
* default `<cyrus-home>/.env` path.
|
|
123
|
+
*/
|
|
124
|
+
function preloadEnvForBootstrap() {
|
|
125
|
+
const argv = process.argv.slice(2);
|
|
126
|
+
const flagIdx = argv.indexOf("--env-file");
|
|
127
|
+
const cyrusHomeIdx = argv.indexOf("--cyrus-home");
|
|
128
|
+
const envFile = flagIdx >= 0 ? argv[flagIdx + 1] : undefined;
|
|
129
|
+
const cyrusHome = cyrusHomeIdx >= 0 && argv[cyrusHomeIdx + 1]
|
|
130
|
+
? argv[cyrusHomeIdx + 1]
|
|
131
|
+
: resolve(homedir(), ".cyrus");
|
|
132
|
+
const path = envFile ?? join(cyrusHome, ".env");
|
|
133
|
+
if (existsSync(path)) {
|
|
134
|
+
dotenv.config({ path, override: false });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
102
137
|
//# sourceMappingURL=app.js.map
|
package/dist/src/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ILogger, type LogContext, type LogLevel } from "cyrus-core";
|
|
1
|
+
import { type ILogger, type LogContext, type LogEventAttributes, type LogLevel } from "cyrus-core";
|
|
2
2
|
export { LogLevel } from "cyrus-core";
|
|
3
3
|
/**
|
|
4
4
|
* Logger configuration options
|
|
@@ -44,6 +44,13 @@ export declare class Logger implements ILogger {
|
|
|
44
44
|
* Error log (highest priority)
|
|
45
45
|
*/
|
|
46
46
|
error(message: string, ...args: any[]): void;
|
|
47
|
+
/**
|
|
48
|
+
* Emit a named major event. Delegates to the core logger so event-stream
|
|
49
|
+
* forwarding goes through the same Sentry Logs gate as the rest of the
|
|
50
|
+
* codebase — keeps the CLI's presentation wrapper Liskov-compatible with
|
|
51
|
+
* the core ILogger contract.
|
|
52
|
+
*/
|
|
53
|
+
event(name: string, attributes?: LogEventAttributes): void;
|
|
47
54
|
/**
|
|
48
55
|
* Raw output without formatting (always outputs regardless of level)
|
|
49
56
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../src/services/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,kCAAkC;IAClC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,qBAAa,MAAO,YAAW,OAAO;IACrC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAU;gBAEhB,OAAO,GAAE,aAAkB;IASvC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI5C;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI9C;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI5C;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI1C;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ7B;;OAEG;IACH,OAAO,CAAC,MAAM,SAAK,GAAG,IAAI;IAI1B;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO;IAIzC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B;;OAEG;IACH,QAAQ,IAAI,QAAQ;CAGpB;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../src/services/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,kCAAkC;IAClC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,qBAAa,MAAO,YAAW,OAAO;IACrC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAU;gBAEhB,OAAO,GAAE,aAAkB;IASvC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI5C;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI9C;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI5C;;;;;OAKG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,kBAAkB,GAAG,IAAI;IAI1D;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI1C;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ7B;;OAEG;IACH,OAAO,CAAC,MAAM,SAAK,GAAG,IAAI;IAI1B;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO;IAIzC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B;;OAEG;IACH,QAAQ,IAAI,QAAQ;CAGpB;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,QAAe,CAAC"}
|
|
@@ -51,6 +51,15 @@ export class Logger {
|
|
|
51
51
|
error(message, ...args) {
|
|
52
52
|
this.coreLogger.error(message, ...args);
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Emit a named major event. Delegates to the core logger so event-stream
|
|
56
|
+
* forwarding goes through the same Sentry Logs gate as the rest of the
|
|
57
|
+
* codebase — keeps the CLI's presentation wrapper Liskov-compatible with
|
|
58
|
+
* the core ILogger contract.
|
|
59
|
+
*/
|
|
60
|
+
event(name, attributes) {
|
|
61
|
+
this.coreLogger.event(name, attributes);
|
|
62
|
+
}
|
|
54
63
|
/**
|
|
55
64
|
* Raw output without formatting (always outputs regardless of level)
|
|
56
65
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../../src/services/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,
|
|
1
|
+
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../../src/services/Logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as Sentry from "@sentry/node";
|
|
2
|
+
import type { ErrorReporter, ErrorReporterContext, ErrorReporterLogAttributes, ErrorReporterLogLevel, ErrorReporterSeverity } from "cyrus-core";
|
|
3
|
+
export interface SentryErrorReporterOptions {
|
|
4
|
+
dsn: string;
|
|
5
|
+
release?: string;
|
|
6
|
+
environment?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Tags applied to every event emitted by this reporter (e.g. `team_id` from
|
|
9
|
+
* `CYRUS_TEAM_ID`). See https://docs.sentry.io/platform-redirect/?next=/enriching-events/tags
|
|
10
|
+
*/
|
|
11
|
+
tags?: Record<string, string>;
|
|
12
|
+
/**
|
|
13
|
+
* Structured context block attached to every event under the `cyrus` key.
|
|
14
|
+
* Unlike tags, contexts are not indexed for search but support nested
|
|
15
|
+
* structured data — ideal for grouping related fields (team_id, version,
|
|
16
|
+
* environment, deployment) under one heading in the Sentry UI.
|
|
17
|
+
*/
|
|
18
|
+
structuredContext?: Record<string, unknown>;
|
|
19
|
+
/**
|
|
20
|
+
* Sample rate for error events. Sentry's default is 1.0 (send everything).
|
|
21
|
+
* Lower this if a high-volume error path needs sampling.
|
|
22
|
+
*/
|
|
23
|
+
sampleRate?: number;
|
|
24
|
+
/**
|
|
25
|
+
* If true, prints debug logs from the SDK itself. Decoupled from
|
|
26
|
+
* CYRUS_LOG_LEVEL — gate on the dedicated `CYRUS_SENTRY_DEBUG` env var so
|
|
27
|
+
* app-level debugging doesn't pull in the firehose of Sentry-internal
|
|
28
|
+
* tracing/transport chatter.
|
|
29
|
+
*/
|
|
30
|
+
debug?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Hook invoked before an event is sent. Returning null drops the event.
|
|
33
|
+
* Useful for redacting sensitive payloads in tests.
|
|
34
|
+
*/
|
|
35
|
+
beforeSend?: Parameters<typeof Sentry.init>[0] extends infer T ? T extends {
|
|
36
|
+
beforeSend?: infer F;
|
|
37
|
+
} ? F : never : never;
|
|
38
|
+
/**
|
|
39
|
+
* Hook invoked before a structured log entry is shipped to Sentry Logs.
|
|
40
|
+
* Distinct from {@link beforeSend} (which only runs on Issues events) —
|
|
41
|
+
* Logs have their own ingestion pipeline, so a separate redaction hook is
|
|
42
|
+
* required to keep secret-scrubbing symmetric across both paths.
|
|
43
|
+
*/
|
|
44
|
+
beforeSendLog?: Parameters<typeof Sentry.init>[0] extends infer T ? T extends {
|
|
45
|
+
beforeSendLog?: infer F;
|
|
46
|
+
} ? F : never : never;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Sentry-backed {@link ErrorReporter}.
|
|
50
|
+
*
|
|
51
|
+
* Single Responsibility: this class only knows how to translate Cyrus-shaped
|
|
52
|
+
* events into the Sentry SDK. It owns no application logic.
|
|
53
|
+
*
|
|
54
|
+
* The constructor initialises the Sentry SDK; therefore at most one instance
|
|
55
|
+
* should be created per process. Use {@link createErrorReporter} as the entry
|
|
56
|
+
* point — it enforces that contract along with the opt-out semantics.
|
|
57
|
+
*/
|
|
58
|
+
export declare class SentryErrorReporter implements ErrorReporter {
|
|
59
|
+
readonly isEnabled = true;
|
|
60
|
+
private readonly globalLogAttributes;
|
|
61
|
+
constructor(options: SentryErrorReporterOptions);
|
|
62
|
+
captureException(error: unknown, context?: ErrorReporterContext): void;
|
|
63
|
+
captureMessage(message: string, severity?: ErrorReporterSeverity, context?: ErrorReporterContext): void;
|
|
64
|
+
log(level: ErrorReporterLogLevel, message: string, attributes?: ErrorReporterLogAttributes): void;
|
|
65
|
+
flush(timeoutMs?: number): Promise<boolean>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=SentryErrorReporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SentryErrorReporter.d.ts","sourceRoot":"","sources":["../../../src/services/SentryErrorReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,EACX,aAAa,EACb,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA0B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,GAC3D,CAAC,SAAS;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAA;KAAE,GACjC,CAAC,GACD,KAAK,GACN,KAAK,CAAC;IACT;;;;;OAKG;IACH,aAAa,CAAC,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,GAC9D,CAAC,SAAS;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAA;KAAE,GACpC,CAAC,GACD,KAAK,GACN,KAAK,CAAC;CACT;AAED;;;;;;;;;GASG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACxD,QAAQ,CAAC,SAAS,QAAQ;IAE1B,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA6B;gBAErD,OAAO,EAAE,0BAA0B;IAwC/C,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI;IAOtE,cAAc,CACb,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,qBAA8B,EACxC,OAAO,CAAC,EAAE,oBAAoB,GAC5B,IAAI;IAOP,GAAG,CACF,KAAK,EAAE,qBAAqB,EAC5B,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,0BAA0B,GACrC,IAAI;IA6BD,KAAK,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/C"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as Sentry from "@sentry/node";
|
|
2
|
+
/**
|
|
3
|
+
* Sentry-backed {@link ErrorReporter}.
|
|
4
|
+
*
|
|
5
|
+
* Single Responsibility: this class only knows how to translate Cyrus-shaped
|
|
6
|
+
* events into the Sentry SDK. It owns no application logic.
|
|
7
|
+
*
|
|
8
|
+
* The constructor initialises the Sentry SDK; therefore at most one instance
|
|
9
|
+
* should be created per process. Use {@link createErrorReporter} as the entry
|
|
10
|
+
* point — it enforces that contract along with the opt-out semantics.
|
|
11
|
+
*/
|
|
12
|
+
export class SentryErrorReporter {
|
|
13
|
+
isEnabled = true;
|
|
14
|
+
globalLogAttributes;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
// Stash the global tag set (team_id, …) so every Sentry.logger.* call
|
|
17
|
+
// merges them into per-log attributes — Sentry Logs has a separate
|
|
18
|
+
// attributes store from event tags, so initialScope.tags doesn't reach
|
|
19
|
+
// it. https://docs.sentry.io/product/explore/logs/
|
|
20
|
+
this.globalLogAttributes = options.tags ? { ...options.tags } : {};
|
|
21
|
+
Sentry.init({
|
|
22
|
+
dsn: options.dsn,
|
|
23
|
+
release: options.release,
|
|
24
|
+
environment: options.environment ?? "production",
|
|
25
|
+
sampleRate: options.sampleRate ?? 1.0,
|
|
26
|
+
debug: options.debug ?? false,
|
|
27
|
+
// Performance monitoring is intentionally disabled — we only ship
|
|
28
|
+
// error tracking. Flip this on later if we need transaction data.
|
|
29
|
+
tracesSampleRate: 0,
|
|
30
|
+
// Issues and Logs share a single gate (CYRUS_TEAM_ID upstream); by
|
|
31
|
+
// the time we get here both are wanted, so always enable Logs.
|
|
32
|
+
enableLogs: true,
|
|
33
|
+
beforeSend: options.beforeSend,
|
|
34
|
+
beforeSendLog: options.beforeSendLog,
|
|
35
|
+
// Append integrations that enrich every event with structured data:
|
|
36
|
+
// - extraErrorDataIntegration walks Error subclasses and serialises
|
|
37
|
+
// non-standard own properties as `extra` (so e.g. `err.statusCode`,
|
|
38
|
+
// `err.requestId`, custom Cyrus error fields surface in Sentry).
|
|
39
|
+
// - consoleIntegration captures console.* output as breadcrumbs so
|
|
40
|
+
// events arrive with a structured trail of the last log lines.
|
|
41
|
+
integrations: (defaults) => [
|
|
42
|
+
...defaults,
|
|
43
|
+
Sentry.extraErrorDataIntegration({ depth: 4 }),
|
|
44
|
+
Sentry.consoleIntegration(),
|
|
45
|
+
],
|
|
46
|
+
// Apply caller-provided tags (e.g. team_id) and a structured `cyrus`
|
|
47
|
+
// context to every event. Tags are indexed/searchable; the context is
|
|
48
|
+
// shown as a grouped structured block in the Sentry UI and is the
|
|
49
|
+
// home for fields too noisy or unbounded to be tags.
|
|
50
|
+
initialScope: buildInitialScope(options),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
captureException(error, context) {
|
|
54
|
+
Sentry.withScope((scope) => {
|
|
55
|
+
applyContext(scope, context);
|
|
56
|
+
Sentry.captureException(error);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
captureMessage(message, severity = "info", context) {
|
|
60
|
+
Sentry.withScope((scope) => {
|
|
61
|
+
applyContext(scope, context);
|
|
62
|
+
Sentry.captureMessage(message, severity);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
log(level, message, attributes) {
|
|
66
|
+
// Merge per-call attributes on top of the process-wide set so team_id
|
|
67
|
+
// (and any other CYRUS_* tag we configured) lands on every log record.
|
|
68
|
+
const merged = {
|
|
69
|
+
...this.globalLogAttributes,
|
|
70
|
+
...attributes,
|
|
71
|
+
};
|
|
72
|
+
switch (level) {
|
|
73
|
+
case "trace":
|
|
74
|
+
Sentry.logger.trace(message, merged);
|
|
75
|
+
break;
|
|
76
|
+
case "debug":
|
|
77
|
+
Sentry.logger.debug(message, merged);
|
|
78
|
+
break;
|
|
79
|
+
case "info":
|
|
80
|
+
Sentry.logger.info(message, merged);
|
|
81
|
+
break;
|
|
82
|
+
case "warn":
|
|
83
|
+
Sentry.logger.warn(message, merged);
|
|
84
|
+
break;
|
|
85
|
+
case "error":
|
|
86
|
+
Sentry.logger.error(message, merged);
|
|
87
|
+
break;
|
|
88
|
+
case "fatal":
|
|
89
|
+
Sentry.logger.fatal(message, merged);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async flush(timeoutMs = 2000) {
|
|
94
|
+
return Sentry.flush(timeoutMs);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function buildInitialScope(options) {
|
|
98
|
+
const hasTags = options.tags && Object.keys(options.tags).length > 0;
|
|
99
|
+
const hasContext = options.structuredContext &&
|
|
100
|
+
Object.keys(options.structuredContext).length > 0;
|
|
101
|
+
if (!hasTags && !hasContext)
|
|
102
|
+
return undefined;
|
|
103
|
+
return {
|
|
104
|
+
...(hasTags ? { tags: options.tags } : {}),
|
|
105
|
+
...(hasContext ? { contexts: { cyrus: options.structuredContext } } : {}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function applyContext(scope, context) {
|
|
109
|
+
if (!context)
|
|
110
|
+
return;
|
|
111
|
+
if (context.tags) {
|
|
112
|
+
for (const [k, v] of Object.entries(context.tags))
|
|
113
|
+
scope.setTag(k, v);
|
|
114
|
+
}
|
|
115
|
+
if (context.extra) {
|
|
116
|
+
for (const [k, v] of Object.entries(context.extra))
|
|
117
|
+
scope.setExtra(k, v);
|
|
118
|
+
}
|
|
119
|
+
if (context.user)
|
|
120
|
+
scope.setUser(context.user);
|
|
121
|
+
if (context.fingerprint && context.fingerprint.length > 0) {
|
|
122
|
+
scope.setFingerprint(context.fingerprint);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=SentryErrorReporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SentryErrorReporter.js","sourceRoot":"","sources":["../../../src/services/SentryErrorReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AA2DvC;;;;;;;;;GASG;AACH,MAAM,OAAO,mBAAmB;IACtB,SAAS,GAAG,IAAI,CAAC;IAET,mBAAmB,CAA6B;IAEjE,YAAY,OAAmC;QAC9C,sEAAsE;QACtE,mEAAmE;QACnE,uEAAuE;QACvE,mDAAmD;QACnD,IAAI,CAAC,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEnE,MAAM,CAAC,IAAI,CAAC;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,YAAY;YAChD,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,GAAG;YACrC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;YAC7B,kEAAkE;YAClE,kEAAkE;YAClE,gBAAgB,EAAE,CAAC;YACnB,mEAAmE;YACnE,+DAA+D;YAC/D,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,oEAAoE;YACpE,sEAAsE;YACtE,wEAAwE;YACxE,qEAAqE;YACrE,qEAAqE;YACrE,mEAAmE;YACnE,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;gBAC3B,GAAG,QAAQ;gBACX,MAAM,CAAC,yBAAyB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;gBAC9C,MAAM,CAAC,kBAAkB,EAAE;aAC3B;YACD,qEAAqE;YACrE,sEAAsE;YACtE,kEAAkE;YAClE,qDAAqD;YACrD,YAAY,EAAE,iBAAiB,CAAC,OAAO,CAAC;SACxC,CAAC,CAAC;IACJ,CAAC;IAED,gBAAgB,CAAC,KAAc,EAAE,OAA8B;QAC9D,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC7B,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,cAAc,CACb,OAAe,EACf,WAAkC,MAAM,EACxC,OAA8B;QAE9B,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YAC1B,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC7B,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,GAAG,CACF,KAA4B,EAC5B,OAAe,EACf,UAAuC;QAEvC,sEAAsE;QACtE,uEAAuE;QACvE,MAAM,MAAM,GAA+B;YAC1C,GAAG,IAAI,CAAC,mBAAmB;YAC3B,GAAG,UAAU;SACb,CAAC;QACF,QAAQ,KAAK,EAAE,CAAC;YACf,KAAK,OAAO;gBACX,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACrC,MAAM;YACP,KAAK,OAAO;gBACX,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACrC,MAAM;YACP,KAAK,MAAM;gBACV,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACpC,MAAM;YACP,KAAK,MAAM;gBACV,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACpC,MAAM;YACP,KAAK,OAAO;gBACX,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACrC,MAAM;YACP,KAAK,OAAO;gBACX,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACrC,MAAM;QACR,CAAC;IACF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI;QAC3B,OAAO,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;CACD;AAED,SAAS,iBAAiB,CACzB,OAAmC;IAEnC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACrE,MAAM,UAAU,GACf,OAAO,CAAC,iBAAiB;QACzB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACnD,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAC9C,OAAO;QACN,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1C,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzE,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CACpB,KAAmB,EACnB,OAAyC;IAEzC,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,CAAC,IAAI;QAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3D,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ErrorReporter } from "cyrus-core";
|
|
2
|
+
/**
|
|
3
|
+
* Default DSN baked into release builds. Empty until an admin creates the
|
|
4
|
+
* `ceedar/cyrus-cli` Sentry project and pastes the DSN here. Sentry DSNs are
|
|
5
|
+
* safe to publish — they only authorise event ingestion.
|
|
6
|
+
*
|
|
7
|
+
* End users may override this with the `CYRUS_SENTRY_DSN` env var, or disable
|
|
8
|
+
* reporting entirely with `CYRUS_SENTRY_DISABLED=1`.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_SENTRY_DSN = "https://4a343e39f7439cb5669604657fca148e@o4509685010399232.ingest.us.sentry.io/4511293576839168";
|
|
11
|
+
export interface CreateErrorReporterParams {
|
|
12
|
+
release?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Reads default to `process.env`. Injected for tests.
|
|
15
|
+
*/
|
|
16
|
+
env?: NodeJS.ProcessEnv;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build the application's {@link ErrorReporter}.
|
|
20
|
+
*
|
|
21
|
+
* Order of resolution:
|
|
22
|
+
* 1. If `CYRUS_SENTRY_DISABLED` is truthy → noop.
|
|
23
|
+
* 2. If `CYRUS_TEAM_ID` is unset → noop. Both Issues and Logs require a
|
|
24
|
+
* tenant tag so we can slice/filter per Cyrus install in Sentry; without
|
|
25
|
+
* it we send nothing rather than emit untenanted noise.
|
|
26
|
+
* 3. Else if a DSN is available (env var or compiled default) → Sentry.
|
|
27
|
+
* 4. Else → noop.
|
|
28
|
+
*
|
|
29
|
+
* Initialise this as early as possible during process startup so that
|
|
30
|
+
* exceptions thrown by subsequent imports/bootstrap are captured.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createErrorReporter(params?: CreateErrorReporterParams): ErrorReporter;
|
|
33
|
+
//# sourceMappingURL=createErrorReporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createErrorReporter.d.ts","sourceRoot":"","sources":["../../../src/services/createErrorReporter.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAGlB,MAAM,YAAY,CAAC;AAIpB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,oGACmE,CAAC;AAEnG,MAAM,WAAW,yBAAyB;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,GAAE,yBAA8B,GACpC,aAAa,CAqDf"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { NoopErrorReporter, setGlobalErrorTags, } from "cyrus-core";
|
|
2
|
+
import { SentryErrorReporter } from "./SentryErrorReporter.js";
|
|
3
|
+
import { scrubSentryEvent, scrubSentryLog } from "./sentryScrubber.js";
|
|
4
|
+
/**
|
|
5
|
+
* Default DSN baked into release builds. Empty until an admin creates the
|
|
6
|
+
* `ceedar/cyrus-cli` Sentry project and pastes the DSN here. Sentry DSNs are
|
|
7
|
+
* safe to publish — they only authorise event ingestion.
|
|
8
|
+
*
|
|
9
|
+
* End users may override this with the `CYRUS_SENTRY_DSN` env var, or disable
|
|
10
|
+
* reporting entirely with `CYRUS_SENTRY_DISABLED=1`.
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_SENTRY_DSN = "https://4a343e39f7439cb5669604657fca148e@o4509685010399232.ingest.us.sentry.io/4511293576839168";
|
|
13
|
+
/**
|
|
14
|
+
* Build the application's {@link ErrorReporter}.
|
|
15
|
+
*
|
|
16
|
+
* Order of resolution:
|
|
17
|
+
* 1. If `CYRUS_SENTRY_DISABLED` is truthy → noop.
|
|
18
|
+
* 2. If `CYRUS_TEAM_ID` is unset → noop. Both Issues and Logs require a
|
|
19
|
+
* tenant tag so we can slice/filter per Cyrus install in Sentry; without
|
|
20
|
+
* it we send nothing rather than emit untenanted noise.
|
|
21
|
+
* 3. Else if a DSN is available (env var or compiled default) → Sentry.
|
|
22
|
+
* 4. Else → noop.
|
|
23
|
+
*
|
|
24
|
+
* Initialise this as early as possible during process startup so that
|
|
25
|
+
* exceptions thrown by subsequent imports/bootstrap are captured.
|
|
26
|
+
*/
|
|
27
|
+
export function createErrorReporter(params = {}) {
|
|
28
|
+
const env = params.env ?? process.env;
|
|
29
|
+
if (isTruthyEnv(env.CYRUS_SENTRY_DISABLED)) {
|
|
30
|
+
return new NoopErrorReporter();
|
|
31
|
+
}
|
|
32
|
+
const tags = buildInitialTags(env);
|
|
33
|
+
// CYRUS_TEAM_ID is the single gate for *both* Issues and Logs — installs
|
|
34
|
+
// without tenant tagging stay silent so the team's Sentry org isn't
|
|
35
|
+
// flooded with untenanted self-hosted noise we can't slice.
|
|
36
|
+
if (!tags?.team_id) {
|
|
37
|
+
return new NoopErrorReporter();
|
|
38
|
+
}
|
|
39
|
+
const dsn = env.CYRUS_SENTRY_DSN?.trim() || DEFAULT_SENTRY_DSN;
|
|
40
|
+
if (!dsn) {
|
|
41
|
+
return new NoopErrorReporter();
|
|
42
|
+
}
|
|
43
|
+
// Mirror the tag set into the process-wide registry so Logger.error
|
|
44
|
+
// forwarding (which builds its own per-event tag map) includes them too,
|
|
45
|
+
// not just events emitted directly via the Sentry SDK's initialScope.
|
|
46
|
+
setGlobalErrorTags(tags);
|
|
47
|
+
const environment = env.CYRUS_SENTRY_ENVIRONMENT?.trim() || "production";
|
|
48
|
+
return new SentryErrorReporter({
|
|
49
|
+
dsn,
|
|
50
|
+
release: params.release,
|
|
51
|
+
environment,
|
|
52
|
+
// Sentry SDK debug output is unrelated to app log level — gating it on
|
|
53
|
+
// CYRUS_LOG_LEVEL=DEBUG floods stdout with OpenTelemetry tracing
|
|
54
|
+
// inheritance / client-report flush messages that belong to the SDK,
|
|
55
|
+
// not Cyrus. Use a dedicated opt-in env var.
|
|
56
|
+
debug: isTruthyEnv(env.CYRUS_SENTRY_DEBUG),
|
|
57
|
+
tags,
|
|
58
|
+
structuredContext: buildStructuredContext({
|
|
59
|
+
env,
|
|
60
|
+
environment,
|
|
61
|
+
release: params.release,
|
|
62
|
+
tags,
|
|
63
|
+
}),
|
|
64
|
+
sampleRate: parseSampleRate(env.CYRUS_SENTRY_SAMPLE_RATE),
|
|
65
|
+
// Always scrub. Cyrus' logger.error sites pass arbitrary args (request
|
|
66
|
+
// bodies, configs, headers) that may carry tokens; we cannot trust call
|
|
67
|
+
// sites to redact, so we filter on the way out.
|
|
68
|
+
beforeSend: scrubSentryEvent,
|
|
69
|
+
// Logs use a separate ingestion path from Issues — `beforeSend` does
|
|
70
|
+
// not run on them, so we register a dedicated hook with the same scrub
|
|
71
|
+
// rules to keep both paths symmetric.
|
|
72
|
+
beforeSendLog: scrubSentryLog,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the structured `cyrus` context block attached to every event. This is
|
|
77
|
+
* the structured-logging counterpart to {@link buildInitialTags}: tags get
|
|
78
|
+
* the indexed/searchable subset (team_id), the context block carries the
|
|
79
|
+
* richer typed fields that show up grouped in the Sentry UI.
|
|
80
|
+
*/
|
|
81
|
+
function buildStructuredContext(input) {
|
|
82
|
+
const ctx = {
|
|
83
|
+
environment: input.environment,
|
|
84
|
+
};
|
|
85
|
+
if (input.release)
|
|
86
|
+
ctx.release = input.release;
|
|
87
|
+
if (input.tags?.team_id)
|
|
88
|
+
ctx.team_id = input.tags.team_id;
|
|
89
|
+
const linearWorkspace = input.env.CYRUS_LINEAR_WORKSPACE?.trim();
|
|
90
|
+
if (linearWorkspace)
|
|
91
|
+
ctx.linear_workspace = linearWorkspace;
|
|
92
|
+
const deployment = input.env.CYRUS_DEPLOYMENT_ID?.trim();
|
|
93
|
+
if (deployment)
|
|
94
|
+
ctx.deployment_id = deployment;
|
|
95
|
+
return Object.keys(ctx).length > 1 || ctx.team_id ? ctx : undefined;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Parse a sample rate from env. Returns undefined for malformed/empty values
|
|
99
|
+
* so the SentryErrorReporter default (1.0) applies.
|
|
100
|
+
*/
|
|
101
|
+
function parseSampleRate(value) {
|
|
102
|
+
if (!value)
|
|
103
|
+
return undefined;
|
|
104
|
+
const n = Number.parseFloat(value);
|
|
105
|
+
if (!Number.isFinite(n) || n < 0 || n > 1)
|
|
106
|
+
return undefined;
|
|
107
|
+
return n;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Build the global tag set applied to every Sentry event. Currently picks up
|
|
111
|
+
* `CYRUS_TEAM_ID` and exposes it as the `team_id` tag so events can be
|
|
112
|
+
* filtered per Cyrus tenant in Sentry.
|
|
113
|
+
*
|
|
114
|
+
* Add additional process-wide tags here rather than at capture sites — keeps
|
|
115
|
+
* call sites free of cross-cutting concerns.
|
|
116
|
+
*/
|
|
117
|
+
function buildInitialTags(env) {
|
|
118
|
+
const tags = {};
|
|
119
|
+
const teamId = env.CYRUS_TEAM_ID?.trim();
|
|
120
|
+
if (teamId)
|
|
121
|
+
tags.team_id = teamId;
|
|
122
|
+
return Object.keys(tags).length > 0 ? tags : undefined;
|
|
123
|
+
}
|
|
124
|
+
function isTruthyEnv(value) {
|
|
125
|
+
if (!value)
|
|
126
|
+
return false;
|
|
127
|
+
const v = value.trim().toLowerCase();
|
|
128
|
+
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=createErrorReporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createErrorReporter.js","sourceRoot":"","sources":["../../../src/services/createErrorReporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ErrorEvent, EventHint } from "@sentry/node";
|
|
2
|
+
/**
|
|
3
|
+
* Mirrors Sentry's `Log` shape just enough for the scrubber to operate on it.
|
|
4
|
+
* Generic over the level type so this hook plugs into the SDK's `beforeSendLog`
|
|
5
|
+
* signature without redeclaring the LogSeverityLevel literal union here.
|
|
6
|
+
*/
|
|
7
|
+
export interface SentryLog<LevelT = string> {
|
|
8
|
+
level: LevelT;
|
|
9
|
+
message: unknown;
|
|
10
|
+
attributes?: Record<string, unknown>;
|
|
11
|
+
severityNumber?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Strip token-shaped substrings from a Sentry event. Mutates and returns the
|
|
15
|
+
* event so it can be used directly as a `beforeSend` hook.
|
|
16
|
+
*/
|
|
17
|
+
export declare function scrubSentryEvent(event: ErrorEvent, _hint?: EventHint): ErrorEvent | null;
|
|
18
|
+
/**
|
|
19
|
+
* Scrub a Sentry Logs entry. Wired as `beforeSendLog` on `Sentry.init`. The
|
|
20
|
+
* Logs stream is a separate pipeline from Issues — `beforeSend` does not run
|
|
21
|
+
* on logs, so we need a dedicated hook to keep the redaction guarantees
|
|
22
|
+
* symmetric across both ingestion paths.
|
|
23
|
+
*
|
|
24
|
+
* Generic in `T` so the SDK's stricter `Log` shape (with `level:
|
|
25
|
+
* LogSeverityLevel`) flows through unchanged — TypeScript would otherwise
|
|
26
|
+
* narrow the return to a looser `string` level on assignment.
|
|
27
|
+
*/
|
|
28
|
+
export declare function scrubSentryLog<T extends SentryLog<unknown>>(log: T): T;
|
|
29
|
+
//# sourceMappingURL=sentryScrubber.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentryScrubber.d.ts","sourceRoot":"","sources":["../../../src/services/sentryScrubber.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,SAAS,CAAC,MAAM,GAAG,MAAM;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AA0HD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,UAAU,EACjB,KAAK,CAAC,EAAE,SAAS,GACf,UAAU,GAAG,IAAI,CAmDnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAQtE"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Substring patterns (lowercased) that mark a key as sensitive. We err on the
|
|
3
|
+
* side of dropping: a redaction is recoverable from local logs, a leaked token
|
|
4
|
+
* is not.
|
|
5
|
+
*/
|
|
6
|
+
const SENSITIVE_KEY_PATTERNS = [
|
|
7
|
+
"token",
|
|
8
|
+
"secret",
|
|
9
|
+
"password",
|
|
10
|
+
"passwd",
|
|
11
|
+
"apikey",
|
|
12
|
+
"api_key",
|
|
13
|
+
"authorization",
|
|
14
|
+
"auth_header",
|
|
15
|
+
"cookie",
|
|
16
|
+
// NOTE: "session" intentionally omitted — it's too broad (matches the
|
|
17
|
+
// `sessionId` / `claudeSessionId` identifier attributes we *want* in
|
|
18
|
+
// Sentry for log slicing). Real session secrets are caught by the more
|
|
19
|
+
// specific patterns ("token", "cookie", "secret") via compounds like
|
|
20
|
+
// `session_token`, `session_cookie`, `session_secret`.
|
|
21
|
+
"private_key",
|
|
22
|
+
"privatekey",
|
|
23
|
+
"client_secret",
|
|
24
|
+
"clientsecret",
|
|
25
|
+
"refresh_token",
|
|
26
|
+
"access_token",
|
|
27
|
+
"bearer",
|
|
28
|
+
"dsn",
|
|
29
|
+
"webhook_secret",
|
|
30
|
+
"webhooksecret",
|
|
31
|
+
"signing_secret",
|
|
32
|
+
"signingsecret",
|
|
33
|
+
"linear_token",
|
|
34
|
+
"github_token",
|
|
35
|
+
"gitlab_token",
|
|
36
|
+
"slack_token",
|
|
37
|
+
];
|
|
38
|
+
const REDACTED = "[REDACTED]";
|
|
39
|
+
const MAX_DEPTH = 8;
|
|
40
|
+
function isSensitiveKey(key) {
|
|
41
|
+
const lower = key.toLowerCase();
|
|
42
|
+
return SENSITIVE_KEY_PATTERNS.some((p) => lower.includes(p));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Recursively redact values whose keys match a sensitive pattern. Strings that
|
|
46
|
+
* look like tokens (long, no whitespace, high entropy-ish) are also redacted
|
|
47
|
+
* even when their parent key is innocuous, so payload fields like
|
|
48
|
+
* `headers["x-foo"]: "ghp_…"` don't slip through.
|
|
49
|
+
*/
|
|
50
|
+
function scrubValue(value, depth = 0) {
|
|
51
|
+
if (depth > MAX_DEPTH)
|
|
52
|
+
return REDACTED;
|
|
53
|
+
if (value == null)
|
|
54
|
+
return value;
|
|
55
|
+
if (typeof value === "string") {
|
|
56
|
+
return looksLikeToken(value) ? REDACTED : redactBearerInString(value);
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
return value.map((v) => scrubValue(v, depth + 1));
|
|
60
|
+
}
|
|
61
|
+
if (typeof value === "object") {
|
|
62
|
+
const out = {};
|
|
63
|
+
for (const [k, v] of Object.entries(value)) {
|
|
64
|
+
if (isSensitiveKey(k)) {
|
|
65
|
+
out[k] = REDACTED;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
out[k] = scrubValue(v, depth + 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Heuristic for an opaque token: long, no whitespace, mostly URL-safe chars,
|
|
77
|
+
* and matches one of the well-known prefixes used by tokens we handle.
|
|
78
|
+
*/
|
|
79
|
+
function looksLikeToken(s) {
|
|
80
|
+
if (s.length < 20)
|
|
81
|
+
return false;
|
|
82
|
+
if (/\s/.test(s))
|
|
83
|
+
return false;
|
|
84
|
+
// Known prefixes
|
|
85
|
+
if (/^(ghp|gho|ghu|ghs|ghr|github_pat)_/i.test(s) ||
|
|
86
|
+
/^xox[abprs]-/i.test(s) ||
|
|
87
|
+
/^glpat-/i.test(s) ||
|
|
88
|
+
/^lin_(api|oauth)_/i.test(s) ||
|
|
89
|
+
/^sk-[A-Za-z0-9_-]{20,}$/i.test(s) ||
|
|
90
|
+
/^Bearer\s+\S{16,}$/i.test(s)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
// JWT-shaped (three base64url segments)
|
|
94
|
+
if (/^[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}$/.test(s)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Redact `Authorization: Bearer …` and `?token=…` substrings inside otherwise
|
|
101
|
+
* innocuous strings (e.g. error messages echoing a request line).
|
|
102
|
+
*/
|
|
103
|
+
function redactBearerInString(s) {
|
|
104
|
+
return s
|
|
105
|
+
.replace(/Bearer\s+[A-Za-z0-9._\-+/=]{16,}/gi, "Bearer [REDACTED]")
|
|
106
|
+
.replace(/([?&](?:token|access_token|api_key|key|secret)=)[^&\s"']+/gi, "$1[REDACTED]");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Strip token-shaped substrings from a Sentry event. Mutates and returns the
|
|
110
|
+
* event so it can be used directly as a `beforeSend` hook.
|
|
111
|
+
*/
|
|
112
|
+
export function scrubSentryEvent(event, _hint) {
|
|
113
|
+
if (event.message) {
|
|
114
|
+
event.message = redactBearerInString(event.message);
|
|
115
|
+
}
|
|
116
|
+
if (event.extra) {
|
|
117
|
+
event.extra = scrubValue(event.extra);
|
|
118
|
+
}
|
|
119
|
+
if (event.contexts) {
|
|
120
|
+
event.contexts = scrubValue(event.contexts);
|
|
121
|
+
}
|
|
122
|
+
if (event.request) {
|
|
123
|
+
if (event.request.headers) {
|
|
124
|
+
event.request.headers = scrubValue(event.request.headers);
|
|
125
|
+
}
|
|
126
|
+
if (event.request.cookies) {
|
|
127
|
+
event.request.cookies =
|
|
128
|
+
REDACTED;
|
|
129
|
+
}
|
|
130
|
+
if (event.request.data !== undefined) {
|
|
131
|
+
event.request.data = scrubValue(event.request.data);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (event.exception?.values) {
|
|
135
|
+
for (const ex of event.exception.values) {
|
|
136
|
+
if (ex.value)
|
|
137
|
+
ex.value = redactBearerInString(ex.value);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Breadcrumbs come from `consoleIntegration` (every console.* line) and
|
|
141
|
+
// other auto-captured trails. They ride along on every event, so anything
|
|
142
|
+
// the app printed before the failure — request bodies, headers, repo paths
|
|
143
|
+
// — would otherwise leak with the next captured exception.
|
|
144
|
+
if (event.breadcrumbs) {
|
|
145
|
+
for (const bc of event.breadcrumbs) {
|
|
146
|
+
if (typeof bc.message === "string") {
|
|
147
|
+
bc.message = redactBearerInString(bc.message);
|
|
148
|
+
}
|
|
149
|
+
if (bc.data) {
|
|
150
|
+
bc.data = scrubValue(bc.data);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return event;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Scrub a Sentry Logs entry. Wired as `beforeSendLog` on `Sentry.init`. The
|
|
158
|
+
* Logs stream is a separate pipeline from Issues — `beforeSend` does not run
|
|
159
|
+
* on logs, so we need a dedicated hook to keep the redaction guarantees
|
|
160
|
+
* symmetric across both ingestion paths.
|
|
161
|
+
*
|
|
162
|
+
* Generic in `T` so the SDK's stricter `Log` shape (with `level:
|
|
163
|
+
* LogSeverityLevel`) flows through unchanged — TypeScript would otherwise
|
|
164
|
+
* narrow the return to a looser `string` level on assignment.
|
|
165
|
+
*/
|
|
166
|
+
export function scrubSentryLog(log) {
|
|
167
|
+
if (typeof log.message === "string") {
|
|
168
|
+
log.message = redactBearerInString(log.message);
|
|
169
|
+
}
|
|
170
|
+
if (log.attributes) {
|
|
171
|
+
log.attributes = scrubValue(log.attributes);
|
|
172
|
+
}
|
|
173
|
+
return log;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=sentryScrubber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentryScrubber.js","sourceRoot":"","sources":["../../../src/services/sentryScrubber.ts"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,MAAM,sBAAsB,GAAG;IAC9B,OAAO;IACP,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,eAAe;IACf,aAAa;IACb,QAAQ;IACR,sEAAsE;IACtE,qEAAqE;IACrE,uEAAuE;IACvE,qEAAqE;IACrE,uDAAuD;IACvD,aAAa;IACb,YAAY;IACZ,eAAe;IACf,cAAc;IACd,eAAe;IACf,cAAc;IACd,QAAQ;IACR,KAAK;IACL,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,eAAe;IACf,cAAc;IACd,cAAc;IACd,cAAc;IACd,aAAa;CACb,CAAC;AAEF,MAAM,QAAQ,GAAG,YAAY,CAAC;AAC9B,MAAM,SAAS,GAAG,CAAC,CAAC;AAEpB,SAAS,cAAc,CAAC,GAAW;IAClC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAChC,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,KAAc,EAAE,KAAK,GAAG,CAAC;IAC5C,IAAI,KAAK,GAAG,SAAS;QAAE,OAAO,QAAQ,CAAC;IACvC,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAEhC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACvE,IAAI,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvB,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACP,GAAG,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YACnC,CAAC;QACF,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,CAAS;IAChC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE/B,iBAAiB;IACjB,IACC,qCAAqC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QACvB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAClB,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5B,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC;QAClC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAC5B,CAAC;QACF,OAAO,IAAI,CAAC;IACb,CAAC;IAED,wCAAwC;IACxC,IAAI,8DAA8D,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC;SACN,OAAO,CAAC,oCAAoC,EAAE,mBAAmB,CAAC;SAClE,OAAO,CACP,6DAA6D,EAC7D,cAAc,CACd,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC/B,KAAiB,EACjB,KAAiB;IAEjB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACjB,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAA4B,CAAC;IAClE,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpB,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAA0B,CAAC;IACtE,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,OAAO,CAAC,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAGvD,CAAC;QACH,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,OAAO,CAAC,OAAO;gBACpB,QAAmD,CAAC;QACtD,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACtC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;IACF,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAC7B,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACzC,IAAI,EAAE,CAAC,KAAK;gBAAE,EAAE,CAAC,KAAK,GAAG,oBAAoB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC;IACF,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,2EAA2E;IAC3E,2DAA2D;IAC3D,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACvB,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACpC,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACpC,EAAE,CAAC,OAAO,GAAG,oBAAoB,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;gBACb,EAAE,CAAC,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC,IAAI,CAA4B,CAAC;YAC1D,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAA+B,GAAM;IAClE,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACrC,GAAG,CAAC,OAAO,GAAG,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAiB,CAAC;IACjE,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACpB,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAA4B,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyrus-ai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.50",
|
|
4
4
|
"description": "AI-powered Linear issue automation using Claude",
|
|
5
5
|
"main": "dist/src/app.js",
|
|
6
6
|
"types": "dist/src/app.d.ts",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@linear/sdk": "^64.0.0",
|
|
34
|
+
"@sentry/node": "^9.47.1",
|
|
34
35
|
"commander": "^14.0.2",
|
|
35
36
|
"dotenv": "^16.5.0",
|
|
36
37
|
"express": "^5.2.0",
|
|
@@ -40,12 +41,12 @@
|
|
|
40
41
|
"node-fetch": "^2.7.0",
|
|
41
42
|
"open": "^10.0.0",
|
|
42
43
|
"zod": "^4.3.5",
|
|
43
|
-
"cyrus-
|
|
44
|
-
"cyrus-
|
|
45
|
-
"cyrus-
|
|
46
|
-
"cyrus-edge-worker": "0.2.
|
|
47
|
-
"cyrus-
|
|
48
|
-
"cyrus-slack-event-transport": "0.2.
|
|
44
|
+
"cyrus-claude-runner": "0.2.50",
|
|
45
|
+
"cyrus-cloudflare-tunnel-client": "0.2.50",
|
|
46
|
+
"cyrus-config-updater": "0.2.50",
|
|
47
|
+
"cyrus-edge-worker": "0.2.50",
|
|
48
|
+
"cyrus-core": "0.2.50",
|
|
49
|
+
"cyrus-slack-event-transport": "0.2.50"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
52
|
"@types/node": "^20.0.0",
|