@aurora-foundation/obsidian-next 0.4.7 → 0.4.9
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/CHANGELOG.md +23 -0
- package/LICENSE +628 -190
- package/README.md +23 -9
- package/dist/auditLog-6WDBDNYL.js +8 -0
- package/dist/auditLog-HGPVDSDC.js +8 -0
- package/dist/auditLog-TDIKFBM4.js +8 -0
- package/dist/auditLog-XC2KY3ZZ.js +8 -0
- package/dist/chunk-2I235WNB.js +133 -0
- package/dist/chunk-2JWDGXTR.js +42 -0
- package/dist/chunk-2NOB6W2B.js +133 -0
- package/dist/chunk-3LFKVKKL.js +7199 -0
- package/dist/chunk-3U6WHPDX.js +4695 -0
- package/dist/chunk-3UCL6RYE.js +7272 -0
- package/dist/chunk-4GN2UQLI.js +130 -0
- package/dist/chunk-4MW33MZD.js +516 -0
- package/dist/chunk-4PUJBUKZ.js +4716 -0
- package/dist/chunk-4QHK6H6O.js +130 -0
- package/dist/chunk-55CQIHCO.js +133 -0
- package/dist/chunk-5LWINFWI.js +676 -0
- package/dist/chunk-5OKGLNQW.js +439 -0
- package/dist/chunk-5T6ETZEO.js +6183 -0
- package/dist/chunk-5WGIFUVL.js +4234 -0
- package/dist/chunk-66EW47T3.js +4237 -0
- package/dist/chunk-6TXUOTT2.js +581 -0
- package/dist/chunk-6YUYSYDA.js +130 -0
- package/dist/chunk-74VPNFMX.js +133 -0
- package/dist/chunk-77CGJRGV.js +6188 -0
- package/dist/chunk-7DS3VT4C.js +7135 -0
- package/dist/chunk-7FHX3VBT.js +133 -0
- package/dist/chunk-7MHF56YU.js +6178 -0
- package/dist/chunk-ABLPMV7G.js +133 -0
- package/dist/chunk-B77K6OQZ.js +687 -0
- package/dist/chunk-BKOXH66O.js +133 -0
- package/dist/chunk-BPP76UN2.js +130 -0
- package/dist/chunk-C4D56GRC.js +5936 -0
- package/dist/chunk-CCDPY4WE.js +370 -0
- package/dist/chunk-CHNVBJN3.js +7272 -0
- package/dist/chunk-CKBZI576.js +7229 -0
- package/dist/chunk-CW5HBSJ2.js +7198 -0
- package/dist/chunk-DGHDJEY7.js +133 -0
- package/dist/chunk-DPNIQWKZ.js +439 -0
- package/dist/chunk-DU4T3V2T.js +214 -0
- package/dist/chunk-DV3WFKNB.js +4679 -0
- package/dist/chunk-DZI2OVN2.js +516 -0
- package/dist/chunk-E45VILML.js +7198 -0
- package/dist/chunk-ECEUUYXC.js +7199 -0
- package/dist/chunk-EJRRSHPW.js +685 -0
- package/dist/chunk-EMBMLZFE.js +370 -0
- package/dist/chunk-EPG5V5OO.js +285 -0
- package/dist/chunk-F2R4HXXW.js +130 -0
- package/dist/chunk-FK6N66ES.js +581 -0
- package/dist/chunk-G3CZKGYA.js +197 -0
- package/dist/chunk-GUUPG4A7.js +7111 -0
- package/dist/chunk-HBAAUGUN.js +7230 -0
- package/dist/chunk-HHFJMK2Q.js +6177 -0
- package/dist/chunk-HINRQTCZ.js +196 -0
- package/dist/chunk-HRKJ3R2U.js +288 -0
- package/dist/chunk-HWVK4CVE.js +439 -0
- package/dist/chunk-JEYSADNZ.js +581 -0
- package/dist/chunk-JNEIL7UN.js +4252 -0
- package/dist/chunk-JTWSK277.js +676 -0
- package/dist/chunk-K4CHTTCJ.js +942 -0
- package/dist/chunk-K7R5KUDS.js +4695 -0
- package/dist/chunk-KNJFOURE.js +7151 -0
- package/dist/chunk-KY22FIT3.js +7256 -0
- package/dist/chunk-L2OTIJSF.js +4228 -0
- package/dist/chunk-LEEBUHP6.js +4655 -0
- package/dist/chunk-LK7UP2T7.js +130 -0
- package/dist/chunk-LPGNO3PK.js +284 -0
- package/dist/chunk-LYQYJMWS.js +133 -0
- package/dist/chunk-MBYFJXR3.js +130 -0
- package/dist/chunk-N3WX44L3.js +130 -0
- package/dist/chunk-N6AQWES3.js +6197 -0
- package/dist/chunk-NW4XSTQZ.js +130 -0
- package/dist/chunk-NWG2XURH.js +130 -0
- package/dist/chunk-O3GF3LJD.js +6142 -0
- package/dist/chunk-OHP5LD3Y.js +6188 -0
- package/dist/chunk-P5PQSFZT.js +6182 -0
- package/dist/chunk-PAADOWNP.js +130 -0
- package/dist/chunk-PERGND7L.js +7213 -0
- package/dist/chunk-PWA7V4XX.js +179 -0
- package/dist/chunk-QGCWEP6L.js +7111 -0
- package/dist/chunk-QVT2IHNJ.js +175 -0
- package/dist/chunk-QZNGYPMS.js +6161 -0
- package/dist/chunk-R6P2E2ZQ.js +207 -0
- package/dist/chunk-ROSDMGIL.js +4679 -0
- package/dist/chunk-RQZP7IKG.js +196 -0
- package/dist/chunk-RUQSPX3U.js +133 -0
- package/dist/chunk-S3BYHP5M.js +130 -0
- package/dist/chunk-S6GNETVE.js +438 -0
- package/dist/chunk-SDT2ZE2R.js +133 -0
- package/dist/chunk-SHQBXJFC.js +6166 -0
- package/dist/chunk-TJNISYTE.js +42 -0
- package/dist/chunk-TJW74HFF.js +130 -0
- package/dist/chunk-TPP72DTK.js +7096 -0
- package/dist/chunk-UOESII6R.js +42 -0
- package/dist/chunk-UWEDGLYJ.js +6142 -0
- package/dist/chunk-V5FYNAFX.js +133 -0
- package/dist/chunk-VPURF6UT.js +7198 -0
- package/dist/chunk-VQH6LWIZ.js +6184 -0
- package/dist/chunk-VS22YVX6.js +7111 -0
- package/dist/chunk-VSF5KBW7.js +367 -0
- package/dist/chunk-VV3JMCKY.js +214 -0
- package/dist/chunk-W5L7HOE3.js +133 -0
- package/dist/chunk-WFEVQISK.js +676 -0
- package/dist/chunk-WJZPSCEP.js +516 -0
- package/dist/chunk-WLV4MKEF.js +16 -0
- package/dist/chunk-WSEVQFFI.js +5428 -0
- package/dist/chunk-X7N2RNR3.js +5428 -0
- package/dist/chunk-XKZNMRNO.js +133 -0
- package/dist/chunk-Y7BVEC36.js +130 -0
- package/dist/chunk-YG7YSNNU.js +4226 -0
- package/dist/chunk-YHM62466.js +261 -0
- package/dist/chunk-YLTYJLDZ.js +7208 -0
- package/dist/chunk-YPMJD4YE.js +56 -0
- package/dist/chunk-YTX3FU2A.js +7199 -0
- package/dist/chunk-ZEQ3EBBN.js +214 -0
- package/dist/chunk-ZIWLQSLK.js +42 -0
- package/dist/chunk-ZJELNTEO.js +516 -0
- package/dist/chunk-ZOSSVNGK.js +370 -0
- package/dist/config-EYK32F2E.js +10 -0
- package/dist/config-FJPPPYTY.js +10 -0
- package/dist/config-VAHPVILX.js +10 -0
- package/dist/context-2YGE4U75.js +10 -0
- package/dist/context-5UFVYKES.js +9 -0
- package/dist/context-ANZF4J72.js +10 -0
- package/dist/context-GLUNCUBQ.js +10 -0
- package/dist/context-M5ULPZKQ.js +10 -0
- package/dist/context-NYOIRZKV.js +10 -0
- package/dist/context-YP2REI6A.js +10 -0
- package/dist/database-MP2JBLMF.js +8 -0
- package/dist/index.js +6177 -4688
- package/dist/keyManager-P2SZONKE.js +8 -0
- package/dist/mcp/index.js +127 -47
- package/dist/memory-BPGJAL4J.js +13 -0
- package/dist/memory-FRQOUI6W.js +13 -0
- package/dist/memory-OAMK27IZ.js +13 -0
- package/dist/memory-OZ734ALL.js +13 -0
- package/dist/memory-PQ2EWRMU.js +13 -0
- package/dist/memory-PXL45M6W.js +13 -0
- package/dist/memory-QZTBTYPH.js +13 -0
- package/dist/migrations-TLJ3WRVW.js +188 -0
- package/dist/resume-2NHDK6EI.js +17 -0
- package/dist/resume-44L2PDB2.js +17 -0
- package/dist/resume-4MXIWUJO.js +7 -0
- package/dist/resume-72VJX66I.js +17 -0
- package/dist/resume-7ZW4XM3B.js +15 -0
- package/dist/resume-AZHYQ657.js +17 -0
- package/dist/resume-CNLXSYHV.js +17 -0
- package/dist/resume-DPN4Q777.js +16 -0
- package/dist/resume-DSFHVNPI.js +15 -0
- package/dist/resume-GHLQJJTO.js +17 -0
- package/dist/resume-HJ6SBWTF.js +17 -0
- package/dist/resume-HRLYHY2L.js +17 -0
- package/dist/resume-ISIQFKO6.js +17 -0
- package/dist/resume-JQDEA6PS.js +15 -0
- package/dist/resume-KP3Y3Y7P.js +17 -0
- package/dist/resume-M4KHR5OI.js +17 -0
- package/dist/resume-N62OAMBG.js +17 -0
- package/dist/resume-NNMA5POT.js +17 -0
- package/dist/resume-ODYT3J4H.js +17 -0
- package/dist/resume-PCFJXA5O.js +17 -0
- package/dist/resume-PLF4XGBD.js +15 -0
- package/dist/resume-Q2PFX57V.js +17 -0
- package/dist/resume-QB4XI2J5.js +17 -0
- package/dist/resume-R5MFTUPF.js +17 -0
- package/dist/resume-SVA7223Z.js +17 -0
- package/dist/resume-TYKKDJZI.js +17 -0
- package/dist/resume-XIS45HKV.js +17 -0
- package/dist/resume-YCSEJTU7.js +17 -0
- package/dist/resume-YD76GI2J.js +15 -0
- package/dist/resume-YDN7EL77.js +17 -0
- package/dist/resume-YE7DB4ZA.js +17 -0
- package/dist/resume-YKAKOXWV.js +15 -0
- package/dist/resume-ZHBCVFDY.js +17 -0
- package/dist/scheduler-2CK24A2Q.js +14 -0
- package/dist/scheduler-7OAF2XKX.js +14 -0
- package/dist/scheduler-AS23AAB5.js +14 -0
- package/dist/scheduler-PCOYQJA5.js +14 -0
- package/dist/scheduler-V2ECBQPK.js +14 -0
- package/dist/scheduler-VEWZ6L7V.js +13 -0
- package/dist/scheduler-W37QMGDQ.js +14 -0
- package/dist/session-2E2JKPD7.js +15 -0
- package/dist/session-2VSF257B.js +14 -0
- package/dist/session-4APFTDJU.js +14 -0
- package/dist/session-5YS5LNNL.js +16 -0
- package/dist/session-6MO5ZPOB.js +16 -0
- package/dist/session-6XMGPRTQ.js +14 -0
- package/dist/session-7DJR77R7.js +16 -0
- package/dist/session-7DQHPWTR.js +14 -0
- package/dist/session-ADKIQCR5.js +16 -0
- package/dist/session-AOGH2GGI.js +16 -0
- package/dist/session-C4W6GDYG.js +16 -0
- package/dist/session-DCGNGGMV.js +14 -0
- package/dist/session-F5JKZAN2.js +16 -0
- package/dist/session-G6F3O2FQ.js +16 -0
- package/dist/session-GFBSARRO.js +16 -0
- package/dist/session-H5IWAIUI.js +16 -0
- package/dist/session-IPFA6AHC.js +14 -0
- package/dist/session-IWG2UOAX.js +14 -0
- package/dist/session-KJ2K4Y4M.js +14 -0
- package/dist/session-KPXFBW6Q.js +14 -0
- package/dist/session-KR256UL5.js +16 -0
- package/dist/session-M72LJXPR.js +16 -0
- package/dist/session-MBK3FODN.js +14 -0
- package/dist/session-MOUFAU7G.js +16 -0
- package/dist/session-NRC6ZXFQ.js +16 -0
- package/dist/session-NRPQMV4K.js +16 -0
- package/dist/session-O5IFFJZQ.js +14 -0
- package/dist/session-OF5BGKDE.js +16 -0
- package/dist/session-OGRZMIM7.js +14 -0
- package/dist/session-OJOFAJG3.js +16 -0
- package/dist/session-OKU4N3SP.js +16 -0
- package/dist/session-P2VAOSFB.js +14 -0
- package/dist/session-PKOVZD4M.js +16 -0
- package/dist/session-POAIMUVN.js +16 -0
- package/dist/session-PSHFONFE.js +16 -0
- package/dist/session-QKYVVZFV.js +16 -0
- package/dist/session-QPWGBMUS.js +14 -0
- package/dist/session-R5UG5PZR.js +14 -0
- package/dist/session-RAY6BZRQ.js +16 -0
- package/dist/session-S3VATHMU.js +16 -0
- package/dist/session-SYTD7RHW.js +14 -0
- package/dist/session-UHMMVO4J.js +16 -0
- package/dist/session-WEX5K3ZY.js +14 -0
- package/dist/session-XFLOXGU3.js +14 -0
- package/dist/session-XV2A4HHG.js +14 -0
- package/dist/settings-3VPJYD4D.js +8 -0
- package/dist/settings-GZTJJTBK.js +8 -0
- package/dist/settings-YKJFSKMO.js +8 -0
- package/dist/shell-FM34624T.js +8 -0
- package/package.json +14 -4
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
import {
|
|
2
|
+
config
|
|
3
|
+
} from "./chunk-7MMY74WO.js";
|
|
4
|
+
import {
|
|
5
|
+
settings
|
|
6
|
+
} from "./chunk-EPG5V5OO.js";
|
|
7
|
+
|
|
8
|
+
// src/core/auditLog.ts
|
|
9
|
+
import fs from "fs/promises";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import os from "os";
|
|
12
|
+
|
|
13
|
+
// src/core/redactor.ts
|
|
14
|
+
var BUILTIN_RULES = [
|
|
15
|
+
// Email addresses
|
|
16
|
+
{
|
|
17
|
+
name: "email",
|
|
18
|
+
pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
|
|
19
|
+
replacement: "[REDACTED:email]",
|
|
20
|
+
enabled: true,
|
|
21
|
+
description: "Email addresses"
|
|
22
|
+
},
|
|
23
|
+
// Phone numbers (various formats) - must have separators to avoid false positives
|
|
24
|
+
{
|
|
25
|
+
name: "phone",
|
|
26
|
+
pattern: /(\+?1[-.\s])?\(?\d{3}\)?[-.\s]\d{3,4}[-.\s]\d{4}\b/g,
|
|
27
|
+
replacement: "[REDACTED:phone]",
|
|
28
|
+
enabled: true,
|
|
29
|
+
description: "Phone numbers (US format with separators)"
|
|
30
|
+
},
|
|
31
|
+
// Social Security Numbers
|
|
32
|
+
{
|
|
33
|
+
name: "ssn",
|
|
34
|
+
pattern: /\b\d{3}[-\s]?\d{2}[-\s]?\d{4}\b/g,
|
|
35
|
+
replacement: "[REDACTED:ssn]",
|
|
36
|
+
enabled: true,
|
|
37
|
+
description: "Social Security Numbers"
|
|
38
|
+
},
|
|
39
|
+
// Credit card numbers (basic patterns)
|
|
40
|
+
{
|
|
41
|
+
name: "credit-card",
|
|
42
|
+
pattern: /\b(?:4\d{3}|5[1-5]\d{2}|6(?:011|5\d{2})|3[47]\d{2})[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g,
|
|
43
|
+
replacement: "[REDACTED:credit-card]",
|
|
44
|
+
enabled: true,
|
|
45
|
+
description: "Credit card numbers"
|
|
46
|
+
},
|
|
47
|
+
// AWS Access Keys
|
|
48
|
+
{
|
|
49
|
+
name: "aws-access-key",
|
|
50
|
+
pattern: /\b(AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}\b/g,
|
|
51
|
+
replacement: "[REDACTED:aws-key]",
|
|
52
|
+
enabled: true,
|
|
53
|
+
description: "AWS access key IDs"
|
|
54
|
+
},
|
|
55
|
+
// AWS Secret Keys (40 char base64-like)
|
|
56
|
+
{
|
|
57
|
+
name: "aws-secret-key",
|
|
58
|
+
pattern: /\b[A-Za-z0-9/+=]{40}\b/g,
|
|
59
|
+
replacement: (match) => {
|
|
60
|
+
if (/[A-Z]/.test(match) && /[a-z]/.test(match) && /[/+=]/.test(match)) {
|
|
61
|
+
return "[REDACTED:aws-secret]";
|
|
62
|
+
}
|
|
63
|
+
return match;
|
|
64
|
+
},
|
|
65
|
+
enabled: true,
|
|
66
|
+
description: "AWS secret access keys"
|
|
67
|
+
},
|
|
68
|
+
// Anthropic API Keys
|
|
69
|
+
{
|
|
70
|
+
name: "anthropic-key",
|
|
71
|
+
pattern: /\bsk-ant-[a-zA-Z0-9-_]{20,}/g,
|
|
72
|
+
replacement: "[REDACTED:anthropic-key]",
|
|
73
|
+
enabled: true,
|
|
74
|
+
description: "Anthropic API keys"
|
|
75
|
+
},
|
|
76
|
+
// OpenAI API Keys (start with sk- but not sk-ant-, may contain hyphens)
|
|
77
|
+
{
|
|
78
|
+
name: "openai-key",
|
|
79
|
+
pattern: /sk-(?!ant)[a-zA-Z0-9-]{20,}/g,
|
|
80
|
+
replacement: "[REDACTED:openai-key]",
|
|
81
|
+
enabled: true,
|
|
82
|
+
description: "OpenAI API keys"
|
|
83
|
+
},
|
|
84
|
+
// Generic API keys (common patterns)
|
|
85
|
+
{
|
|
86
|
+
name: "api-key-generic",
|
|
87
|
+
pattern: /\b(api[_-]?key|apikey|api[_-]?secret|api[_-]?token)\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
88
|
+
replacement: (match) => {
|
|
89
|
+
const keyName = match.split(/[=:]/)[0].trim();
|
|
90
|
+
return `${keyName}=[REDACTED:api-key]`;
|
|
91
|
+
},
|
|
92
|
+
enabled: true,
|
|
93
|
+
description: "Generic API keys in config"
|
|
94
|
+
},
|
|
95
|
+
// Passwords in config files (various naming conventions)
|
|
96
|
+
{
|
|
97
|
+
name: "password-config",
|
|
98
|
+
pattern: /\b([A-Z_]*(?:PASSWORD|PASSWD|PWD|SECRET)[A-Z_]*)\s*[=:]\s*['"]?([^'"\s\n]{4,})['"]?/gi,
|
|
99
|
+
replacement: (match) => {
|
|
100
|
+
const keyName = match.split(/[=:]/)[0].trim();
|
|
101
|
+
return `${keyName}=[REDACTED:password]`;
|
|
102
|
+
},
|
|
103
|
+
enabled: true,
|
|
104
|
+
description: "Passwords in configuration"
|
|
105
|
+
},
|
|
106
|
+
// Private keys (PEM format)
|
|
107
|
+
{
|
|
108
|
+
name: "private-key",
|
|
109
|
+
pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END\s+(RSA\s+)?PRIVATE\s+KEY-----/g,
|
|
110
|
+
replacement: "[REDACTED:private-key]",
|
|
111
|
+
enabled: true,
|
|
112
|
+
description: "PEM private keys"
|
|
113
|
+
},
|
|
114
|
+
// JWT tokens
|
|
115
|
+
{
|
|
116
|
+
name: "jwt",
|
|
117
|
+
pattern: /\beyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/g,
|
|
118
|
+
replacement: "[REDACTED:jwt]",
|
|
119
|
+
enabled: true,
|
|
120
|
+
description: "JWT tokens"
|
|
121
|
+
},
|
|
122
|
+
// GitHub tokens (various prefixes)
|
|
123
|
+
{
|
|
124
|
+
name: "github-token",
|
|
125
|
+
pattern: /(ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{20,}/g,
|
|
126
|
+
replacement: "[REDACTED:github-token]",
|
|
127
|
+
enabled: true,
|
|
128
|
+
description: "GitHub tokens"
|
|
129
|
+
},
|
|
130
|
+
// Stripe keys
|
|
131
|
+
{
|
|
132
|
+
name: "stripe-key",
|
|
133
|
+
pattern: /\b(sk|pk)_(test|live)_[a-zA-Z0-9]{24,}/g,
|
|
134
|
+
replacement: "[REDACTED:stripe-key]",
|
|
135
|
+
enabled: true,
|
|
136
|
+
description: "Stripe API keys"
|
|
137
|
+
},
|
|
138
|
+
// IP addresses (private networks only by default)
|
|
139
|
+
{
|
|
140
|
+
name: "private-ip",
|
|
141
|
+
pattern: /\b(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})\b/g,
|
|
142
|
+
replacement: "[REDACTED:private-ip]",
|
|
143
|
+
enabled: false,
|
|
144
|
+
// Disabled by default - may cause issues with code
|
|
145
|
+
description: "Private IP addresses"
|
|
146
|
+
},
|
|
147
|
+
// GitHub Fine-grained Personal Access Tokens (newer format)
|
|
148
|
+
{
|
|
149
|
+
name: "github-fine-grained-pat",
|
|
150
|
+
pattern: /github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}/g,
|
|
151
|
+
replacement: "[REDACTED:github-pat]",
|
|
152
|
+
enabled: true,
|
|
153
|
+
description: "GitHub fine-grained personal access tokens"
|
|
154
|
+
},
|
|
155
|
+
// Slack tokens (various types)
|
|
156
|
+
{
|
|
157
|
+
name: "slack-token",
|
|
158
|
+
pattern: /xox[baprs]-[a-zA-Z0-9-]{10,}/g,
|
|
159
|
+
replacement: "[REDACTED:slack-token]",
|
|
160
|
+
enabled: true,
|
|
161
|
+
description: "Slack API tokens"
|
|
162
|
+
},
|
|
163
|
+
// Discord tokens
|
|
164
|
+
{
|
|
165
|
+
name: "discord-token",
|
|
166
|
+
pattern: /[MN][A-Za-z\d]{23,}\.[\w-]{6}\.[\w-]{27}/g,
|
|
167
|
+
replacement: "[REDACTED:discord-token]",
|
|
168
|
+
enabled: true,
|
|
169
|
+
description: "Discord bot tokens"
|
|
170
|
+
},
|
|
171
|
+
// Google API keys
|
|
172
|
+
{
|
|
173
|
+
name: "google-api-key",
|
|
174
|
+
pattern: /AIza[0-9A-Za-z\\-_]{35}/g,
|
|
175
|
+
replacement: "[REDACTED:google-api-key]",
|
|
176
|
+
enabled: true,
|
|
177
|
+
description: "Google API keys"
|
|
178
|
+
},
|
|
179
|
+
// Twilio keys
|
|
180
|
+
{
|
|
181
|
+
name: "twilio-key",
|
|
182
|
+
pattern: /SK[a-f0-9]{32}/g,
|
|
183
|
+
replacement: "[REDACTED:twilio-key]",
|
|
184
|
+
enabled: true,
|
|
185
|
+
description: "Twilio API keys"
|
|
186
|
+
},
|
|
187
|
+
// SendGrid keys
|
|
188
|
+
{
|
|
189
|
+
name: "sendgrid-key",
|
|
190
|
+
pattern: /SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/g,
|
|
191
|
+
replacement: "[REDACTED:sendgrid-key]",
|
|
192
|
+
enabled: true,
|
|
193
|
+
description: "SendGrid API keys"
|
|
194
|
+
},
|
|
195
|
+
// NPM tokens
|
|
196
|
+
{
|
|
197
|
+
name: "npm-token",
|
|
198
|
+
pattern: /npm_[a-zA-Z0-9]{36}/g,
|
|
199
|
+
replacement: "[REDACTED:npm-token]",
|
|
200
|
+
enabled: true,
|
|
201
|
+
description: "NPM access tokens"
|
|
202
|
+
},
|
|
203
|
+
// PyPI tokens
|
|
204
|
+
{
|
|
205
|
+
name: "pypi-token",
|
|
206
|
+
pattern: /pypi-[a-zA-Z0-9_-]{100,}/g,
|
|
207
|
+
replacement: "[REDACTED:pypi-token]",
|
|
208
|
+
enabled: true,
|
|
209
|
+
description: "PyPI API tokens"
|
|
210
|
+
},
|
|
211
|
+
// Database connection strings
|
|
212
|
+
{
|
|
213
|
+
name: "db-connection-string",
|
|
214
|
+
pattern: /(mongodb(\+srv)?|postgres(ql)?|mysql|redis):\/\/[^\s'"]+/gi,
|
|
215
|
+
replacement: "[REDACTED:db-connection-string]",
|
|
216
|
+
enabled: true,
|
|
217
|
+
description: "Database connection strings"
|
|
218
|
+
},
|
|
219
|
+
// Bearer tokens in headers
|
|
220
|
+
{
|
|
221
|
+
name: "bearer-token",
|
|
222
|
+
pattern: /Bearer\s+[a-zA-Z0-9_-]{20,}/gi,
|
|
223
|
+
replacement: "Bearer [REDACTED:bearer-token]",
|
|
224
|
+
enabled: true,
|
|
225
|
+
description: "Bearer authentication tokens"
|
|
226
|
+
},
|
|
227
|
+
// Basic auth in URLs
|
|
228
|
+
{
|
|
229
|
+
name: "basic-auth-url",
|
|
230
|
+
pattern: /:\/\/[^:]+:[^@]+@/g,
|
|
231
|
+
replacement: "://[REDACTED:credentials]@",
|
|
232
|
+
enabled: true,
|
|
233
|
+
description: "Basic auth credentials in URLs"
|
|
234
|
+
}
|
|
235
|
+
];
|
|
236
|
+
var Redactor = class {
|
|
237
|
+
rules = [...BUILTIN_RULES];
|
|
238
|
+
enabled = true;
|
|
239
|
+
allowlist = /* @__PURE__ */ new Set();
|
|
240
|
+
/**
|
|
241
|
+
* Enable or disable redaction globally
|
|
242
|
+
*/
|
|
243
|
+
setEnabled(enabled) {
|
|
244
|
+
this.enabled = enabled;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Check if redaction is enabled
|
|
248
|
+
*/
|
|
249
|
+
isEnabled() {
|
|
250
|
+
return this.enabled;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Enable or disable a specific rule
|
|
254
|
+
*/
|
|
255
|
+
setRuleEnabled(ruleName, enabled) {
|
|
256
|
+
const rule = this.rules.find((r) => r.name === ruleName);
|
|
257
|
+
if (rule) {
|
|
258
|
+
rule.enabled = enabled;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Add a pattern to the allowlist (won't be redacted)
|
|
263
|
+
*/
|
|
264
|
+
addToAllowlist(pattern) {
|
|
265
|
+
this.allowlist.add(pattern);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Remove a pattern from the allowlist
|
|
269
|
+
*/
|
|
270
|
+
removeFromAllowlist(pattern) {
|
|
271
|
+
this.allowlist.delete(pattern);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Add a custom redaction rule
|
|
275
|
+
*/
|
|
276
|
+
addRule(rule) {
|
|
277
|
+
this.rules.push(rule);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Get all available rules
|
|
281
|
+
*/
|
|
282
|
+
getRules() {
|
|
283
|
+
return this.rules;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Redact sensitive information from text
|
|
287
|
+
*/
|
|
288
|
+
redact(text) {
|
|
289
|
+
if (!this.enabled || !text) {
|
|
290
|
+
return { text, redactionCount: 0, redactedTypes: [] };
|
|
291
|
+
}
|
|
292
|
+
let result = text;
|
|
293
|
+
let totalRedactions = 0;
|
|
294
|
+
const redactedTypes = /* @__PURE__ */ new Set();
|
|
295
|
+
for (const rule of this.rules) {
|
|
296
|
+
if (!rule.enabled) continue;
|
|
297
|
+
rule.pattern.lastIndex = 0;
|
|
298
|
+
const matches = text.match(rule.pattern);
|
|
299
|
+
if (matches) {
|
|
300
|
+
for (const match of matches) {
|
|
301
|
+
if (this.allowlist.has(match)) continue;
|
|
302
|
+
const replacement = typeof rule.replacement === "function" ? rule.replacement(match) : rule.replacement;
|
|
303
|
+
if (replacement !== match) {
|
|
304
|
+
result = result.replace(match, replacement);
|
|
305
|
+
totalRedactions++;
|
|
306
|
+
redactedTypes.add(rule.name);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
text: result,
|
|
313
|
+
redactionCount: totalRedactions,
|
|
314
|
+
redactedTypes: Array.from(redactedTypes)
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Redact tool output specifically (used before sending to LLM)
|
|
319
|
+
*/
|
|
320
|
+
redactToolOutput(toolName, output) {
|
|
321
|
+
return this.redact(output);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Check if text contains any sensitive patterns
|
|
325
|
+
*/
|
|
326
|
+
containsSensitiveData(text) {
|
|
327
|
+
if (!text) {
|
|
328
|
+
return { hasSensitive: false, types: [] };
|
|
329
|
+
}
|
|
330
|
+
const types = [];
|
|
331
|
+
for (const rule of this.rules) {
|
|
332
|
+
if (!rule.enabled) continue;
|
|
333
|
+
rule.pattern.lastIndex = 0;
|
|
334
|
+
if (rule.pattern.test(text)) {
|
|
335
|
+
types.push(rule.name);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return { hasSensitive: types.length > 0, types };
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get statistics about what would be redacted
|
|
342
|
+
*/
|
|
343
|
+
analyze(text) {
|
|
344
|
+
const stats = [];
|
|
345
|
+
for (const rule of this.rules) {
|
|
346
|
+
if (!rule.enabled) continue;
|
|
347
|
+
rule.pattern.lastIndex = 0;
|
|
348
|
+
const matches = text.match(rule.pattern) || [];
|
|
349
|
+
if (matches.length > 0) {
|
|
350
|
+
stats.push({
|
|
351
|
+
ruleName: rule.name,
|
|
352
|
+
count: matches.length,
|
|
353
|
+
// Only show first 3 examples, partially masked
|
|
354
|
+
examples: matches.slice(0, 3).map(
|
|
355
|
+
(m) => m.length > 10 ? m.slice(0, 5) + "..." + m.slice(-3) : "***"
|
|
356
|
+
)
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return stats;
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
var redactor = new Redactor();
|
|
364
|
+
|
|
365
|
+
// src/core/auditLog.ts
|
|
366
|
+
var LOG_DIR = ".obsidian-next";
|
|
367
|
+
var LOG_FILE = "audit.log";
|
|
368
|
+
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
369
|
+
var AuditLogger = class {
|
|
370
|
+
logPath;
|
|
371
|
+
sessionId;
|
|
372
|
+
enabled = true;
|
|
373
|
+
writeQueue = [];
|
|
374
|
+
isWriting = false;
|
|
375
|
+
constructor() {
|
|
376
|
+
this.logPath = path.join(os.homedir(), LOG_DIR, LOG_FILE);
|
|
377
|
+
this.sessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Initialize the audit logger
|
|
381
|
+
*/
|
|
382
|
+
async init() {
|
|
383
|
+
const s = await settings.load();
|
|
384
|
+
this.enabled = s.security?.auditLogging ?? true;
|
|
385
|
+
if (!this.enabled) return;
|
|
386
|
+
const dir = path.dirname(this.logPath);
|
|
387
|
+
await fs.mkdir(dir, { recursive: true });
|
|
388
|
+
await this.rotateIfNeeded();
|
|
389
|
+
const cfg = await config.load();
|
|
390
|
+
await this.log({
|
|
391
|
+
eventType: "session_start",
|
|
392
|
+
success: true,
|
|
393
|
+
metadata: {
|
|
394
|
+
cwd: cfg.workspaceRoot,
|
|
395
|
+
pid: process.pid,
|
|
396
|
+
nodeVersion: process.version
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Set the session ID (called from agent)
|
|
402
|
+
*/
|
|
403
|
+
setSessionId(sessionId) {
|
|
404
|
+
this.sessionId = sessionId;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Enable or disable logging
|
|
408
|
+
*/
|
|
409
|
+
setEnabled(enabled) {
|
|
410
|
+
this.enabled = enabled;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Log a command execution
|
|
414
|
+
*/
|
|
415
|
+
async logCommand(command, success, reason) {
|
|
416
|
+
await this.log({
|
|
417
|
+
eventType: success ? "command_executed" : "command_blocked",
|
|
418
|
+
tool: "bash",
|
|
419
|
+
command: redactor.redact(command).text,
|
|
420
|
+
success,
|
|
421
|
+
reason
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Log a file operation
|
|
426
|
+
*/
|
|
427
|
+
async logFileOperation(operation, filePath, success, reason) {
|
|
428
|
+
const eventMap = {
|
|
429
|
+
read: "file_read",
|
|
430
|
+
write: "file_write",
|
|
431
|
+
edit: "file_edit",
|
|
432
|
+
delete: "file_delete"
|
|
433
|
+
};
|
|
434
|
+
await this.log({
|
|
435
|
+
eventType: eventMap[operation],
|
|
436
|
+
filePath,
|
|
437
|
+
success,
|
|
438
|
+
reason
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Log an approval decision
|
|
443
|
+
*/
|
|
444
|
+
async logApproval(status, command, reason) {
|
|
445
|
+
const eventMap = {
|
|
446
|
+
requested: "approval_requested",
|
|
447
|
+
granted: "approval_granted",
|
|
448
|
+
denied: "approval_denied",
|
|
449
|
+
timeout: "approval_timeout"
|
|
450
|
+
};
|
|
451
|
+
await this.log({
|
|
452
|
+
eventType: eventMap[status],
|
|
453
|
+
command,
|
|
454
|
+
success: status === "granted",
|
|
455
|
+
reason
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Log a security violation
|
|
460
|
+
*/
|
|
461
|
+
async logSecurityViolation(command, reason) {
|
|
462
|
+
await this.log({
|
|
463
|
+
eventType: "security_violation",
|
|
464
|
+
command,
|
|
465
|
+
success: false,
|
|
466
|
+
reason
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Log a system event
|
|
471
|
+
*/
|
|
472
|
+
async logSystemEvent(event, metadata) {
|
|
473
|
+
await this.log({
|
|
474
|
+
eventType: "security_violation",
|
|
475
|
+
// Mapping generic system events to generic log type for now, or add new type
|
|
476
|
+
command: event,
|
|
477
|
+
success: false,
|
|
478
|
+
// Usually error events
|
|
479
|
+
reason: JSON.stringify(metadata)
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Log PII redaction
|
|
484
|
+
*/
|
|
485
|
+
async logRedaction(count, types) {
|
|
486
|
+
await this.log({
|
|
487
|
+
eventType: "pii_redacted",
|
|
488
|
+
success: true,
|
|
489
|
+
metadata: { count, types }
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Core logging function
|
|
494
|
+
*/
|
|
495
|
+
async log(entry) {
|
|
496
|
+
if (!this.enabled) return;
|
|
497
|
+
const fullEntry = {
|
|
498
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
499
|
+
sessionId: this.sessionId,
|
|
500
|
+
...entry
|
|
501
|
+
};
|
|
502
|
+
this.writeQueue.push(fullEntry);
|
|
503
|
+
if (!this.isWriting) {
|
|
504
|
+
await this.processQueue();
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Process the write queue
|
|
509
|
+
*/
|
|
510
|
+
async processQueue() {
|
|
511
|
+
if (this.isWriting || this.writeQueue.length === 0) return;
|
|
512
|
+
this.isWriting = true;
|
|
513
|
+
try {
|
|
514
|
+
const entries = [...this.writeQueue];
|
|
515
|
+
this.writeQueue = [];
|
|
516
|
+
const lines = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
517
|
+
await fs.appendFile(this.logPath, lines, { encoding: "utf-8", mode: 384 });
|
|
518
|
+
} catch (error) {
|
|
519
|
+
} finally {
|
|
520
|
+
this.isWriting = false;
|
|
521
|
+
if (this.writeQueue.length > 0) {
|
|
522
|
+
setImmediate(() => this.processQueue());
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Rotate log file if too large
|
|
528
|
+
*/
|
|
529
|
+
async rotateIfNeeded() {
|
|
530
|
+
try {
|
|
531
|
+
const stats = await fs.stat(this.logPath);
|
|
532
|
+
if (stats.size >= MAX_LOG_SIZE) {
|
|
533
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
534
|
+
const rotatedPath = this.logPath.replace(".log", `.${timestamp}.log`);
|
|
535
|
+
await fs.rename(this.logPath, rotatedPath);
|
|
536
|
+
await this.cleanupOldLogs();
|
|
537
|
+
}
|
|
538
|
+
} catch {
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Clean up old rotated log files
|
|
543
|
+
*/
|
|
544
|
+
async cleanupOldLogs() {
|
|
545
|
+
try {
|
|
546
|
+
const dir = path.dirname(this.logPath);
|
|
547
|
+
const files = await fs.readdir(dir);
|
|
548
|
+
const auditLogs = files.filter((f) => f.startsWith("audit.") && f.endsWith(".log") && f !== "audit.log").sort().reverse();
|
|
549
|
+
for (const file of auditLogs.slice(5)) {
|
|
550
|
+
await fs.unlink(path.join(dir, file));
|
|
551
|
+
}
|
|
552
|
+
} catch {
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Get recent audit entries formatted for display
|
|
557
|
+
*/
|
|
558
|
+
async getRecentActivities(count = 50) {
|
|
559
|
+
const entries = await this.getRecentEntries(count);
|
|
560
|
+
return entries.map((entry) => {
|
|
561
|
+
let content = "";
|
|
562
|
+
let color = "white";
|
|
563
|
+
switch (entry.eventType) {
|
|
564
|
+
case "command_executed":
|
|
565
|
+
content = `CMD: ${entry.command || "unknown command"}`;
|
|
566
|
+
color = "blue";
|
|
567
|
+
break;
|
|
568
|
+
case "command_blocked":
|
|
569
|
+
case "command_denied":
|
|
570
|
+
case "security_violation":
|
|
571
|
+
content = `SECURITY: ${entry.reason || entry.command || "security event"}`;
|
|
572
|
+
color = "red";
|
|
573
|
+
break;
|
|
574
|
+
case "approval_requested":
|
|
575
|
+
content = `APPROVAL: Requested for "${entry.command || "action"}"`;
|
|
576
|
+
color = "yellow";
|
|
577
|
+
break;
|
|
578
|
+
case "approval_granted":
|
|
579
|
+
content = `APPROVAL: Granted for "${entry.command || "action"}"`;
|
|
580
|
+
color = "green";
|
|
581
|
+
break;
|
|
582
|
+
case "approval_denied":
|
|
583
|
+
content = `APPROVAL: Denied for "${entry.command || "action"}"`;
|
|
584
|
+
color = "red";
|
|
585
|
+
break;
|
|
586
|
+
case "file_read":
|
|
587
|
+
content = `FILE: Read ${entry.filePath}`;
|
|
588
|
+
color = "cyan";
|
|
589
|
+
break;
|
|
590
|
+
case "file_write":
|
|
591
|
+
content = `FILE: Wrote ${entry.filePath}`;
|
|
592
|
+
color = "magenta";
|
|
593
|
+
break;
|
|
594
|
+
case "file_edit":
|
|
595
|
+
content = `FILE: Edited ${entry.filePath}`;
|
|
596
|
+
color = "magentaBright";
|
|
597
|
+
break;
|
|
598
|
+
case "file_delete":
|
|
599
|
+
content = `FILE: Deleted ${entry.filePath}`;
|
|
600
|
+
color = "redBright";
|
|
601
|
+
break;
|
|
602
|
+
case "session_start":
|
|
603
|
+
content = `SESSION: Started`;
|
|
604
|
+
color = "green";
|
|
605
|
+
break;
|
|
606
|
+
case "session_end":
|
|
607
|
+
content = `SESSION: Ended`;
|
|
608
|
+
color = "gray";
|
|
609
|
+
break;
|
|
610
|
+
case "pii_redacted":
|
|
611
|
+
content = `SECURITY: PII Redacted (${entry.metadata?.count || 0} items)`;
|
|
612
|
+
color = "yellow";
|
|
613
|
+
break;
|
|
614
|
+
default:
|
|
615
|
+
content = `EVENT: ${entry.eventType}`;
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
if (entry.filePath && entry.filePath.length > 50) {
|
|
619
|
+
content = content.replace(entry.filePath, `...${entry.filePath.slice(-47)}`);
|
|
620
|
+
}
|
|
621
|
+
return {
|
|
622
|
+
timestamp: new Date(entry.timestamp).toLocaleTimeString(),
|
|
623
|
+
content,
|
|
624
|
+
color
|
|
625
|
+
};
|
|
626
|
+
}).reverse();
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Get recent audit entries
|
|
630
|
+
*/
|
|
631
|
+
async getRecentEntries(count = 100) {
|
|
632
|
+
try {
|
|
633
|
+
const content = await fs.readFile(this.logPath, "utf-8");
|
|
634
|
+
const lines = content.trim().split("\n").filter((l) => l);
|
|
635
|
+
const entries = lines.slice(-count).map((line) => {
|
|
636
|
+
try {
|
|
637
|
+
return JSON.parse(line);
|
|
638
|
+
} catch {
|
|
639
|
+
return null;
|
|
640
|
+
}
|
|
641
|
+
}).filter((e) => e !== null);
|
|
642
|
+
return entries;
|
|
643
|
+
} catch {
|
|
644
|
+
return [];
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Search audit log by event type or command
|
|
649
|
+
*/
|
|
650
|
+
async search(query) {
|
|
651
|
+
const entries = await this.getRecentEntries(1e3);
|
|
652
|
+
return entries.filter((e) => {
|
|
653
|
+
if (query.eventType && e.eventType !== query.eventType) return false;
|
|
654
|
+
if (query.command && (!e.command || !e.command.includes(query.command))) return false;
|
|
655
|
+
if (query.since && new Date(e.timestamp) < query.since) return false;
|
|
656
|
+
return true;
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Log session end (call on shutdown)
|
|
661
|
+
*/
|
|
662
|
+
async close() {
|
|
663
|
+
if (!this.enabled) return;
|
|
664
|
+
await this.log({
|
|
665
|
+
eventType: "session_end",
|
|
666
|
+
success: true
|
|
667
|
+
});
|
|
668
|
+
await this.processQueue();
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
var auditLog = new AuditLogger();
|
|
672
|
+
|
|
673
|
+
export {
|
|
674
|
+
redactor,
|
|
675
|
+
auditLog
|
|
676
|
+
};
|