@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.
Files changed (232) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +628 -190
  3. package/README.md +23 -9
  4. package/dist/auditLog-6WDBDNYL.js +8 -0
  5. package/dist/auditLog-HGPVDSDC.js +8 -0
  6. package/dist/auditLog-TDIKFBM4.js +8 -0
  7. package/dist/auditLog-XC2KY3ZZ.js +8 -0
  8. package/dist/chunk-2I235WNB.js +133 -0
  9. package/dist/chunk-2JWDGXTR.js +42 -0
  10. package/dist/chunk-2NOB6W2B.js +133 -0
  11. package/dist/chunk-3LFKVKKL.js +7199 -0
  12. package/dist/chunk-3U6WHPDX.js +4695 -0
  13. package/dist/chunk-3UCL6RYE.js +7272 -0
  14. package/dist/chunk-4GN2UQLI.js +130 -0
  15. package/dist/chunk-4MW33MZD.js +516 -0
  16. package/dist/chunk-4PUJBUKZ.js +4716 -0
  17. package/dist/chunk-4QHK6H6O.js +130 -0
  18. package/dist/chunk-55CQIHCO.js +133 -0
  19. package/dist/chunk-5LWINFWI.js +676 -0
  20. package/dist/chunk-5OKGLNQW.js +439 -0
  21. package/dist/chunk-5T6ETZEO.js +6183 -0
  22. package/dist/chunk-5WGIFUVL.js +4234 -0
  23. package/dist/chunk-66EW47T3.js +4237 -0
  24. package/dist/chunk-6TXUOTT2.js +581 -0
  25. package/dist/chunk-6YUYSYDA.js +130 -0
  26. package/dist/chunk-74VPNFMX.js +133 -0
  27. package/dist/chunk-77CGJRGV.js +6188 -0
  28. package/dist/chunk-7DS3VT4C.js +7135 -0
  29. package/dist/chunk-7FHX3VBT.js +133 -0
  30. package/dist/chunk-7MHF56YU.js +6178 -0
  31. package/dist/chunk-ABLPMV7G.js +133 -0
  32. package/dist/chunk-B77K6OQZ.js +687 -0
  33. package/dist/chunk-BKOXH66O.js +133 -0
  34. package/dist/chunk-BPP76UN2.js +130 -0
  35. package/dist/chunk-C4D56GRC.js +5936 -0
  36. package/dist/chunk-CCDPY4WE.js +370 -0
  37. package/dist/chunk-CHNVBJN3.js +7272 -0
  38. package/dist/chunk-CKBZI576.js +7229 -0
  39. package/dist/chunk-CW5HBSJ2.js +7198 -0
  40. package/dist/chunk-DGHDJEY7.js +133 -0
  41. package/dist/chunk-DPNIQWKZ.js +439 -0
  42. package/dist/chunk-DU4T3V2T.js +214 -0
  43. package/dist/chunk-DV3WFKNB.js +4679 -0
  44. package/dist/chunk-DZI2OVN2.js +516 -0
  45. package/dist/chunk-E45VILML.js +7198 -0
  46. package/dist/chunk-ECEUUYXC.js +7199 -0
  47. package/dist/chunk-EJRRSHPW.js +685 -0
  48. package/dist/chunk-EMBMLZFE.js +370 -0
  49. package/dist/chunk-EPG5V5OO.js +285 -0
  50. package/dist/chunk-F2R4HXXW.js +130 -0
  51. package/dist/chunk-FK6N66ES.js +581 -0
  52. package/dist/chunk-G3CZKGYA.js +197 -0
  53. package/dist/chunk-GUUPG4A7.js +7111 -0
  54. package/dist/chunk-HBAAUGUN.js +7230 -0
  55. package/dist/chunk-HHFJMK2Q.js +6177 -0
  56. package/dist/chunk-HINRQTCZ.js +196 -0
  57. package/dist/chunk-HRKJ3R2U.js +288 -0
  58. package/dist/chunk-HWVK4CVE.js +439 -0
  59. package/dist/chunk-JEYSADNZ.js +581 -0
  60. package/dist/chunk-JNEIL7UN.js +4252 -0
  61. package/dist/chunk-JTWSK277.js +676 -0
  62. package/dist/chunk-K4CHTTCJ.js +942 -0
  63. package/dist/chunk-K7R5KUDS.js +4695 -0
  64. package/dist/chunk-KNJFOURE.js +7151 -0
  65. package/dist/chunk-KY22FIT3.js +7256 -0
  66. package/dist/chunk-L2OTIJSF.js +4228 -0
  67. package/dist/chunk-LEEBUHP6.js +4655 -0
  68. package/dist/chunk-LK7UP2T7.js +130 -0
  69. package/dist/chunk-LPGNO3PK.js +284 -0
  70. package/dist/chunk-LYQYJMWS.js +133 -0
  71. package/dist/chunk-MBYFJXR3.js +130 -0
  72. package/dist/chunk-N3WX44L3.js +130 -0
  73. package/dist/chunk-N6AQWES3.js +6197 -0
  74. package/dist/chunk-NW4XSTQZ.js +130 -0
  75. package/dist/chunk-NWG2XURH.js +130 -0
  76. package/dist/chunk-O3GF3LJD.js +6142 -0
  77. package/dist/chunk-OHP5LD3Y.js +6188 -0
  78. package/dist/chunk-P5PQSFZT.js +6182 -0
  79. package/dist/chunk-PAADOWNP.js +130 -0
  80. package/dist/chunk-PERGND7L.js +7213 -0
  81. package/dist/chunk-PWA7V4XX.js +179 -0
  82. package/dist/chunk-QGCWEP6L.js +7111 -0
  83. package/dist/chunk-QVT2IHNJ.js +175 -0
  84. package/dist/chunk-QZNGYPMS.js +6161 -0
  85. package/dist/chunk-R6P2E2ZQ.js +207 -0
  86. package/dist/chunk-ROSDMGIL.js +4679 -0
  87. package/dist/chunk-RQZP7IKG.js +196 -0
  88. package/dist/chunk-RUQSPX3U.js +133 -0
  89. package/dist/chunk-S3BYHP5M.js +130 -0
  90. package/dist/chunk-S6GNETVE.js +438 -0
  91. package/dist/chunk-SDT2ZE2R.js +133 -0
  92. package/dist/chunk-SHQBXJFC.js +6166 -0
  93. package/dist/chunk-TJNISYTE.js +42 -0
  94. package/dist/chunk-TJW74HFF.js +130 -0
  95. package/dist/chunk-TPP72DTK.js +7096 -0
  96. package/dist/chunk-UOESII6R.js +42 -0
  97. package/dist/chunk-UWEDGLYJ.js +6142 -0
  98. package/dist/chunk-V5FYNAFX.js +133 -0
  99. package/dist/chunk-VPURF6UT.js +7198 -0
  100. package/dist/chunk-VQH6LWIZ.js +6184 -0
  101. package/dist/chunk-VS22YVX6.js +7111 -0
  102. package/dist/chunk-VSF5KBW7.js +367 -0
  103. package/dist/chunk-VV3JMCKY.js +214 -0
  104. package/dist/chunk-W5L7HOE3.js +133 -0
  105. package/dist/chunk-WFEVQISK.js +676 -0
  106. package/dist/chunk-WJZPSCEP.js +516 -0
  107. package/dist/chunk-WLV4MKEF.js +16 -0
  108. package/dist/chunk-WSEVQFFI.js +5428 -0
  109. package/dist/chunk-X7N2RNR3.js +5428 -0
  110. package/dist/chunk-XKZNMRNO.js +133 -0
  111. package/dist/chunk-Y7BVEC36.js +130 -0
  112. package/dist/chunk-YG7YSNNU.js +4226 -0
  113. package/dist/chunk-YHM62466.js +261 -0
  114. package/dist/chunk-YLTYJLDZ.js +7208 -0
  115. package/dist/chunk-YPMJD4YE.js +56 -0
  116. package/dist/chunk-YTX3FU2A.js +7199 -0
  117. package/dist/chunk-ZEQ3EBBN.js +214 -0
  118. package/dist/chunk-ZIWLQSLK.js +42 -0
  119. package/dist/chunk-ZJELNTEO.js +516 -0
  120. package/dist/chunk-ZOSSVNGK.js +370 -0
  121. package/dist/config-EYK32F2E.js +10 -0
  122. package/dist/config-FJPPPYTY.js +10 -0
  123. package/dist/config-VAHPVILX.js +10 -0
  124. package/dist/context-2YGE4U75.js +10 -0
  125. package/dist/context-5UFVYKES.js +9 -0
  126. package/dist/context-ANZF4J72.js +10 -0
  127. package/dist/context-GLUNCUBQ.js +10 -0
  128. package/dist/context-M5ULPZKQ.js +10 -0
  129. package/dist/context-NYOIRZKV.js +10 -0
  130. package/dist/context-YP2REI6A.js +10 -0
  131. package/dist/database-MP2JBLMF.js +8 -0
  132. package/dist/index.js +6177 -4688
  133. package/dist/keyManager-P2SZONKE.js +8 -0
  134. package/dist/mcp/index.js +127 -47
  135. package/dist/memory-BPGJAL4J.js +13 -0
  136. package/dist/memory-FRQOUI6W.js +13 -0
  137. package/dist/memory-OAMK27IZ.js +13 -0
  138. package/dist/memory-OZ734ALL.js +13 -0
  139. package/dist/memory-PQ2EWRMU.js +13 -0
  140. package/dist/memory-PXL45M6W.js +13 -0
  141. package/dist/memory-QZTBTYPH.js +13 -0
  142. package/dist/migrations-TLJ3WRVW.js +188 -0
  143. package/dist/resume-2NHDK6EI.js +17 -0
  144. package/dist/resume-44L2PDB2.js +17 -0
  145. package/dist/resume-4MXIWUJO.js +7 -0
  146. package/dist/resume-72VJX66I.js +17 -0
  147. package/dist/resume-7ZW4XM3B.js +15 -0
  148. package/dist/resume-AZHYQ657.js +17 -0
  149. package/dist/resume-CNLXSYHV.js +17 -0
  150. package/dist/resume-DPN4Q777.js +16 -0
  151. package/dist/resume-DSFHVNPI.js +15 -0
  152. package/dist/resume-GHLQJJTO.js +17 -0
  153. package/dist/resume-HJ6SBWTF.js +17 -0
  154. package/dist/resume-HRLYHY2L.js +17 -0
  155. package/dist/resume-ISIQFKO6.js +17 -0
  156. package/dist/resume-JQDEA6PS.js +15 -0
  157. package/dist/resume-KP3Y3Y7P.js +17 -0
  158. package/dist/resume-M4KHR5OI.js +17 -0
  159. package/dist/resume-N62OAMBG.js +17 -0
  160. package/dist/resume-NNMA5POT.js +17 -0
  161. package/dist/resume-ODYT3J4H.js +17 -0
  162. package/dist/resume-PCFJXA5O.js +17 -0
  163. package/dist/resume-PLF4XGBD.js +15 -0
  164. package/dist/resume-Q2PFX57V.js +17 -0
  165. package/dist/resume-QB4XI2J5.js +17 -0
  166. package/dist/resume-R5MFTUPF.js +17 -0
  167. package/dist/resume-SVA7223Z.js +17 -0
  168. package/dist/resume-TYKKDJZI.js +17 -0
  169. package/dist/resume-XIS45HKV.js +17 -0
  170. package/dist/resume-YCSEJTU7.js +17 -0
  171. package/dist/resume-YD76GI2J.js +15 -0
  172. package/dist/resume-YDN7EL77.js +17 -0
  173. package/dist/resume-YE7DB4ZA.js +17 -0
  174. package/dist/resume-YKAKOXWV.js +15 -0
  175. package/dist/resume-ZHBCVFDY.js +17 -0
  176. package/dist/scheduler-2CK24A2Q.js +14 -0
  177. package/dist/scheduler-7OAF2XKX.js +14 -0
  178. package/dist/scheduler-AS23AAB5.js +14 -0
  179. package/dist/scheduler-PCOYQJA5.js +14 -0
  180. package/dist/scheduler-V2ECBQPK.js +14 -0
  181. package/dist/scheduler-VEWZ6L7V.js +13 -0
  182. package/dist/scheduler-W37QMGDQ.js +14 -0
  183. package/dist/session-2E2JKPD7.js +15 -0
  184. package/dist/session-2VSF257B.js +14 -0
  185. package/dist/session-4APFTDJU.js +14 -0
  186. package/dist/session-5YS5LNNL.js +16 -0
  187. package/dist/session-6MO5ZPOB.js +16 -0
  188. package/dist/session-6XMGPRTQ.js +14 -0
  189. package/dist/session-7DJR77R7.js +16 -0
  190. package/dist/session-7DQHPWTR.js +14 -0
  191. package/dist/session-ADKIQCR5.js +16 -0
  192. package/dist/session-AOGH2GGI.js +16 -0
  193. package/dist/session-C4W6GDYG.js +16 -0
  194. package/dist/session-DCGNGGMV.js +14 -0
  195. package/dist/session-F5JKZAN2.js +16 -0
  196. package/dist/session-G6F3O2FQ.js +16 -0
  197. package/dist/session-GFBSARRO.js +16 -0
  198. package/dist/session-H5IWAIUI.js +16 -0
  199. package/dist/session-IPFA6AHC.js +14 -0
  200. package/dist/session-IWG2UOAX.js +14 -0
  201. package/dist/session-KJ2K4Y4M.js +14 -0
  202. package/dist/session-KPXFBW6Q.js +14 -0
  203. package/dist/session-KR256UL5.js +16 -0
  204. package/dist/session-M72LJXPR.js +16 -0
  205. package/dist/session-MBK3FODN.js +14 -0
  206. package/dist/session-MOUFAU7G.js +16 -0
  207. package/dist/session-NRC6ZXFQ.js +16 -0
  208. package/dist/session-NRPQMV4K.js +16 -0
  209. package/dist/session-O5IFFJZQ.js +14 -0
  210. package/dist/session-OF5BGKDE.js +16 -0
  211. package/dist/session-OGRZMIM7.js +14 -0
  212. package/dist/session-OJOFAJG3.js +16 -0
  213. package/dist/session-OKU4N3SP.js +16 -0
  214. package/dist/session-P2VAOSFB.js +14 -0
  215. package/dist/session-PKOVZD4M.js +16 -0
  216. package/dist/session-POAIMUVN.js +16 -0
  217. package/dist/session-PSHFONFE.js +16 -0
  218. package/dist/session-QKYVVZFV.js +16 -0
  219. package/dist/session-QPWGBMUS.js +14 -0
  220. package/dist/session-R5UG5PZR.js +14 -0
  221. package/dist/session-RAY6BZRQ.js +16 -0
  222. package/dist/session-S3VATHMU.js +16 -0
  223. package/dist/session-SYTD7RHW.js +14 -0
  224. package/dist/session-UHMMVO4J.js +16 -0
  225. package/dist/session-WEX5K3ZY.js +14 -0
  226. package/dist/session-XFLOXGU3.js +14 -0
  227. package/dist/session-XV2A4HHG.js +14 -0
  228. package/dist/settings-3VPJYD4D.js +8 -0
  229. package/dist/settings-GZTJJTBK.js +8 -0
  230. package/dist/settings-YKJFSKMO.js +8 -0
  231. package/dist/shell-FM34624T.js +8 -0
  232. package/package.json +14 -4
