specweave 0.28.68 → 0.29.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.
Files changed (234) hide show
  1. package/CLAUDE.md +3 -2
  2. package/README.md +19 -2
  3. package/dist/src/cli/commands/discrepancies.d.ts +89 -0
  4. package/dist/src/cli/commands/discrepancies.d.ts.map +1 -0
  5. package/dist/src/cli/commands/discrepancies.js +385 -0
  6. package/dist/src/cli/commands/discrepancies.js.map +1 -0
  7. package/dist/src/cli/commands/notifications.d.ts +70 -0
  8. package/dist/src/cli/commands/notifications.d.ts.map +1 -0
  9. package/dist/src/cli/commands/notifications.js +236 -0
  10. package/dist/src/cli/commands/notifications.js.map +1 -0
  11. package/dist/src/cli/commands/sync-logs.d.ts +54 -0
  12. package/dist/src/cli/commands/sync-logs.d.ts.map +1 -0
  13. package/dist/src/cli/commands/sync-logs.js +240 -0
  14. package/dist/src/cli/commands/sync-logs.js.map +1 -0
  15. package/dist/src/cli/commands/sync-monitor.d.ts +42 -0
  16. package/dist/src/cli/commands/sync-monitor.d.ts.map +1 -0
  17. package/dist/src/cli/commands/sync-monitor.js +191 -0
  18. package/dist/src/cli/commands/sync-monitor.js.map +1 -0
  19. package/dist/src/cli/helpers/init/brownfield-analysis.d.ts +45 -0
  20. package/dist/src/cli/helpers/init/brownfield-analysis.d.ts.map +1 -0
  21. package/dist/src/cli/helpers/init/brownfield-analysis.js +431 -0
  22. package/dist/src/cli/helpers/init/brownfield-analysis.js.map +1 -0
  23. package/dist/src/cli/helpers/init/index.d.ts +1 -0
  24. package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
  25. package/dist/src/cli/helpers/init/index.js +2 -0
  26. package/dist/src/cli/helpers/init/index.js.map +1 -1
  27. package/dist/src/cli/workers/brownfield-worker.d.ts +66 -0
  28. package/dist/src/cli/workers/brownfield-worker.d.ts.map +1 -0
  29. package/dist/src/cli/workers/brownfield-worker.js +417 -0
  30. package/dist/src/cli/workers/brownfield-worker.js.map +1 -0
  31. package/dist/src/core/background/brownfield-launcher.d.ts +86 -0
  32. package/dist/src/core/background/brownfield-launcher.d.ts.map +1 -0
  33. package/dist/src/core/background/brownfield-launcher.js +295 -0
  34. package/dist/src/core/background/brownfield-launcher.js.map +1 -0
  35. package/dist/src/core/background/index.d.ts +2 -0
  36. package/dist/src/core/background/index.d.ts.map +1 -1
  37. package/dist/src/core/background/index.js +2 -0
  38. package/dist/src/core/background/index.js.map +1 -1
  39. package/dist/src/core/background/types.d.ts +23 -2
  40. package/dist/src/core/background/types.d.ts.map +1 -1
  41. package/dist/src/core/config/index.d.ts +1 -0
  42. package/dist/src/core/config/index.d.ts.map +1 -1
  43. package/dist/src/core/config/index.js +1 -0
  44. package/dist/src/core/config/index.js.map +1 -1
  45. package/dist/src/core/config/types.d.ts +6 -0
  46. package/dist/src/core/config/types.d.ts.map +1 -1
  47. package/dist/src/core/config/types.js.map +1 -1
  48. package/dist/src/core/dashboard/dashboard-data.d.ts +156 -0
  49. package/dist/src/core/dashboard/dashboard-data.d.ts.map +1 -0
  50. package/dist/src/core/dashboard/dashboard-data.js +191 -0
  51. package/dist/src/core/dashboard/dashboard-data.js.map +1 -0
  52. package/dist/src/core/dashboard/index.d.ts +9 -0
  53. package/dist/src/core/dashboard/index.d.ts.map +1 -0
  54. package/dist/src/core/dashboard/index.js +9 -0
  55. package/dist/src/core/dashboard/index.js.map +1 -0
  56. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts +77 -0
  57. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts.map +1 -0
  58. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js +286 -0
  59. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js.map +1 -0
  60. package/dist/src/core/discrepancy/analyzers/index.d.ts +8 -0
  61. package/dist/src/core/discrepancy/analyzers/index.d.ts.map +1 -0
  62. package/dist/src/core/discrepancy/analyzers/index.js +8 -0
  63. package/dist/src/core/discrepancy/analyzers/index.js.map +1 -0
  64. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts +96 -0
  65. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts.map +1 -0
  66. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js +247 -0
  67. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js.map +1 -0
  68. package/dist/src/core/discrepancy/brownfield-manager.d.ts +88 -0
  69. package/dist/src/core/discrepancy/brownfield-manager.d.ts.map +1 -0
  70. package/dist/src/core/discrepancy/brownfield-manager.js +520 -0
  71. package/dist/src/core/discrepancy/brownfield-manager.js.map +1 -0
  72. package/dist/src/core/discrepancy/brownfield-types.d.ts +174 -0
  73. package/dist/src/core/discrepancy/brownfield-types.d.ts.map +1 -0
  74. package/dist/src/core/discrepancy/brownfield-types.js +11 -0
  75. package/dist/src/core/discrepancy/brownfield-types.js.map +1 -0
  76. package/dist/src/core/discrepancy/detector.d.ts +92 -0
  77. package/dist/src/core/discrepancy/detector.d.ts.map +1 -0
  78. package/dist/src/core/discrepancy/detector.js +346 -0
  79. package/dist/src/core/discrepancy/detector.js.map +1 -0
  80. package/dist/src/core/discrepancy/increment-generator.d.ts +51 -0
  81. package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -0
  82. package/dist/src/core/discrepancy/increment-generator.js +234 -0
  83. package/dist/src/core/discrepancy/increment-generator.js.map +1 -0
  84. package/dist/src/core/discrepancy/index.d.ts +18 -0
  85. package/dist/src/core/discrepancy/index.d.ts.map +1 -0
  86. package/dist/src/core/discrepancy/index.js +24 -0
  87. package/dist/src/core/discrepancy/index.js.map +1 -0
  88. package/dist/src/core/discrepancy/severity-classifier.d.ts +81 -0
  89. package/dist/src/core/discrepancy/severity-classifier.d.ts.map +1 -0
  90. package/dist/src/core/discrepancy/severity-classifier.js +289 -0
  91. package/dist/src/core/discrepancy/severity-classifier.js.map +1 -0
  92. package/dist/src/core/discrepancy/spec-parser.d.ts +74 -0
  93. package/dist/src/core/discrepancy/spec-parser.d.ts.map +1 -0
  94. package/dist/src/core/discrepancy/spec-parser.js +213 -0
  95. package/dist/src/core/discrepancy/spec-parser.js.map +1 -0
  96. package/dist/src/core/discrepancy/update-recommender.d.ts +77 -0
  97. package/dist/src/core/discrepancy/update-recommender.d.ts.map +1 -0
  98. package/dist/src/core/discrepancy/update-recommender.js +323 -0
  99. package/dist/src/core/discrepancy/update-recommender.js.map +1 -0
  100. package/dist/src/core/living-docs/living-docs-sync.d.ts +13 -16
  101. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  102. package/dist/src/core/living-docs/living-docs-sync.js +31 -112
  103. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  104. package/dist/src/core/logs/index.d.ts +10 -0
  105. package/dist/src/core/logs/index.d.ts.map +1 -0
  106. package/dist/src/core/logs/index.js +10 -0
  107. package/dist/src/core/logs/index.js.map +1 -0
  108. package/dist/src/core/logs/log-aggregator.d.ts +130 -0
  109. package/dist/src/core/logs/log-aggregator.d.ts.map +1 -0
  110. package/dist/src/core/logs/log-aggregator.js +206 -0
  111. package/dist/src/core/logs/log-aggregator.js.map +1 -0
  112. package/dist/src/core/logs/log-exporter.d.ts +81 -0
  113. package/dist/src/core/logs/log-exporter.d.ts.map +1 -0
  114. package/dist/src/core/logs/log-exporter.js +141 -0
  115. package/dist/src/core/logs/log-exporter.js.map +1 -0
  116. package/dist/src/core/notifications/command-integration.d.ts +82 -0
  117. package/dist/src/core/notifications/command-integration.d.ts.map +1 -0
  118. package/dist/src/core/notifications/command-integration.js +80 -0
  119. package/dist/src/core/notifications/command-integration.js.map +1 -0
  120. package/dist/src/core/notifications/index.d.ts +12 -0
  121. package/dist/src/core/notifications/index.d.ts.map +1 -0
  122. package/dist/src/core/notifications/index.js +12 -0
  123. package/dist/src/core/notifications/index.js.map +1 -0
  124. package/dist/src/core/notifications/notification-display.d.ts +70 -0
  125. package/dist/src/core/notifications/notification-display.d.ts.map +1 -0
  126. package/dist/src/core/notifications/notification-display.js +177 -0
  127. package/dist/src/core/notifications/notification-display.js.map +1 -0
  128. package/dist/src/core/notifications/notification-manager.d.ts +126 -0
  129. package/dist/src/core/notifications/notification-manager.d.ts.map +1 -0
  130. package/dist/src/core/notifications/notification-manager.js +287 -0
  131. package/dist/src/core/notifications/notification-manager.js.map +1 -0
  132. package/dist/src/core/notifications/notification-types.d.ts +159 -0
  133. package/dist/src/core/notifications/notification-types.d.ts.map +1 -0
  134. package/dist/src/core/notifications/notification-types.js +93 -0
  135. package/dist/src/core/notifications/notification-types.js.map +1 -0
  136. package/dist/src/core/scheduler/index.d.ts +11 -0
  137. package/dist/src/core/scheduler/index.d.ts.map +1 -0
  138. package/dist/src/core/scheduler/index.js +11 -0
  139. package/dist/src/core/scheduler/index.js.map +1 -0
  140. package/dist/src/core/scheduler/job-scheduler.d.ts +179 -0
  141. package/dist/src/core/scheduler/job-scheduler.d.ts.map +1 -0
  142. package/dist/src/core/scheduler/job-scheduler.js +282 -0
  143. package/dist/src/core/scheduler/job-scheduler.js.map +1 -0
  144. package/dist/src/core/scheduler/schedule-persistence.d.ts +83 -0
  145. package/dist/src/core/scheduler/schedule-persistence.d.ts.map +1 -0
  146. package/dist/src/core/scheduler/schedule-persistence.js +180 -0
  147. package/dist/src/core/scheduler/schedule-persistence.js.map +1 -0
  148. package/dist/src/core/scheduler/scheduled-job.d.ts +188 -0
  149. package/dist/src/core/scheduler/scheduled-job.d.ts.map +1 -0
  150. package/dist/src/core/scheduler/scheduled-job.js +182 -0
  151. package/dist/src/core/scheduler/scheduled-job.js.map +1 -0
  152. package/dist/src/core/sync/permission-enforcer.d.ts +206 -0
  153. package/dist/src/core/sync/permission-enforcer.d.ts.map +1 -0
  154. package/dist/src/core/sync/permission-enforcer.js +268 -0
  155. package/dist/src/core/sync/permission-enforcer.js.map +1 -0
  156. package/dist/src/core/sync/sync-audit-logger.d.ts +217 -0
  157. package/dist/src/core/sync/sync-audit-logger.d.ts.map +1 -0
  158. package/dist/src/core/sync/sync-audit-logger.js +327 -0
  159. package/dist/src/core/sync/sync-audit-logger.js.map +1 -0
  160. package/dist/src/core/sync/sync-interceptor.d.ts +190 -0
  161. package/dist/src/core/sync/sync-interceptor.d.ts.map +1 -0
  162. package/dist/src/core/sync/sync-interceptor.js +224 -0
  163. package/dist/src/core/sync/sync-interceptor.js.map +1 -0
  164. package/dist/src/core/types/increment-metadata.d.ts +5 -2
  165. package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
  166. package/dist/src/core/types/sync-config.d.ts +267 -0
  167. package/dist/src/core/types/sync-config.d.ts.map +1 -0
  168. package/dist/src/core/types/sync-config.js +304 -0
  169. package/dist/src/core/types/sync-config.js.map +1 -0
  170. package/dist/src/hooks/index.d.ts +11 -0
  171. package/dist/src/hooks/index.d.ts.map +1 -0
  172. package/dist/src/hooks/index.js +11 -0
  173. package/dist/src/hooks/index.js.map +1 -0
  174. package/dist/src/hooks/platform.d.ts +125 -0
  175. package/dist/src/hooks/platform.d.ts.map +1 -0
  176. package/dist/src/hooks/platform.js +325 -0
  177. package/dist/src/hooks/platform.js.map +1 -0
  178. package/dist/src/hooks/processor.d.ts +20 -0
  179. package/dist/src/hooks/processor.d.ts.map +1 -0
  180. package/dist/src/hooks/processor.js +317 -0
  181. package/dist/src/hooks/processor.js.map +1 -0
  182. package/dist/src/hooks/scheduler-startup.d.ts +19 -0
  183. package/dist/src/hooks/scheduler-startup.d.ts.map +1 -0
  184. package/dist/src/hooks/scheduler-startup.js +92 -0
  185. package/dist/src/hooks/scheduler-startup.js.map +1 -0
  186. package/dist/src/hooks/session-start.d.ts +16 -0
  187. package/dist/src/hooks/session-start.d.ts.map +1 -0
  188. package/dist/src/hooks/session-start.js +92 -0
  189. package/dist/src/hooks/session-start.js.map +1 -0
  190. package/dist/src/importers/duplicate-detector.d.ts +13 -2
  191. package/dist/src/importers/duplicate-detector.d.ts.map +1 -1
  192. package/dist/src/importers/duplicate-detector.js +21 -2
  193. package/dist/src/importers/duplicate-detector.js.map +1 -1
  194. package/dist/src/importers/item-converter.d.ts +41 -2
  195. package/dist/src/importers/item-converter.d.ts.map +1 -1
  196. package/dist/src/importers/item-converter.js +225 -38
  197. package/dist/src/importers/item-converter.js.map +1 -1
  198. package/dist/src/living-docs/fs-id-allocator.d.ts +7 -0
  199. package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
  200. package/dist/src/living-docs/fs-id-allocator.js +30 -4
  201. package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
  202. package/dist/src/sync/ado-sync-wrapper.d.ts +137 -0
  203. package/dist/src/sync/ado-sync-wrapper.d.ts.map +1 -0
  204. package/dist/src/sync/ado-sync-wrapper.js +148 -0
  205. package/dist/src/sync/ado-sync-wrapper.js.map +1 -0
  206. package/dist/src/sync/github-sync-wrapper.d.ts +195 -0
  207. package/dist/src/sync/github-sync-wrapper.d.ts.map +1 -0
  208. package/dist/src/sync/github-sync-wrapper.js +220 -0
  209. package/dist/src/sync/github-sync-wrapper.js.map +1 -0
  210. package/dist/src/sync/jira-sync-wrapper.d.ts +155 -0
  211. package/dist/src/sync/jira-sync-wrapper.d.ts.map +1 -0
  212. package/dist/src/sync/jira-sync-wrapper.js +175 -0
  213. package/dist/src/sync/jira-sync-wrapper.js.map +1 -0
  214. package/dist/src/utils/feature-id-derivation.d.ts +58 -0
  215. package/dist/src/utils/feature-id-derivation.d.ts.map +1 -0
  216. package/dist/src/utils/feature-id-derivation.js +77 -0
  217. package/dist/src/utils/feature-id-derivation.js.map +1 -0
  218. package/package.json +1 -1
  219. package/plugins/specweave/commands/specweave-discrepancies.md +141 -0
  220. package/plugins/specweave/commands/specweave-discrepancy-to-increment.md +160 -0
  221. package/plugins/specweave/commands/specweave-jobs.md +45 -2
  222. package/plugins/specweave/commands/specweave-notifications.md +92 -0
  223. package/plugins/specweave/commands/specweave-sync-logs.md +131 -0
  224. package/plugins/specweave/commands/specweave-sync-monitor.md +57 -0
  225. package/plugins/specweave/hooks/hooks.json +3 -3
  226. package/plugins/specweave/hooks/lib/scheduler-startup.sh +72 -0
  227. package/plugins/specweave/hooks/universal/dispatcher.mjs +246 -0
  228. package/plugins/specweave/hooks/universal/session-start.cmd +16 -0
  229. package/plugins/specweave/hooks/universal/session-start.ps1 +16 -0
  230. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +14 -5
  231. package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +5 -2
  232. package/plugins/specweave/skills/discrepancy-viewer.md +154 -0
  233. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +34 -0
  234. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +51 -0
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Sync Audit Logger
3
+ *
4
+ * Logs all sync operations for compliance and debugging.
5
+ * Uses JSONL format for efficient appending and querying.
6
+ *
7
+ * Features:
8
+ * - JSONL format (one JSON object per line)
9
+ * - Log rotation (new file when > 100MB or new day)
10
+ * - Configurable retention
11
+ *
12
+ * @module core/sync/sync-audit-logger
13
+ */
14
+ import { SyncPlatform } from '../types/sync-config.js';
15
+ import { SyncOperation } from './permission-enforcer.js';
16
+ import { Logger } from '../../utils/logger.js';
17
+ /**
18
+ * Audit log entry - single sync operation record
19
+ */
20
+ export interface AuditLogEntry {
21
+ /**
22
+ * ISO timestamp of the operation
23
+ */
24
+ timestamp: string;
25
+ /**
26
+ * Target platform
27
+ */
28
+ platform: SyncPlatform;
29
+ /**
30
+ * Operation type
31
+ */
32
+ operation: SyncOperation;
33
+ /**
34
+ * Item ID being operated on
35
+ */
36
+ itemId: string;
37
+ /**
38
+ * Operation result
39
+ */
40
+ result: 'success' | 'denied' | 'error';
41
+ /**
42
+ * Reason for denial (if denied)
43
+ */
44
+ reason?: string;
45
+ /**
46
+ * Error message (if error)
47
+ */
48
+ error?: string;
49
+ /**
50
+ * Duration of the operation in milliseconds
51
+ */
52
+ durationMs?: number;
53
+ /**
54
+ * Additional context
55
+ */
56
+ context?: Record<string, unknown>;
57
+ }
58
+ /**
59
+ * Audit logger options
60
+ */
61
+ export interface SyncAuditLoggerOptions {
62
+ /**
63
+ * Path to .specweave directory
64
+ */
65
+ specweavePath?: string;
66
+ /**
67
+ * Logger instance
68
+ */
69
+ logger?: Logger;
70
+ /**
71
+ * Max file size in bytes before rotation
72
+ * @default 104857600 (100MB)
73
+ */
74
+ maxFileSizeBytes?: number;
75
+ /**
76
+ * Retention period in days
77
+ * @default 30
78
+ */
79
+ retentionDays?: number;
80
+ /**
81
+ * Enable logging (can be disabled for testing)
82
+ * @default true
83
+ */
84
+ enabled?: boolean;
85
+ }
86
+ /**
87
+ * SyncAuditLogger - Comprehensive audit logging for sync operations
88
+ *
89
+ * All sync attempts are logged including:
90
+ * - Successful operations
91
+ * - Permission denials
92
+ * - Errors during execution
93
+ *
94
+ * Logs are stored in JSONL format for easy parsing:
95
+ * `.specweave/logs/sync/audit-YYYY-MM-DD.jsonl`
96
+ *
97
+ * Usage:
98
+ * ```typescript
99
+ * const logger = new SyncAuditLogger({ specweavePath });
100
+ *
101
+ * await logger.logSuccess('github', 'upsert-internal', 'FS-001', 150);
102
+ * await logger.logDenied('jira', 'upsert-external', 'EXT-123', 'External updates disabled');
103
+ * await logger.logError('ado', 'update-status', 'US-456', new Error('Network timeout'));
104
+ * ```
105
+ */
106
+ export declare class SyncAuditLogger {
107
+ private readonly logDir;
108
+ private readonly logger;
109
+ private readonly maxFileSizeBytes;
110
+ private readonly retentionDays;
111
+ private readonly enabled;
112
+ private currentDate;
113
+ private currentFilePath;
114
+ constructor(options?: SyncAuditLoggerOptions);
115
+ /**
116
+ * Log a successful sync operation
117
+ *
118
+ * @param platform - Target platform
119
+ * @param operation - Operation type
120
+ * @param itemId - Item ID
121
+ * @param durationMs - Operation duration in milliseconds
122
+ * @param context - Optional additional context
123
+ */
124
+ logSuccess(platform: SyncPlatform, operation: SyncOperation, itemId: string, durationMs?: number, context?: Record<string, unknown>): Promise<void>;
125
+ /**
126
+ * Log a denied sync operation
127
+ *
128
+ * @param platform - Target platform
129
+ * @param operation - Operation type
130
+ * @param itemId - Item ID
131
+ * @param reason - Denial reason
132
+ * @param context - Optional additional context
133
+ */
134
+ logDenied(platform: SyncPlatform, operation: SyncOperation, itemId: string, reason: string, context?: Record<string, unknown>): Promise<void>;
135
+ /**
136
+ * Log an error during sync operation
137
+ *
138
+ * @param platform - Target platform
139
+ * @param operation - Operation type
140
+ * @param itemId - Item ID
141
+ * @param error - Error that occurred
142
+ * @param context - Optional additional context
143
+ */
144
+ logError(platform: SyncPlatform, operation: SyncOperation, itemId: string, error: Error, context?: Record<string, unknown>): Promise<void>;
145
+ /**
146
+ * Get log file path for a specific date
147
+ *
148
+ * @param date - Date to get log path for (defaults to today)
149
+ */
150
+ getLogPath(date?: Date): string;
151
+ /**
152
+ * Get all log files in the log directory
153
+ *
154
+ * @returns Array of log file paths sorted by date (newest first)
155
+ */
156
+ getLogFiles(): Promise<string[]>;
157
+ /**
158
+ * Read log entries from a file
159
+ *
160
+ * @param filePath - Path to log file
161
+ * @param limit - Maximum entries to return
162
+ * @param filter - Optional filter function
163
+ */
164
+ readEntries(filePath: string, limit?: number, filter?: (entry: AuditLogEntry) => boolean): Promise<AuditLogEntry[]>;
165
+ /**
166
+ * Get recent log entries across all log files
167
+ *
168
+ * @param limit - Maximum entries to return
169
+ * @param filter - Optional filter function
170
+ */
171
+ getRecentEntries(limit?: number, filter?: (entry: AuditLogEntry) => boolean): Promise<AuditLogEntry[]>;
172
+ /**
173
+ * Get entries for a specific platform
174
+ *
175
+ * @param platform - Platform to filter by
176
+ * @param limit - Maximum entries
177
+ */
178
+ getEntriesForPlatform(platform: SyncPlatform, limit?: number): Promise<AuditLogEntry[]>;
179
+ /**
180
+ * Get all denied entries (for monitoring)
181
+ *
182
+ * @param limit - Maximum entries
183
+ */
184
+ getDeniedEntries(limit?: number): Promise<AuditLogEntry[]>;
185
+ /**
186
+ * Get all error entries (for debugging)
187
+ *
188
+ * @param limit - Maximum entries
189
+ */
190
+ getErrorEntries(limit?: number): Promise<AuditLogEntry[]>;
191
+ /**
192
+ * Get statistics for a time period
193
+ *
194
+ * @param since - Start date (defaults to 24 hours ago)
195
+ */
196
+ getStats(since?: Date): Promise<{
197
+ total: number;
198
+ success: number;
199
+ denied: number;
200
+ errors: number;
201
+ byPlatform: Record<SyncPlatform, number>;
202
+ avgDurationMs: number;
203
+ }>;
204
+ /**
205
+ * Clean up old log files based on retention policy
206
+ */
207
+ cleanup(): Promise<number>;
208
+ /**
209
+ * Write an entry to the log file
210
+ */
211
+ private log;
212
+ /**
213
+ * Get current file path, rotating if needed
214
+ */
215
+ private getOrRotateFilePath;
216
+ }
217
+ //# sourceMappingURL=sync-audit-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-audit-logger.d.ts","sourceRoot":"","sources":["../../../../src/core/sync/sync-audit-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,327 @@
1
+ /**
2
+ * Sync Audit Logger
3
+ *
4
+ * Logs all sync operations for compliance and debugging.
5
+ * Uses JSONL format for efficient appending and querying.
6
+ *
7
+ * Features:
8
+ * - JSONL format (one JSON object per line)
9
+ * - Log rotation (new file when > 100MB or new day)
10
+ * - Configurable retention
11
+ *
12
+ * @module core/sync/sync-audit-logger
13
+ */
14
+ import { promises as fs } from 'fs';
15
+ import path from 'path';
16
+ import { consoleLogger } from '../../utils/logger.js';
17
+ /**
18
+ * SyncAuditLogger - Comprehensive audit logging for sync operations
19
+ *
20
+ * All sync attempts are logged including:
21
+ * - Successful operations
22
+ * - Permission denials
23
+ * - Errors during execution
24
+ *
25
+ * Logs are stored in JSONL format for easy parsing:
26
+ * `.specweave/logs/sync/audit-YYYY-MM-DD.jsonl`
27
+ *
28
+ * Usage:
29
+ * ```typescript
30
+ * const logger = new SyncAuditLogger({ specweavePath });
31
+ *
32
+ * await logger.logSuccess('github', 'upsert-internal', 'FS-001', 150);
33
+ * await logger.logDenied('jira', 'upsert-external', 'EXT-123', 'External updates disabled');
34
+ * await logger.logError('ado', 'update-status', 'US-456', new Error('Network timeout'));
35
+ * ```
36
+ */
37
+ export class SyncAuditLogger {
38
+ constructor(options = {}) {
39
+ // Cache current date to detect day changes
40
+ this.currentDate = '';
41
+ this.currentFilePath = '';
42
+ const specweavePath = options.specweavePath ?? path.join(process.cwd(), '.specweave');
43
+ this.logDir = path.join(specweavePath, 'logs', 'sync');
44
+ this.logger = options.logger ?? consoleLogger;
45
+ this.maxFileSizeBytes = options.maxFileSizeBytes ?? 100 * 1024 * 1024; // 100MB
46
+ this.retentionDays = options.retentionDays ?? 30;
47
+ this.enabled = options.enabled ?? true;
48
+ }
49
+ /**
50
+ * Log a successful sync operation
51
+ *
52
+ * @param platform - Target platform
53
+ * @param operation - Operation type
54
+ * @param itemId - Item ID
55
+ * @param durationMs - Operation duration in milliseconds
56
+ * @param context - Optional additional context
57
+ */
58
+ async logSuccess(platform, operation, itemId, durationMs, context) {
59
+ await this.log({
60
+ timestamp: new Date().toISOString(),
61
+ platform,
62
+ operation,
63
+ itemId,
64
+ result: 'success',
65
+ durationMs,
66
+ context,
67
+ });
68
+ }
69
+ /**
70
+ * Log a denied sync operation
71
+ *
72
+ * @param platform - Target platform
73
+ * @param operation - Operation type
74
+ * @param itemId - Item ID
75
+ * @param reason - Denial reason
76
+ * @param context - Optional additional context
77
+ */
78
+ async logDenied(platform, operation, itemId, reason, context) {
79
+ await this.log({
80
+ timestamp: new Date().toISOString(),
81
+ platform,
82
+ operation,
83
+ itemId,
84
+ result: 'denied',
85
+ reason,
86
+ context,
87
+ });
88
+ }
89
+ /**
90
+ * Log an error during sync operation
91
+ *
92
+ * @param platform - Target platform
93
+ * @param operation - Operation type
94
+ * @param itemId - Item ID
95
+ * @param error - Error that occurred
96
+ * @param context - Optional additional context
97
+ */
98
+ async logError(platform, operation, itemId, error, context) {
99
+ await this.log({
100
+ timestamp: new Date().toISOString(),
101
+ platform,
102
+ operation,
103
+ itemId,
104
+ result: 'error',
105
+ error: error.message,
106
+ context: {
107
+ ...context,
108
+ stack: error.stack,
109
+ },
110
+ });
111
+ }
112
+ /**
113
+ * Get log file path for a specific date
114
+ *
115
+ * @param date - Date to get log path for (defaults to today)
116
+ */
117
+ getLogPath(date) {
118
+ const d = date ?? new Date();
119
+ const dateStr = d.toISOString().split('T')[0]; // YYYY-MM-DD
120
+ return path.join(this.logDir, `audit-${dateStr}.jsonl`);
121
+ }
122
+ /**
123
+ * Get all log files in the log directory
124
+ *
125
+ * @returns Array of log file paths sorted by date (newest first)
126
+ */
127
+ async getLogFiles() {
128
+ try {
129
+ const files = await fs.readdir(this.logDir);
130
+ return files
131
+ .filter((f) => f.startsWith('audit-') && f.endsWith('.jsonl'))
132
+ .map((f) => path.join(this.logDir, f))
133
+ .sort()
134
+ .reverse();
135
+ }
136
+ catch {
137
+ return [];
138
+ }
139
+ }
140
+ /**
141
+ * Read log entries from a file
142
+ *
143
+ * @param filePath - Path to log file
144
+ * @param limit - Maximum entries to return
145
+ * @param filter - Optional filter function
146
+ */
147
+ async readEntries(filePath, limit, filter) {
148
+ try {
149
+ const content = await fs.readFile(filePath, 'utf-8');
150
+ const lines = content.trim().split('\n').filter(Boolean);
151
+ let entries = lines.map((line) => JSON.parse(line));
152
+ if (filter) {
153
+ entries = entries.filter(filter);
154
+ }
155
+ if (limit) {
156
+ entries = entries.slice(-limit); // Last N entries
157
+ }
158
+ return entries;
159
+ }
160
+ catch {
161
+ return [];
162
+ }
163
+ }
164
+ /**
165
+ * Get recent log entries across all log files
166
+ *
167
+ * @param limit - Maximum entries to return
168
+ * @param filter - Optional filter function
169
+ */
170
+ async getRecentEntries(limit = 100, filter) {
171
+ const files = await this.getLogFiles();
172
+ const entries = [];
173
+ for (const file of files) {
174
+ const fileEntries = await this.readEntries(file, undefined, filter);
175
+ entries.push(...fileEntries);
176
+ if (entries.length >= limit) {
177
+ break;
178
+ }
179
+ }
180
+ return entries.slice(-limit);
181
+ }
182
+ /**
183
+ * Get entries for a specific platform
184
+ *
185
+ * @param platform - Platform to filter by
186
+ * @param limit - Maximum entries
187
+ */
188
+ async getEntriesForPlatform(platform, limit = 50) {
189
+ return this.getRecentEntries(limit, (e) => e.platform === platform);
190
+ }
191
+ /**
192
+ * Get all denied entries (for monitoring)
193
+ *
194
+ * @param limit - Maximum entries
195
+ */
196
+ async getDeniedEntries(limit = 50) {
197
+ return this.getRecentEntries(limit, (e) => e.result === 'denied');
198
+ }
199
+ /**
200
+ * Get all error entries (for debugging)
201
+ *
202
+ * @param limit - Maximum entries
203
+ */
204
+ async getErrorEntries(limit = 50) {
205
+ return this.getRecentEntries(limit, (e) => e.result === 'error');
206
+ }
207
+ /**
208
+ * Get statistics for a time period
209
+ *
210
+ * @param since - Start date (defaults to 24 hours ago)
211
+ */
212
+ async getStats(since) {
213
+ const sinceDate = since ?? new Date(Date.now() - 24 * 60 * 60 * 1000);
214
+ const sinceStr = sinceDate.toISOString();
215
+ const entries = await this.getRecentEntries(10000, (e) => e.timestamp >= sinceStr);
216
+ const stats = {
217
+ total: entries.length,
218
+ success: 0,
219
+ denied: 0,
220
+ errors: 0,
221
+ byPlatform: { github: 0, jira: 0, ado: 0 },
222
+ avgDurationMs: 0,
223
+ };
224
+ let totalDuration = 0;
225
+ let durationCount = 0;
226
+ for (const entry of entries) {
227
+ if (entry.result === 'success')
228
+ stats.success++;
229
+ else if (entry.result === 'denied')
230
+ stats.denied++;
231
+ else if (entry.result === 'error')
232
+ stats.errors++;
233
+ stats.byPlatform[entry.platform]++;
234
+ if (entry.durationMs) {
235
+ totalDuration += entry.durationMs;
236
+ durationCount++;
237
+ }
238
+ }
239
+ stats.avgDurationMs = durationCount > 0 ? Math.round(totalDuration / durationCount) : 0;
240
+ return stats;
241
+ }
242
+ /**
243
+ * Clean up old log files based on retention policy
244
+ */
245
+ async cleanup() {
246
+ const cutoffDate = new Date();
247
+ cutoffDate.setDate(cutoffDate.getDate() - this.retentionDays);
248
+ const cutoffStr = cutoffDate.toISOString().split('T')[0];
249
+ const files = await this.getLogFiles();
250
+ let deletedCount = 0;
251
+ for (const file of files) {
252
+ // Extract date from filename: audit-YYYY-MM-DD.jsonl
253
+ const match = path.basename(file).match(/audit-(\d{4}-\d{2}-\d{2})\.jsonl/);
254
+ if (match && match[1] < cutoffStr) {
255
+ try {
256
+ await fs.unlink(file);
257
+ deletedCount++;
258
+ this.logger.debug(`Deleted old audit log: ${path.basename(file)}`);
259
+ }
260
+ catch (error) {
261
+ this.logger.debug(`Failed to delete audit log: ${file}`);
262
+ }
263
+ }
264
+ }
265
+ return deletedCount;
266
+ }
267
+ /**
268
+ * Write an entry to the log file
269
+ */
270
+ async log(entry) {
271
+ if (!this.enabled) {
272
+ return;
273
+ }
274
+ try {
275
+ // Ensure directory exists
276
+ await fs.mkdir(this.logDir, { recursive: true });
277
+ // Get current file path (may rotate on new day)
278
+ const filePath = await this.getOrRotateFilePath();
279
+ // Append entry as JSONL
280
+ const line = JSON.stringify(entry) + '\n';
281
+ await fs.appendFile(filePath, line, 'utf-8');
282
+ }
283
+ catch (error) {
284
+ // Don't fail the sync operation if logging fails
285
+ this.logger.debug(`Failed to write audit log: ${error}`);
286
+ }
287
+ }
288
+ /**
289
+ * Get current file path, rotating if needed
290
+ */
291
+ async getOrRotateFilePath() {
292
+ const today = new Date().toISOString().split('T')[0];
293
+ // Check if we need a new file (new day)
294
+ if (today !== this.currentDate) {
295
+ this.currentDate = today;
296
+ this.currentFilePath = this.getLogPath();
297
+ }
298
+ // Check file size for rotation
299
+ if (this.currentFilePath) {
300
+ try {
301
+ const stats = await fs.stat(this.currentFilePath);
302
+ if (stats.size >= this.maxFileSizeBytes) {
303
+ // Rotate: add sequence number
304
+ const basePath = this.currentFilePath.replace('.jsonl', '');
305
+ let seq = 1;
306
+ while (true) {
307
+ const rotatedPath = `${basePath}-${seq}.jsonl`;
308
+ try {
309
+ await fs.access(rotatedPath);
310
+ seq++;
311
+ }
312
+ catch {
313
+ // File doesn't exist, use this name
314
+ this.currentFilePath = rotatedPath;
315
+ break;
316
+ }
317
+ }
318
+ }
319
+ }
320
+ catch {
321
+ // File doesn't exist yet, that's fine
322
+ }
323
+ }
324
+ return this.currentFilePath;
325
+ }
326
+ }
327
+ //# sourceMappingURL=sync-audit-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-audit-logger.js","sourceRoot":"","sources":["../../../../src/core/sync/sync-audit-logger.ts"],"names":[],"mappings":"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"}