claude-remote-guard 1.0.0
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/README.md +433 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +427 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/hook.d.ts +3 -0
- package/dist/bin/hook.d.ts.map +1 -0
- package/dist/bin/hook.js +136 -0
- package/dist/bin/hook.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/claude-settings.d.ts +11 -0
- package/dist/lib/claude-settings.d.ts.map +1 -0
- package/dist/lib/claude-settings.js +96 -0
- package/dist/lib/claude-settings.js.map +1 -0
- package/dist/lib/config.d.ts +47 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +177 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/edge-function.d.ts +14 -0
- package/dist/lib/edge-function.d.ts.map +1 -0
- package/dist/lib/edge-function.js +521 -0
- package/dist/lib/edge-function.js.map +1 -0
- package/dist/lib/firebase.d.ts +27 -0
- package/dist/lib/firebase.d.ts.map +1 -0
- package/dist/lib/firebase.js +136 -0
- package/dist/lib/firebase.js.map +1 -0
- package/dist/lib/messenger/base.d.ts +6 -0
- package/dist/lib/messenger/base.d.ts.map +1 -0
- package/dist/lib/messenger/base.js +34 -0
- package/dist/lib/messenger/base.js.map +1 -0
- package/dist/lib/messenger/factory.d.ts +15 -0
- package/dist/lib/messenger/factory.d.ts.map +1 -0
- package/dist/lib/messenger/factory.js +37 -0
- package/dist/lib/messenger/factory.js.map +1 -0
- package/dist/lib/messenger/index.d.ts +7 -0
- package/dist/lib/messenger/index.d.ts.map +1 -0
- package/dist/lib/messenger/index.js +9 -0
- package/dist/lib/messenger/index.js.map +1 -0
- package/dist/lib/messenger/slack.d.ts +14 -0
- package/dist/lib/messenger/slack.d.ts.map +1 -0
- package/dist/lib/messenger/slack.js +169 -0
- package/dist/lib/messenger/slack.js.map +1 -0
- package/dist/lib/messenger/telegram.d.ts +15 -0
- package/dist/lib/messenger/telegram.d.ts.map +1 -0
- package/dist/lib/messenger/telegram.js +120 -0
- package/dist/lib/messenger/telegram.js.map +1 -0
- package/dist/lib/messenger/types.d.ts +21 -0
- package/dist/lib/messenger/types.d.ts.map +1 -0
- package/dist/lib/messenger/types.js +2 -0
- package/dist/lib/messenger/types.js.map +1 -0
- package/dist/lib/messenger/whatsapp.d.ts +16 -0
- package/dist/lib/messenger/whatsapp.d.ts.map +1 -0
- package/dist/lib/messenger/whatsapp.js +103 -0
- package/dist/lib/messenger/whatsapp.js.map +1 -0
- package/dist/lib/rules.d.ts +17 -0
- package/dist/lib/rules.d.ts.map +1 -0
- package/dist/lib/rules.js +138 -0
- package/dist/lib/rules.js.map +1 -0
- package/dist/lib/rules.test.d.ts +2 -0
- package/dist/lib/rules.test.d.ts.map +1 -0
- package/dist/lib/rules.test.js +144 -0
- package/dist/lib/rules.test.js.map +1 -0
- package/dist/lib/setup-instructions.d.ts +3 -0
- package/dist/lib/setup-instructions.d.ts.map +1 -0
- package/dist/lib/setup-instructions.js +55 -0
- package/dist/lib/setup-instructions.js.map +1 -0
- package/dist/lib/slack.d.ts +18 -0
- package/dist/lib/slack.d.ts.map +1 -0
- package/dist/lib/slack.js +21 -0
- package/dist/lib/slack.js.map +1 -0
- package/dist/lib/supabase.d.ts +33 -0
- package/dist/lib/supabase.d.ts.map +1 -0
- package/dist/lib/supabase.js +169 -0
- package/dist/lib/supabase.js.map +1 -0
- package/package.json +67 -0
- package/supabase/functions/slack-callback/index.ts +198 -0
- package/supabase/functions/telegram-callback/index.ts +209 -0
- package/supabase/functions/whatsapp-callback/index.ts +180 -0
- package/supabase/migrations/001_create_approval_requests.sql +91 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firebase.js","sourceRoot":"","sources":["../../src/lib/firebase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Severity } from '../rules.js';
|
|
2
|
+
export declare function maskSensitiveInfo(text: string): string;
|
|
3
|
+
export declare function truncateCommand(command: string, maxLength?: number): string;
|
|
4
|
+
export declare function getSeverityEmoji(severity: Severity): string;
|
|
5
|
+
export declare function getSeverityColor(severity: Severity): string;
|
|
6
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/lib/messenger/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAgBxG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAKhF;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE3D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE3D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getSeverityEmoji as getEmoji, getSeverityColor as getColor } from '../rules.js';
|
|
2
|
+
// Patterns that may contain sensitive information
|
|
3
|
+
const SENSITIVE_PATTERNS = [
|
|
4
|
+
// API keys, tokens, secrets in various formats
|
|
5
|
+
{ pattern: /([?&])(api[_-]?key|token|secret|password|auth|key|access[_-]?token)=([^&\s'"]+)/gi, replacement: '$1$2=[REDACTED]' },
|
|
6
|
+
// Authorization headers
|
|
7
|
+
{ pattern: /(Authorization:\s*)(Bearer\s+)?[^\s'"]+/gi, replacement: '$1$2[REDACTED]' },
|
|
8
|
+
// Environment variable assignments with sensitive names
|
|
9
|
+
{ pattern: /(export\s+)?(AWS_SECRET_ACCESS_KEY|AWS_ACCESS_KEY_ID|API_KEY|SECRET_KEY|PRIVATE_KEY|DATABASE_URL|DB_PASSWORD|SLACK_TOKEN|GITHUB_TOKEN|NPM_TOKEN)=([^\s'"]+)/gi, replacement: '$1$2=[REDACTED]' },
|
|
10
|
+
// Connection strings with passwords
|
|
11
|
+
{ pattern: /:\/\/([^:]+):([^@]+)@/g, replacement: '://$1:[REDACTED]@' },
|
|
12
|
+
// Base64 encoded credentials (likely in headers)
|
|
13
|
+
{ pattern: /(Basic\s+)[A-Za-z0-9+/=]{20,}/gi, replacement: '$1[REDACTED]' },
|
|
14
|
+
];
|
|
15
|
+
export function maskSensitiveInfo(text) {
|
|
16
|
+
let masked = text;
|
|
17
|
+
for (const { pattern, replacement } of SENSITIVE_PATTERNS) {
|
|
18
|
+
masked = masked.replace(pattern, replacement);
|
|
19
|
+
}
|
|
20
|
+
return masked;
|
|
21
|
+
}
|
|
22
|
+
export function truncateCommand(command, maxLength = 500) {
|
|
23
|
+
if (command.length <= maxLength) {
|
|
24
|
+
return command;
|
|
25
|
+
}
|
|
26
|
+
return command.substring(0, maxLength - 3) + '...';
|
|
27
|
+
}
|
|
28
|
+
export function getSeverityEmoji(severity) {
|
|
29
|
+
return getEmoji(severity);
|
|
30
|
+
}
|
|
31
|
+
export function getSeverityColor(severity) {
|
|
32
|
+
return getColor(severity);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/lib/messenger/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,IAAI,QAAQ,EAAE,gBAAgB,IAAI,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAExG,kDAAkD;AAClD,MAAM,kBAAkB,GAAoD;IAC1E,+CAA+C;IAC/C,EAAE,OAAO,EAAE,mFAAmF,EAAE,WAAW,EAAE,iBAAiB,EAAE;IAChI,wBAAwB;IACxB,EAAE,OAAO,EAAE,2CAA2C,EAAE,WAAW,EAAE,gBAAgB,EAAE;IACvF,wDAAwD;IACxD,EAAE,OAAO,EAAE,+JAA+J,EAAE,WAAW,EAAE,iBAAiB,EAAE;IAC5M,oCAAoC;IACpC,EAAE,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACvE,iDAAiD;IACjD,EAAE,OAAO,EAAE,iCAAiC,EAAE,WAAW,EAAE,cAAc,EAAE;CAC5E,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,kBAAkB,EAAE,CAAC;QAC1D,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,YAAoB,GAAG;IACtE,IAAI,OAAO,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IACjD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IACjD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Messenger, MessengerType } from './types.js';
|
|
2
|
+
import { type SlackConfig } from './slack.js';
|
|
3
|
+
import { type TelegramConfig } from './telegram.js';
|
|
4
|
+
import { type WhatsAppConfig } from './whatsapp.js';
|
|
5
|
+
export interface MessengerConfig {
|
|
6
|
+
type: MessengerType;
|
|
7
|
+
slack?: SlackConfig;
|
|
8
|
+
telegram?: TelegramConfig;
|
|
9
|
+
whatsapp?: WhatsAppConfig;
|
|
10
|
+
}
|
|
11
|
+
export declare class MessengerFactory {
|
|
12
|
+
static create(config: MessengerConfig): Messenger;
|
|
13
|
+
static getMessengerTypeLabel(type: MessengerType): string;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/lib/messenger/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,qBAAa,gBAAgB;IAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS;IAyBjD,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;CAU1D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SlackMessenger } from './slack.js';
|
|
2
|
+
import { TelegramMessenger } from './telegram.js';
|
|
3
|
+
import { WhatsAppMessenger } from './whatsapp.js';
|
|
4
|
+
export class MessengerFactory {
|
|
5
|
+
static create(config) {
|
|
6
|
+
switch (config.type) {
|
|
7
|
+
case 'slack':
|
|
8
|
+
if (!config.slack) {
|
|
9
|
+
throw new Error('Slack configuration is required when type is "slack"');
|
|
10
|
+
}
|
|
11
|
+
return new SlackMessenger(config.slack);
|
|
12
|
+
case 'telegram':
|
|
13
|
+
if (!config.telegram) {
|
|
14
|
+
throw new Error('Telegram configuration is required when type is "telegram"');
|
|
15
|
+
}
|
|
16
|
+
return new TelegramMessenger(config.telegram);
|
|
17
|
+
case 'whatsapp':
|
|
18
|
+
if (!config.whatsapp) {
|
|
19
|
+
throw new Error('WhatsApp configuration is required when type is "whatsapp"');
|
|
20
|
+
}
|
|
21
|
+
return new WhatsAppMessenger(config.whatsapp);
|
|
22
|
+
default:
|
|
23
|
+
throw new Error(`Unknown messenger type: ${config.type}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
static getMessengerTypeLabel(type) {
|
|
27
|
+
switch (type) {
|
|
28
|
+
case 'slack':
|
|
29
|
+
return 'Slack';
|
|
30
|
+
case 'telegram':
|
|
31
|
+
return 'Telegram';
|
|
32
|
+
case 'whatsapp':
|
|
33
|
+
return 'WhatsApp (Twilio)';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/lib/messenger/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAoB,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAuB,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAuB,MAAM,eAAe,CAAC;AASvE,MAAM,OAAO,gBAAgB;IAC3B,MAAM,CAAC,MAAM,CAAC,MAAuB;QACnC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,OAAO;gBACV,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;oBAClB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;gBAC1E,CAAC;gBACD,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAE1C,KAAK,UAAU;gBACb,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACrB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;gBAChF,CAAC;gBACD,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAEhD,KAAK,UAAU;gBACb,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACrB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;gBAChF,CAAC;gBACD,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAEhD;gBACE,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,qBAAqB,CAAC,IAAmB;QAC9C,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,OAAO;gBACV,OAAO,OAAO,CAAC;YACjB,KAAK,UAAU;gBACb,OAAO,UAAU,CAAC;YACpB,KAAK,UAAU;gBACb,OAAO,mBAAmB,CAAC;QAC/B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { Messenger, MessengerMessage, MessengerResult, MessengerType } from './types.js';
|
|
2
|
+
export { maskSensitiveInfo, truncateCommand, getSeverityEmoji, getSeverityColor } from './base.js';
|
|
3
|
+
export { SlackMessenger, type SlackConfig } from './slack.js';
|
|
4
|
+
export { TelegramMessenger, type TelegramConfig } from './telegram.js';
|
|
5
|
+
export { WhatsAppMessenger, type WhatsAppConfig } from './whatsapp.js';
|
|
6
|
+
export { MessengerFactory, type MessengerConfig } from './factory.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/messenger/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG9F,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGnG,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGvE,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Base utilities
|
|
2
|
+
export { maskSensitiveInfo, truncateCommand, getSeverityEmoji, getSeverityColor } from './base.js';
|
|
3
|
+
// Messenger implementations
|
|
4
|
+
export { SlackMessenger } from './slack.js';
|
|
5
|
+
export { TelegramMessenger } from './telegram.js';
|
|
6
|
+
export { WhatsAppMessenger } from './whatsapp.js';
|
|
7
|
+
// Factory
|
|
8
|
+
export { MessengerFactory } from './factory.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/messenger/index.ts"],"names":[],"mappings":"AAGA,iBAAiB;AACjB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAEnG,4BAA4B;AAC5B,OAAO,EAAE,cAAc,EAAoB,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAuB,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAuB,MAAM,eAAe,CAAC;AAEvE,UAAU;AACV,OAAO,EAAE,gBAAgB,EAAwB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Messenger, MessengerMessage, MessengerResult } from './types.js';
|
|
2
|
+
export interface SlackConfig {
|
|
3
|
+
webhookUrl: string;
|
|
4
|
+
channelId?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class SlackMessenger implements Messenger {
|
|
7
|
+
readonly type: "slack";
|
|
8
|
+
private config;
|
|
9
|
+
constructor(config: SlackConfig);
|
|
10
|
+
validateConfig(): boolean;
|
|
11
|
+
sendNotification(message: MessengerMessage): Promise<MessengerResult>;
|
|
12
|
+
sendTestNotification(): Promise<MessengerResult>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=slack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../../src/lib/messenger/slack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG/E,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoID,qBAAa,cAAe,YAAW,SAAS;IAC9C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,EAAE,WAAW;IAI/B,cAAc,IAAI,OAAO;IAOnB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAwBrE,oBAAoB,IAAI,OAAO,CAAC,eAAe,CAAC;CAkDvD"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { maskSensitiveInfo, truncateCommand, getSeverityEmoji, getSeverityColor } from './base.js';
|
|
2
|
+
function escapeSlackText(text) {
|
|
3
|
+
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
4
|
+
}
|
|
5
|
+
function buildSlackBlocks(message) {
|
|
6
|
+
const emoji = getSeverityEmoji(message.severity);
|
|
7
|
+
const color = getSeverityColor(message.severity);
|
|
8
|
+
// Mask sensitive information before displaying
|
|
9
|
+
const maskedCommand = maskSensitiveInfo(message.command);
|
|
10
|
+
const escapedCommand = escapeSlackText(truncateCommand(maskedCommand));
|
|
11
|
+
const escapedCwd = escapeSlackText(message.cwd);
|
|
12
|
+
const escapedReason = escapeSlackText(message.reason);
|
|
13
|
+
return {
|
|
14
|
+
blocks: [
|
|
15
|
+
{
|
|
16
|
+
type: 'header',
|
|
17
|
+
text: {
|
|
18
|
+
type: 'plain_text',
|
|
19
|
+
text: `${emoji} Claude Guard: Approval Required`,
|
|
20
|
+
emoji: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'section',
|
|
25
|
+
text: {
|
|
26
|
+
type: 'mrkdwn',
|
|
27
|
+
text: `*Reason:* ${escapedReason}\n*Severity:* ${message.severity.toUpperCase()}`,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'section',
|
|
32
|
+
text: {
|
|
33
|
+
type: 'mrkdwn',
|
|
34
|
+
text: `*Command:*\n\`\`\`${escapedCommand}\`\`\``,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: 'section',
|
|
39
|
+
text: {
|
|
40
|
+
type: 'mrkdwn',
|
|
41
|
+
text: `*Working Directory:*\n\`${escapedCwd}\``,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: 'actions',
|
|
46
|
+
elements: [
|
|
47
|
+
{
|
|
48
|
+
type: 'button',
|
|
49
|
+
text: {
|
|
50
|
+
type: 'plain_text',
|
|
51
|
+
text: 'Approve',
|
|
52
|
+
emoji: true,
|
|
53
|
+
},
|
|
54
|
+
style: 'primary',
|
|
55
|
+
action_id: 'approve_command',
|
|
56
|
+
value: message.requestId,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: 'button',
|
|
60
|
+
text: {
|
|
61
|
+
type: 'plain_text',
|
|
62
|
+
text: 'Reject',
|
|
63
|
+
emoji: true,
|
|
64
|
+
},
|
|
65
|
+
style: 'danger',
|
|
66
|
+
action_id: 'reject_command',
|
|
67
|
+
value: message.requestId,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'context',
|
|
73
|
+
elements: [
|
|
74
|
+
{
|
|
75
|
+
type: 'mrkdwn',
|
|
76
|
+
text: `Request ID: \`${message.requestId}\` | Time: <!date^${Math.floor(message.timestamp / 1000)}^{date_short_pretty} {time}|${new Date(message.timestamp).toISOString()}>`,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
attachments: [
|
|
82
|
+
{
|
|
83
|
+
color: color,
|
|
84
|
+
blocks: [],
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export class SlackMessenger {
|
|
90
|
+
type = 'slack';
|
|
91
|
+
config;
|
|
92
|
+
constructor(config) {
|
|
93
|
+
this.config = config;
|
|
94
|
+
}
|
|
95
|
+
validateConfig() {
|
|
96
|
+
return (typeof this.config.webhookUrl === 'string' &&
|
|
97
|
+
this.config.webhookUrl.startsWith('https://hooks.slack.com/'));
|
|
98
|
+
}
|
|
99
|
+
async sendNotification(message) {
|
|
100
|
+
try {
|
|
101
|
+
const payload = buildSlackBlocks(message);
|
|
102
|
+
const response = await fetch(this.config.webhookUrl, {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
headers: {
|
|
105
|
+
'Content-Type': 'application/json',
|
|
106
|
+
},
|
|
107
|
+
body: JSON.stringify(payload),
|
|
108
|
+
});
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
const text = await response.text();
|
|
111
|
+
return { ok: false, error: `Slack API error: ${response.status} ${text}` };
|
|
112
|
+
}
|
|
113
|
+
return { ok: true };
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
117
|
+
return { ok: false, error: errorMessage };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async sendTestNotification() {
|
|
121
|
+
try {
|
|
122
|
+
const payload = {
|
|
123
|
+
blocks: [
|
|
124
|
+
{
|
|
125
|
+
type: 'header',
|
|
126
|
+
text: {
|
|
127
|
+
type: 'plain_text',
|
|
128
|
+
text: '✅ Claude Guard Test Notification',
|
|
129
|
+
emoji: true,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
type: 'section',
|
|
134
|
+
text: {
|
|
135
|
+
type: 'mrkdwn',
|
|
136
|
+
text: 'This is a test notification from Claude Guard.\nIf you see this message, your Slack integration is working correctly!',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: 'context',
|
|
141
|
+
elements: [
|
|
142
|
+
{
|
|
143
|
+
type: 'mrkdwn',
|
|
144
|
+
text: `Sent at: <!date^${Math.floor(Date.now() / 1000)}^{date_short_pretty} {time}|${new Date().toISOString()}>`,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
const response = await fetch(this.config.webhookUrl, {
|
|
151
|
+
method: 'POST',
|
|
152
|
+
headers: {
|
|
153
|
+
'Content-Type': 'application/json',
|
|
154
|
+
},
|
|
155
|
+
body: JSON.stringify(payload),
|
|
156
|
+
});
|
|
157
|
+
if (!response.ok) {
|
|
158
|
+
const text = await response.text();
|
|
159
|
+
return { ok: false, error: `Slack API error: ${response.status} ${text}` };
|
|
160
|
+
}
|
|
161
|
+
return { ok: true };
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
165
|
+
return { ok: false, error: errorMessage };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=slack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.js","sourceRoot":"","sources":["../../../src/lib/messenger/slack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Messenger, MessengerMessage, MessengerResult } from './types.js';
|
|
2
|
+
export interface TelegramConfig {
|
|
3
|
+
botToken: string;
|
|
4
|
+
chatId: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class TelegramMessenger implements Messenger {
|
|
7
|
+
readonly type: "telegram";
|
|
8
|
+
private config;
|
|
9
|
+
private baseUrl;
|
|
10
|
+
constructor(config: TelegramConfig);
|
|
11
|
+
validateConfig(): boolean;
|
|
12
|
+
sendNotification(message: MessengerMessage): Promise<MessengerResult>;
|
|
13
|
+
sendTestNotification(): Promise<MessengerResult>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=telegram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../../src/lib/messenger/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG/E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAmDD,qBAAa,iBAAkB,YAAW,SAAS;IACjD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IACpC,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,cAAc;IAKlC,cAAc,IAAI,OAAO;IASnB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA+BrE,oBAAoB,IAAI,OAAO,CAAC,eAAe,CAAC;CAmCvD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { maskSensitiveInfo, truncateCommand, getSeverityEmoji } from './base.js';
|
|
2
|
+
// Telegram MarkdownV2에서 이스케이프가 필요한 문자
|
|
3
|
+
function escapeTelegramMarkdownV2(text) {
|
|
4
|
+
// eslint-disable-next-line no-useless-escape
|
|
5
|
+
return text.replace(/[_*\[\]()~`>#+\-=|{}.!\\]/g, '\\$&');
|
|
6
|
+
}
|
|
7
|
+
function buildTelegramMessage(message) {
|
|
8
|
+
const emoji = getSeverityEmoji(message.severity);
|
|
9
|
+
const maskedCommand = maskSensitiveInfo(message.command);
|
|
10
|
+
const truncatedCommand = truncateCommand(maskedCommand, 300);
|
|
11
|
+
// MarkdownV2 형식으로 메시지 구성
|
|
12
|
+
const lines = [
|
|
13
|
+
`${emoji} *Claude Guard: Approval Required*`,
|
|
14
|
+
'',
|
|
15
|
+
`*Reason:* ${escapeTelegramMarkdownV2(message.reason)}`,
|
|
16
|
+
`*Severity:* ${message.severity.toUpperCase()}`,
|
|
17
|
+
'',
|
|
18
|
+
`*Command:*`,
|
|
19
|
+
'```',
|
|
20
|
+
escapeTelegramMarkdownV2(truncatedCommand),
|
|
21
|
+
'```',
|
|
22
|
+
'',
|
|
23
|
+
`*Working Directory:*`,
|
|
24
|
+
`\`${escapeTelegramMarkdownV2(message.cwd)}\``,
|
|
25
|
+
'',
|
|
26
|
+
`_Request ID: ${escapeTelegramMarkdownV2(message.requestId)}_`,
|
|
27
|
+
];
|
|
28
|
+
return lines.join('\n');
|
|
29
|
+
}
|
|
30
|
+
function buildInlineKeyboard(requestId) {
|
|
31
|
+
return {
|
|
32
|
+
inline_keyboard: [
|
|
33
|
+
[
|
|
34
|
+
{
|
|
35
|
+
text: '✅ Approve',
|
|
36
|
+
callback_data: `approve:${requestId}`,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
text: '❌ Reject',
|
|
40
|
+
callback_data: `reject:${requestId}`,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export class TelegramMessenger {
|
|
47
|
+
type = 'telegram';
|
|
48
|
+
config;
|
|
49
|
+
baseUrl;
|
|
50
|
+
constructor(config) {
|
|
51
|
+
this.config = config;
|
|
52
|
+
this.baseUrl = `https://api.telegram.org/bot${config.botToken}`;
|
|
53
|
+
}
|
|
54
|
+
validateConfig() {
|
|
55
|
+
return (typeof this.config.botToken === 'string' &&
|
|
56
|
+
this.config.botToken.length > 0 &&
|
|
57
|
+
typeof this.config.chatId === 'string' &&
|
|
58
|
+
this.config.chatId.length > 0);
|
|
59
|
+
}
|
|
60
|
+
async sendNotification(message) {
|
|
61
|
+
try {
|
|
62
|
+
const text = buildTelegramMessage(message);
|
|
63
|
+
const replyMarkup = buildInlineKeyboard(message.requestId);
|
|
64
|
+
const response = await fetch(`${this.baseUrl}/sendMessage`, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: {
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
},
|
|
69
|
+
body: JSON.stringify({
|
|
70
|
+
chat_id: this.config.chatId,
|
|
71
|
+
text,
|
|
72
|
+
parse_mode: 'MarkdownV2',
|
|
73
|
+
reply_markup: replyMarkup,
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
const result = await response.json();
|
|
77
|
+
if (!result.ok) {
|
|
78
|
+
return { ok: false, error: `Telegram API error: ${result.description || 'Unknown error'}` };
|
|
79
|
+
}
|
|
80
|
+
return { ok: true };
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
84
|
+
return { ok: false, error: errorMessage };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async sendTestNotification() {
|
|
88
|
+
try {
|
|
89
|
+
const text = [
|
|
90
|
+
'✅ *Claude Guard Test Notification*',
|
|
91
|
+
'',
|
|
92
|
+
'This is a test notification from Claude Guard\\.',
|
|
93
|
+
'If you see this message, your Telegram integration is working correctly\\!',
|
|
94
|
+
'',
|
|
95
|
+
`_Sent at: ${escapeTelegramMarkdownV2(new Date().toISOString())}_`,
|
|
96
|
+
].join('\n');
|
|
97
|
+
const response = await fetch(`${this.baseUrl}/sendMessage`, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: {
|
|
100
|
+
'Content-Type': 'application/json',
|
|
101
|
+
},
|
|
102
|
+
body: JSON.stringify({
|
|
103
|
+
chat_id: this.config.chatId,
|
|
104
|
+
text,
|
|
105
|
+
parse_mode: 'MarkdownV2',
|
|
106
|
+
}),
|
|
107
|
+
});
|
|
108
|
+
const result = await response.json();
|
|
109
|
+
if (!result.ok) {
|
|
110
|
+
return { ok: false, error: `Telegram API error: ${result.description || 'Unknown error'}` };
|
|
111
|
+
}
|
|
112
|
+
return { ok: true };
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
116
|
+
return { ok: false, error: errorMessage };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=telegram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../src/lib/messenger/telegram.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Severity } from '../rules.js';
|
|
2
|
+
export type MessengerType = 'slack' | 'telegram' | 'whatsapp';
|
|
3
|
+
export interface MessengerMessage {
|
|
4
|
+
requestId: string;
|
|
5
|
+
command: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
severity: Severity;
|
|
8
|
+
cwd: string;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
}
|
|
11
|
+
export interface MessengerResult {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface Messenger {
|
|
16
|
+
readonly type: MessengerType;
|
|
17
|
+
sendNotification(message: MessengerMessage): Promise<MessengerResult>;
|
|
18
|
+
sendTestNotification(): Promise<MessengerResult>;
|
|
19
|
+
validateConfig(): boolean;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/messenger/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACtE,oBAAoB,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IACjD,cAAc,IAAI,OAAO,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/messenger/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Messenger, MessengerMessage, MessengerResult } from './types.js';
|
|
2
|
+
export interface WhatsAppConfig {
|
|
3
|
+
accountSid: string;
|
|
4
|
+
authToken: string;
|
|
5
|
+
fromNumber: string;
|
|
6
|
+
toNumber: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class WhatsAppMessenger implements Messenger {
|
|
9
|
+
readonly type: "whatsapp";
|
|
10
|
+
private config;
|
|
11
|
+
constructor(config: WhatsAppConfig);
|
|
12
|
+
validateConfig(): boolean;
|
|
13
|
+
sendNotification(message: MessengerMessage): Promise<MessengerResult>;
|
|
14
|
+
sendTestNotification(): Promise<MessengerResult>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=whatsapp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whatsapp.d.ts","sourceRoot":"","sources":["../../../src/lib/messenger/whatsapp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG/E,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA0BD,qBAAa,iBAAkB,YAAW,SAAS;IACjD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IACpC,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;IAIlC,cAAc,IAAI,OAAO;IAanB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkCrE,oBAAoB,IAAI,OAAO,CAAC,eAAe,CAAC;CAwCvD"}
|