@@ -0,0 +1,942 @@
1
+ import {
2
+ context
3
+ } from "./chunk-DPNIQWKZ.js";
4
+ import {
5
+ config
6
+ } from "./chunk-G3CZKGYA.js";
7
+ import {
8
+ settings
9
+ } from "./chunk-HRKJ3R2U.js";
10
+ import {
11
+ bus
12
+ } from "./chunk-WQM6FFSD.js";
13
+ import {
14
+ db
15
+ } from "./chunk-R6P2E2ZQ.js";
16
+
17
+ // src/core/scheduler.ts
18
+ import cronParser from "cron-parser";
19
+
20
+ // src/core/auditLog.ts
21
+ import fs from "fs/promises";
22
+ import path from "path";
23
+ import os from "os";
24
+
25
+ // src/core/redactor.ts
26
+ var BUILTIN_RULES = [
27
+ // Email addresses
28
+ {
29
+ name: "email",
30
+ pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
31
+ replacement: "[REDACTED:email]",
32
+ enabled: true,
33
+ description: "Email addresses"
34
+ },
35
+ // Phone numbers (various formats) - must have separators to avoid false positives
36
+ {
37
+ name: "phone",
38
+ pattern: /(\+?1[-.\s])?\(?\d{3}\)?[-.\s]\d{3,4}[-.\s]\d{4}\b/g,
39
+ replacement: "[REDACTED:phone]",
40
+ enabled: true,
41
+ description: "Phone numbers (US format with separators)"
42
+ },
43
+ // Social Security Numbers
44
+ {
45
+ name: "ssn",
46
+ pattern: /\b\d{3}[-\s]?\d{2}[-\s]?\d{4}\b/g,
47
+ replacement: "[REDACTED:ssn]",
48
+ enabled: true,
49
+ description: "Social Security Numbers"
50
+ },
51
+ // Credit card numbers (basic patterns)
52
+ {
53
+ name: "credit-card",
54
+ 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,
55
+ replacement: "[REDACTED:credit-card]",
56
+ enabled: true,
57
+ description: "Credit card numbers"
58
+ },
59
+ // AWS Access Keys
60
+ {
61
+ name: "aws-access-key",
62
+ pattern: /\b(AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}\b/g,
63
+ replacement: "[REDACTED:aws-key]",
64
+ enabled: true,
65
+ description: "AWS access key IDs"
66
+ },
67
+ // AWS Secret Keys (40 char base64-like)
68
+ {
69
+ name: "aws-secret-key",
70
+ pattern: /\b[A-Za-z0-9/+=]{40}\b/g,
71
+ replacement: (match) => {
72
+ if (/[A-Z]/.test(match) && /[a-z]/.test(match) && /[/+=]/.test(match)) {
73
+ return "[REDACTED:aws-secret]";
74
+ }
75
+ return match;
76
+ },
77
+ enabled: true,
78
+ description: "AWS secret access keys"
79
+ },
80
+ // Anthropic API Keys
81
+ {
82
+ name: "anthropic-key",
83
+ pattern: /\bsk-ant-[a-zA-Z0-9-_]{20,}/g,
84
+ replacement: "[REDACTED:anthropic-key]",
85
+ enabled: true,
86
+ description: "Anthropic API keys"
87
+ },
88
+ // OpenAI API Keys (start with sk- but not sk-ant-, may contain hyphens)
89
+ {
90
+ name: "openai-key",
91
+ pattern: /sk-(?!ant)[a-zA-Z0-9-]{20,}/g,
92
+ replacement: "[REDACTED:openai-key]",
93
+ enabled: true,
94
+ description: "OpenAI API keys"
95
+ },
96
+ // Generic API keys (common patterns)
97
+ {
98
+ name: "api-key-generic",
99
+ pattern: /\b(api[_-]?key|apikey|api[_-]?secret|api[_-]?token)\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
100
+ replacement: (match) => {
101
+ const keyName = match.split(/[=:]/)[0].trim();
102
+ return `${keyName}=[REDACTED:api-key]`;
103
+ },
104
+ enabled: true,
105
+ description: "Generic API keys in config"
106
+ },
107
+ // Passwords in config files (various naming conventions)
108
+ {
109
+ name: "password-config",
110
+ pattern: /\b([A-Z_]*(?:PASSWORD|PASSWD|PWD|SECRET)[A-Z_]*)\s*[=:]\s*['"]?([^'"\s\n]{4,})['"]?/gi,
111
+ replacement: (match) => {
112
+ const keyName = match.split(/[=:]/)[0].trim();
113
+ return `${keyName}=[REDACTED:password]`;
114
+ },
115
+ enabled: true,
116
+ description: "Passwords in configuration"
117
+ },
118
+ // Private keys (PEM format)
119
+ {
120
+ name: "private-key",
121
+ pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END\s+(RSA\s+)?PRIVATE\s+KEY-----/g,
122
+ replacement: "[REDACTED:private-key]",
123
+ enabled: true,
124
+ description: "PEM private keys"
125
+ },
126
+ // JWT tokens
127
+ {
128
+ name: "jwt",
129
+ pattern: /\beyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/g,
130
+ replacement: "[REDACTED:jwt]",
131
+ enabled: true,
132
+ description: "JWT tokens"
133
+ },
134
+ // GitHub tokens (various prefixes)
135
+ {
136
+ name: "github-token",
137
+ pattern: /(ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{20,}/g,
138
+ replacement: "[REDACTED:github-token]",
139
+ enabled: true,
140
+ description: "GitHub tokens"
141
+ },
142
+ // Stripe keys
143
+ {
144
+ name: "stripe-key",
145
+ pattern: /\b(sk|pk)_(test|live)_[a-zA-Z0-9]{24,}/g,
146
+ replacement: "[REDACTED:stripe-key]",
147
+ enabled: true,
148
+ description: "Stripe API keys"
149
+ },
150
+ // IP addresses (private networks only by default)
151
+ {
152
+ name: "private-ip",
153
+ 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,
154
+ replacement: "[REDACTED:private-ip]",
155
+ enabled: false,
156
+ // Disabled by default - may cause issues with code
157
+ description: "Private IP addresses"
158
+ },
159
+ // GitHub Fine-grained Personal Access Tokens (newer format)
160
+ {
161
+ name: "github-fine-grained-pat",
162
+ pattern: /github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}/g,
163
+ replacement: "[REDACTED:github-pat]",
164
+ enabled: true,
165
+ description: "GitHub fine-grained personal access tokens"
166
+ },
167
+ // Slack tokens (various types)
168
+ {
169
+ name: "slack-token",
170
+ pattern: /xox[baprs]-[a-zA-Z0-9-]{10,}/g,
171
+ replacement: "[REDACTED:slack-token]",
172
+ enabled: true,
173
+ description: "Slack API tokens"
174
+ },
175
+ // Discord tokens
176
+ {
177
+ name: "discord-token",
178
+ pattern: /[MN][A-Za-z\d]{23,}\.[\w-]{6}\.[\w-]{27}/g,
179
+ replacement: "[REDACTED:discord-token]",
180
+ enabled: true,
181
+ description: "Discord bot tokens"
182
+ },
183
+ // Google API keys
184
+ {
185
+ name: "google-api-key",
186
+ pattern: /AIza[0-9A-Za-z\\-_]{35}/g,
187
+ replacement: "[REDACTED:google-api-key]",
188
+ enabled: true,
189
+ description: "Google API keys"
190
+ },
191
+ // Twilio keys
192
+ {
193
+ name: "twilio-key",
194
+ pattern: /SK[a-f0-9]{32}/g,
195
+ replacement: "[REDACTED:twilio-key]",
196
+ enabled: true,
197
+ description: "Twilio API keys"
198
+ },
199
+ // SendGrid keys
200
+ {
201
+ name: "sendgrid-key",
202
+ pattern: /SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/g,
203
+ replacement: "[REDACTED:sendgrid-key]",
204
+ enabled: true,
205
+ description: "SendGrid API keys"
206
+ },
207
+ // NPM tokens
208
+ {
209
+ name: "npm-token",
210
+ pattern: /npm_[a-zA-Z0-9]{36}/g,
211
+ replacement: "[REDACTED:npm-token]",
212
+ enabled: true,
213
+ description: "NPM access tokens"
214
+ },
215
+ // PyPI tokens
216
+ {
217
+ name: "pypi-token",
218
+ pattern: /pypi-[a-zA-Z0-9_-]{100,}/g,
219
+ replacement: "[REDACTED:pypi-token]",
220
+ enabled: true,
221
+ description: "PyPI API tokens"
222
+ },
223
+ // Database connection strings
224
+ {
225
+ name: "db-connection-string",
226
+ pattern: /(mongodb(\+srv)?|postgres(ql)?|mysql|redis):\/\/[^\s'"]+/gi,
227
+ replacement: "[REDACTED:db-connection-string]",
228
+ enabled: true,
229
+ description: "Database connection strings"
230
+ },
231
+ // Bearer tokens in headers
232
+ {
233
+ name: "bearer-token",
234
+ pattern: /Bearer\s+[a-zA-Z0-9_-]{20,}/gi,
235
+ replacement: "Bearer [REDACTED:bearer-token]",
236
+ enabled: true,
237
+ description: "Bearer authentication tokens"
238
+ },
239
+ // Basic auth in URLs
240
+ {
241
+ name: "basic-auth-url",
242
+ pattern: /:\/\/[^:]+:[^@]+@/g,
243
+ replacement: "://[REDACTED:credentials]@",
244
+ enabled: true,
245
+ description: "Basic auth credentials in URLs"
246
+ }
247
+ ];
248
+ var Redactor = class {
249
+ rules = [...BUILTIN_RULES];
250
+ enabled = true;
251
+ allowlist = /* @__PURE__ */ new Set();
252
+ /**
253
+ * Enable or disable redaction globally
254
+ */
255
+ setEnabled(enabled) {
256
+ this.enabled = enabled;
257
+ }
258
+ /**
259
+ * Check if redaction is enabled
260
+ */
261
+ isEnabled() {
262
+ return this.enabled;
263
+ }
264
+ /**
265
+ * Enable or disable a specific rule
266
+ */
267
+ setRuleEnabled(ruleName, enabled) {
268
+ const rule = this.rules.find((r) => r.name === ruleName);
269
+ if (rule) {
270
+ rule.enabled = enabled;
271
+ }
272
+ }
273
+ /**
274
+ * Add a pattern to the allowlist (won't be redacted)
275
+ */
276
+ addToAllowlist(pattern) {
277
+ this.allowlist.add(pattern);
278
+ }
279
+ /**
280
+ * Remove a pattern from the allowlist
281
+ */
282
+ removeFromAllowlist(pattern) {
283
+ this.allowlist.delete(pattern);
284
+ }
285
+ /**
286
+ * Add a custom redaction rule
287
+ */
288
+ addRule(rule) {
289
+ this.rules.push(rule);
290
+ }
291
+ /**
292
+ * Get all available rules
293
+ */
294
+ getRules() {
295
+ return this.rules;
296
+ }
297
+ /**
298
+ * Redact sensitive information from text
299
+ */
300
+ redact(text) {
301
+ if (!this.enabled || !text) {
302
+ return { text, redactionCount: 0, redactedTypes: [] };
303
+ }
304
+ let result = text;
305
+ let totalRedactions = 0;
306
+ const redactedTypes = /* @__PURE__ */ new Set();
307
+ for (const rule of this.rules) {
308
+ if (!rule.enabled) continue;
309
+ rule.pattern.lastIndex = 0;
310
+ const matches = text.match(rule.pattern);
311
+ if (matches) {
312
+ for (const match of matches) {
313
+ if (this.allowlist.has(match)) continue;
314
+ const replacement = typeof rule.replacement === "function" ? rule.replacement(match) : rule.replacement;
315
+ if (replacement !== match) {
316
+ result = result.replace(match, replacement);
317
+ totalRedactions++;
318
+ redactedTypes.add(rule.name);
319
+ }
320
+ }
321
+ }
322
+ }
323
+ return {
324
+ text: result,
325
+ redactionCount: totalRedactions,
326
+ redactedTypes: Array.from(redactedTypes)
327
+ };
328
+ }
329
+ /**
330
+ * Redact tool output specifically (used before sending to LLM)
331
+ */
332
+ redactToolOutput(toolName, output) {
333
+ return this.redact(output);
334
+ }
335
+ /**
336
+ * Check if text contains any sensitive patterns
337
+ */
338
+ containsSensitiveData(text) {
339
+ if (!text) {
340
+ return { hasSensitive: false, types: [] };
341
+ }
342
+ const types = [];
343
+ for (const rule of this.rules) {
344
+ if (!rule.enabled) continue;
345
+ rule.pattern.lastIndex = 0;
346
+ if (rule.pattern.test(text)) {
347
+ types.push(rule.name);
348
+ }
349
+ }
350
+ return { hasSensitive: types.length > 0, types };
351
+ }
352
+ /**
353
+ * Get statistics about what would be redacted
354
+ */
355
+ analyze(text) {
356
+ const stats = [];
357
+ for (const rule of this.rules) {
358
+ if (!rule.enabled) continue;
359
+ rule.pattern.lastIndex = 0;
360
+ const matches = text.match(rule.pattern) || [];
361
+ if (matches.length > 0) {
362
+ stats.push({
363
+ ruleName: rule.name,
364
+ count: matches.length,
365
+ // Only show first 3 examples, partially masked
366
+ examples: matches.slice(0, 3).map(
367
+ (m) => m.length > 10 ? m.slice(0, 5) + "..." + m.slice(-3) : "***"
368
+ )
369
+ });
370
+ }
371
+ }
372
+ return stats;
373
+ }
374
+ };
375
+ var redactor = new Redactor();
376
+
377
+ // src/core/auditLog.ts
378
+ var LOG_DIR = ".obsidian-next";
379
+ var LOG_FILE = "audit.log";
380
+ var MAX_LOG_SIZE = 10 * 1024 * 1024;
381
+ var AuditLogger = class {
382
+ logPath;
383
+ sessionId;
384
+ enabled = true;
385
+ writeQueue = [];
386
+ isWriting = false;
387
+ constructor() {
388
+ this.logPath = path.join(os.homedir(), LOG_DIR, LOG_FILE);
389
+ this.sessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
390
+ }
391
+ /**
392
+ * Initialize the audit logger
393
+ */
394
+ async init() {
395
+ const s = await settings.load();
396
+ this.enabled = s.security?.auditLogging ?? true;
397
+ if (!this.enabled) return;
398
+ const dir = path.dirname(this.logPath);
399
+ await fs.mkdir(dir, { recursive: true });
400
+ await this.rotateIfNeeded();
401
+ const cfg = await config.load();
402
+ await this.log({
403
+ eventType: "session_start",
404
+ success: true,
405
+ metadata: {
406
+ cwd: cfg.workspaceRoot,
407
+ pid: process.pid,
408
+ nodeVersion: process.version
409
+ }
410
+ });
411
+ }
412
+ /**
413
+ * Set the session ID (called from agent)
414
+ */
415
+ setSessionId(sessionId) {
416
+ this.sessionId = sessionId;
417
+ }
418
+ /**
419
+ * Enable or disable logging
420
+ */
421
+ setEnabled(enabled) {
422
+ this.enabled = enabled;
423
+ }
424
+ /**
425
+ * Log a command execution
426
+ */
427
+ async logCommand(command, success, reason) {
428
+ await this.log({
429
+ eventType: success ? "command_executed" : "command_blocked",
430
+ tool: "bash",
431
+ command: redactor.redact(command).text,
432
+ success,
433
+ reason
434
+ });
435
+ }
436
+ /**
437
+ * Log a file operation
438
+ */
439
+ async logFileOperation(operation, filePath, success, reason) {
440
+ const eventMap = {
441
+ read: "file_read",
442
+ write: "file_write",
443
+ edit: "file_edit",
444
+ delete: "file_delete"
445
+ };
446
+ await this.log({
447
+ eventType: eventMap[operation],
448
+ filePath,
449
+ success,
450
+ reason
451
+ });
452
+ }
453
+ /**
454
+ * Log an approval decision
455
+ */
456
+ async logApproval(status, command, reason) {
457
+ const eventMap = {
458
+ requested: "approval_requested",
459
+ granted: "approval_granted",
460
+ denied: "approval_denied",
461
+ timeout: "approval_timeout"
462
+ };
463
+ await this.log({
464
+ eventType: eventMap[status],
465
+ command,
466
+ success: status === "granted",
467
+ reason
468
+ });
469
+ }
470
+ /**
471
+ * Log a security violation
472
+ */
473
+ async logSecurityViolation(command, reason) {
474
+ await this.log({
475
+ eventType: "security_violation",
476
+ command,
477
+ success: false,
478
+ reason
479
+ });
480
+ }
481
+ /**
482
+ * Log a system event
483
+ */
484
+ async logSystemEvent(event, metadata) {
485
+ await this.log({
486
+ eventType: "security_violation",
487
+ // Mapping generic system events to generic log type for now, or add new type
488
+ command: event,
489
+ success: false,
490
+ // Usually error events
491
+ reason: JSON.stringify(metadata)
492
+ });
493
+ }
494
+ /**
495
+ * Log PII redaction
496
+ */
497
+ async logRedaction(count, types) {
498
+ await this.log({
499
+ eventType: "pii_redacted",
500
+ success: true,
501
+ metadata: { count, types }
502
+ });
503
+ }
504
+ /**
505
+ * Core logging function
506
+ */
507
+ async log(entry) {
508
+ if (!this.enabled) return;
509
+ const fullEntry = {
510
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
511
+ sessionId: this.sessionId,
512
+ ...entry
513
+ };
514
+ this.writeQueue.push(fullEntry);
515
+ if (!this.isWriting) {
516
+ await this.processQueue();
517
+ }
518
+ }
519
+ /**
520
+ * Process the write queue
521
+ */
522
+ async processQueue() {
523
+ if (this.isWriting || this.writeQueue.length === 0) return;
524
+ this.isWriting = true;
525
+ try {
526
+ const entries = [...this.writeQueue];
527
+ this.writeQueue = [];
528
+ const lines = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
529
+ await fs.appendFile(this.logPath, lines, {
530
+ encoding: "utf-8",
531
+ mode: 384
532
+ });
533
+ } catch (error) {
534
+ } finally {
535
+ this.isWriting = false;
536
+ if (this.writeQueue.length > 0) {
537
+ setImmediate(() => this.processQueue());
538
+ }
539
+ }
540
+ }
541
+ /**
542
+ * Rotate log file if too large
543
+ */
544
+ async rotateIfNeeded() {
545
+ try {
546
+ const stats = await fs.stat(this.logPath);
547
+ if (stats.size >= MAX_LOG_SIZE) {
548
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
549
+ const rotatedPath = this.logPath.replace(".log", `.${timestamp}.log`);
550
+ await fs.rename(this.logPath, rotatedPath);
551
+ await this.cleanupOldLogs();
552
+ }
553
+ } catch {
554
+ }
555
+ }
556
+ /**
557
+ * Clean up old rotated log files
558
+ */
559
+ async cleanupOldLogs() {
560
+ try {
561
+ const dir = path.dirname(this.logPath);
562
+ const files = await fs.readdir(dir);
563
+ const auditLogs = files.filter(
564
+ (f) => f.startsWith("audit.") && f.endsWith(".log") && f !== "audit.log"
565
+ ).sort().reverse();
566
+ for (const file of auditLogs.slice(5)) {
567
+ await fs.unlink(path.join(dir, file));
568
+ }
569
+ } catch {
570
+ }
571
+ }
572
+ /**
573
+ * Get recent audit entries formatted for display
574
+ */
575
+ async getRecentActivities(count = 50) {
576
+ const entries = await this.getRecentEntries(count);
577
+ return entries.map((entry) => {
578
+ let content = "";
579
+ let color = "white";
580
+ switch (entry.eventType) {
581
+ case "command_executed":
582
+ content = `CMD: ${entry.command || "unknown command"}`;
583
+ color = "blue";
584
+ break;
585
+ case "command_blocked":
586
+ case "command_denied":
587
+ case "security_violation":
588
+ content = `SECURITY: ${entry.reason || entry.command || "security event"}`;
589
+ color = "red";
590
+ break;
591
+ case "approval_requested":
592
+ content = `APPROVAL: Requested for "${entry.command || "action"}"`;
593
+ color = "yellow";
594
+ break;
595
+ case "approval_granted":
596
+ content = `APPROVAL: Granted for "${entry.command || "action"}"`;
597
+ color = "green";
598
+ break;
599
+ case "approval_denied":
600
+ content = `APPROVAL: Denied for "${entry.command || "action"}"`;
601
+ color = "red";
602
+ break;
603
+ case "file_read":
604
+ content = `FILE: Read ${entry.filePath}`;
605
+ color = "cyan";
606
+ break;
607
+ case "file_write":
608
+ content = `FILE: Wrote ${entry.filePath}`;
609
+ color = "magenta";
610
+ break;
611
+ case "file_edit":
612
+ content = `FILE: Edited ${entry.filePath}`;
613
+ color = "magentaBright";
614
+ break;
615
+ case "file_delete":
616
+ content = `FILE: Deleted ${entry.filePath}`;
617
+ color = "redBright";
618
+ break;
619
+ case "session_start":
620
+ content = `SESSION: Started`;
621
+ color = "green";
622
+ break;
623
+ case "session_end":
624
+ content = `SESSION: Ended`;
625
+ color = "gray";
626
+ break;
627
+ case "pii_redacted":
628
+ content = `SECURITY: PII Redacted (${entry.metadata?.count || 0} items)`;
629
+ color = "yellow";
630
+ break;
631
+ default:
632
+ content = `EVENT: ${entry.eventType}`;
633
+ break;
634
+ }
635
+ if (entry.filePath && entry.filePath.length > 50) {
636
+ content = content.replace(
637
+ entry.filePath,
638
+ `...${entry.filePath.slice(-47)}`
639
+ );
640
+ }
641
+ return {
642
+ timestamp: new Date(entry.timestamp).toLocaleTimeString(),
643
+ content,
644
+ color
645
+ };
646
+ }).reverse();
647
+ }
648
+ /**
649
+ * Get recent audit entries
650
+ */
651
+ async getRecentEntries(count = 100) {
652
+ try {
653
+ const content = await fs.readFile(this.logPath, "utf-8");
654
+ const lines = content.trim().split("\n").filter((l) => l);
655
+ const entries = lines.slice(-count).map((line) => {
656
+ try {
657
+ return JSON.parse(line);
658
+ } catch {
659
+ return null;
660
+ }
661
+ }).filter((e) => e !== null);
662
+ return entries;
663
+ } catch {
664
+ return [];
665
+ }
666
+ }
667
+ /**
668
+ * Search audit log by event type or command
669
+ */
670
+ async search(query) {
671
+ const entries = await this.getRecentEntries(1e3);
672
+ return entries.filter((e) => {
673
+ if (query.eventType && e.eventType !== query.eventType) return false;
674
+ if (query.command && (!e.command || !e.command.includes(query.command)))
675
+ return false;
676
+ if (query.since && new Date(e.timestamp) < query.since) return false;
677
+ return true;
678
+ });
679
+ }
680
+ /**
681
+ * Log session end (call on shutdown)
682
+ */
683
+ async close() {
684
+ if (!this.enabled) return;
685
+ await this.log({
686
+ eventType: "session_end",
687
+ success: true
688
+ });
689
+ await this.processQueue();
690
+ }
691
+ };
692
+ var auditLog = new AuditLogger();
693
+
694
+ // src/core/scheduler.ts
695
+ var parseExpression = cronParser.parseExpression || cronParser.default?.parseExpression || cronParser.parse || cronParser.default?.parse;
696
+ var MAX_CONSECUTIVE_FAILURES = 3;
697
+ var Scheduler = class _Scheduler {
698
+ static instance;
699
+ abilities = /* @__PURE__ */ new Map();
700
+ timer = null;
701
+ isRunning = false;
702
+ failureCounts = /* @__PURE__ */ new Map();
703
+ constructor() {
704
+ }
705
+ static getInstance() {
706
+ if (!_Scheduler.instance) {
707
+ _Scheduler.instance = new _Scheduler();
708
+ }
709
+ return _Scheduler.instance;
710
+ }
711
+ /**
712
+ * Initialize the scheduler loop
713
+ */
714
+ start() {
715
+ if (this.isRunning) return;
716
+ this.isRunning = true;
717
+ this.tick().catch(
718
+ (err) => bus.emitAgent({
719
+ type: "error",
720
+ message: `[Scheduler] Initial tick failed: ${err instanceof Error ? err.message : String(err)}`
721
+ })
722
+ );
723
+ this.timer = setInterval(() => this.tick(), 1e4);
724
+ bus.emitAgent({
725
+ type: "thought",
726
+ content: "[Obsidian] Started background task monitor [Active Heartbeat]"
727
+ });
728
+ }
729
+ stop() {
730
+ if (this.timer) {
731
+ clearInterval(this.timer);
732
+ this.timer = null;
733
+ }
734
+ this.isRunning = false;
735
+ }
736
+ /**
737
+ * Register a new ability that can be scheduled
738
+ */
739
+ registerAbility(name, func) {
740
+ this.abilities.set(name, func);
741
+ }
742
+ /**
743
+ * Get list of registered abilities
744
+ */
745
+ getAbilities() {
746
+ return Array.from(this.abilities.keys());
747
+ }
748
+ /**
749
+ * Schedule a new task
750
+ */
751
+ async scheduleTask(cronExpression, abilityName, params = {}) {
752
+ try {
753
+ parseExpression(cronExpression);
754
+ } catch (err) {
755
+ throw new Error(`Invalid cron expression: ${cronExpression}`);
756
+ }
757
+ if (!this.abilities.has(abilityName)) {
758
+ throw new Error(`Unknown ability: ${abilityName}`);
759
+ }
760
+ const id = `task_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
761
+ const sessionId = context.get().session_id;
762
+ const task = {
763
+ id,
764
+ session_id: sessionId,
765
+ cron_expression: cronExpression,
766
+ command: abilityName,
767
+ params: JSON.stringify(params),
768
+ last_run_at: Date.now(),
769
+ active: 1
770
+ };
771
+ db.getDb().prepare(
772
+ `
773
+ INSERT INTO scheduled_tasks (id, session_id, cron_expression, command, params, last_run_at, active)
774
+ VALUES (?, ?, ?, ?, ?, ?, ?)
775
+ `
776
+ ).run(
777
+ task.id,
778
+ task.session_id,
779
+ task.cron_expression,
780
+ task.command,
781
+ task.params,
782
+ task.last_run_at,
783
+ task.active
784
+ );
785
+ bus.emitAgent({
786
+ type: "thought",
787
+ content: `[Scheduler] Scheduled ${abilityName} (${cronExpression})`
788
+ });
789
+ return task;
790
+ }
791
+ /**
792
+ * List all active tasks
793
+ */
794
+ listTasks() {
795
+ const tasks = db.getDb().prepare(
796
+ `
797
+ SELECT * FROM scheduled_tasks WHERE active = 1
798
+ `
799
+ ).all();
800
+ return tasks.map((t) => {
801
+ try {
802
+ const interval = parseExpression(t.cron_expression);
803
+ t.next_run_at = interval.next().getTime();
804
+ } catch {
805
+ t.next_run_at = 0;
806
+ }
807
+ return t;
808
+ });
809
+ }
810
+ /**
811
+ * Main execution loop
812
+ */
813
+ async tick() {
814
+ const tasks = this.listTasks();
815
+ const now = Date.now();
816
+ for (const task of tasks) {
817
+ try {
818
+ const baseline = task.last_run_at || now - 61e3;
819
+ let taskParams = {};
820
+ try {
821
+ taskParams = task.params ? JSON.parse(task.params) : {};
822
+ } catch {
823
+ }
824
+ if (taskParams.__once && taskParams.__target) {
825
+ if (now >= taskParams.__target) {
826
+ await this.executeTask(task);
827
+ }
828
+ continue;
829
+ }
830
+ const interval = parseExpression(task.cron_expression, {
831
+ currentDate: baseline
832
+ });
833
+ const nextRun = interval.next().getTime();
834
+ if (nextRun <= now) {
835
+ await this.executeTask(task);
836
+ }
837
+ } catch (error) {
838
+ bus.emitAgent({
839
+ type: "error",
840
+ message: `[Scheduler] Error checking task ${task.id}: ${error instanceof Error ? error.message : String(error)}`
841
+ });
842
+ }
843
+ }
844
+ }
845
+ async executeTask(task) {
846
+ const ability = this.abilities.get(task.command);
847
+ if (!ability) {
848
+ bus.emitAgent({
849
+ type: "error",
850
+ message: `[Scheduler] Ability "${task.command}" not found. Disabling task ${task.id}.`
851
+ });
852
+ db.getDb().prepare("UPDATE scheduled_tasks SET active = 0 WHERE id = ?").run(task.id);
853
+ return;
854
+ }
855
+ bus.emitAgent({
856
+ type: "scheduler_task_started",
857
+ taskId: task.id,
858
+ command: task.command
859
+ });
860
+ try {
861
+ let params = {};
862
+ if (task.params) {
863
+ try {
864
+ params = JSON.parse(task.params);
865
+ } catch {
866
+ }
867
+ }
868
+ await ability(params);
869
+ bus.emitAgent({
870
+ type: "scheduler_task_completed",
871
+ taskId: task.id,
872
+ command: task.command
873
+ });
874
+ this.failureCounts.delete(task.id);
875
+ if (params.__once) {
876
+ db.getDb().prepare(`UPDATE scheduled_tasks SET active = 0 WHERE id = ?`).run(task.id);
877
+ bus.emitAgent({
878
+ type: "thought",
879
+ content: `[Scheduler] One-time task ${task.id} completed and deactivated.`
880
+ });
881
+ }
882
+ } catch (error) {
883
+ await auditLog.logSystemEvent("scheduler_error", {
884
+ taskId: task.id,
885
+ error: error.message
886
+ });
887
+ bus.emitAgent({
888
+ type: "scheduler_task_failed",
889
+ taskId: task.id,
890
+ command: task.command,
891
+ error: error.message
892
+ });
893
+ const failures = (this.failureCounts.get(task.id) || 0) + 1;
894
+ this.failureCounts.set(task.id, failures);
895
+ if (failures >= MAX_CONSECUTIVE_FAILURES) {
896
+ db.getDb().prepare("UPDATE scheduled_tasks SET active = 0 WHERE id = ?").run(task.id);
897
+ this.failureCounts.delete(task.id);
898
+ bus.emitAgent({
899
+ type: "error",
900
+ message: `[Scheduler] Task ${task.id} (${task.command}) disabled after ${MAX_CONSECUTIVE_FAILURES} consecutive failures.`
901
+ });
902
+ } else {
903
+ bus.emitAgent({
904
+ type: "error",
905
+ message: `[Scheduler] Task ${task.id} (${task.command}) failed: ${error.message} (${failures}/${MAX_CONSECUTIVE_FAILURES} before auto-disable)`
906
+ });
907
+ }
908
+ } finally {
909
+ db.getDb().prepare(
910
+ `
911
+ UPDATE scheduled_tasks SET last_run_at = ? WHERE id = ?
912
+ `
913
+ ).run(Date.now(), task.id);
914
+ }
915
+ }
916
+ /**
917
+ * Remove (deactivate) a scheduled task
918
+ */
919
+ async removeTask(taskId) {
920
+ const result = db.getDb().prepare(
921
+ `
922
+ UPDATE scheduled_tasks SET active = 0 WHERE id = ?
923
+ `
924
+ ).run(taskId);
925
+ if (result.changes && result.changes > 0) {
926
+ bus.emitAgent({
927
+ type: "thought",
928
+ content: `[Scheduler] Deactivated task: ${taskId}`
929
+ });
930
+ return true;
931
+ }
932
+ return false;
933
+ }
934
+ };
935
+ var scheduler = Scheduler.getInstance();
936
+
937
+ export {
938
+ redactor,
939
+ auditLog,
940
+ Scheduler,
941
+ scheduler
942
+ };