@pax8-cta/core 0.1.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 (226) hide show
  1. package/LICENSE +198 -0
  2. package/dist/auth/device-code-login.d.ts +40 -0
  3. package/dist/auth/device-code-login.d.ts.map +1 -0
  4. package/dist/auth/device-code-login.js +59 -0
  5. package/dist/auth/device-code-login.js.map +1 -0
  6. package/dist/auth/gdap-client.d.ts +81 -0
  7. package/dist/auth/gdap-client.d.ts.map +1 -0
  8. package/dist/auth/gdap-client.js +128 -0
  9. package/dist/auth/gdap-client.js.map +1 -0
  10. package/dist/auth/index.d.ts +19 -0
  11. package/dist/auth/index.d.ts.map +1 -0
  12. package/dist/auth/index.js +19 -0
  13. package/dist/auth/index.js.map +1 -0
  14. package/dist/auth/token-manager.d.ts +54 -0
  15. package/dist/auth/token-manager.d.ts.map +1 -0
  16. package/dist/auth/token-manager.js +150 -0
  17. package/dist/auth/token-manager.js.map +1 -0
  18. package/dist/client.d.ts +27 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +27 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/config/client.d.ts +24 -0
  23. package/dist/config/client.d.ts.map +1 -0
  24. package/dist/config/client.js +18 -0
  25. package/dist/config/client.js.map +1 -0
  26. package/dist/config/index.d.ts +18 -0
  27. package/dist/config/index.d.ts.map +1 -0
  28. package/dist/config/index.js +18 -0
  29. package/dist/config/index.js.map +1 -0
  30. package/dist/config/loader.d.ts +81 -0
  31. package/dist/config/loader.d.ts.map +1 -0
  32. package/dist/config/loader.js +271 -0
  33. package/dist/config/loader.js.map +1 -0
  34. package/dist/config/schema.d.ts +751 -0
  35. package/dist/config/schema.d.ts.map +1 -0
  36. package/dist/config/schema.js +556 -0
  37. package/dist/config/schema.js.map +1 -0
  38. package/dist/constants.d.ts +116 -0
  39. package/dist/constants.d.ts.map +1 -0
  40. package/dist/constants.js +170 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/dataverse/agent-resolver.d.ts +98 -0
  43. package/dist/dataverse/agent-resolver.d.ts.map +1 -0
  44. package/dist/dataverse/agent-resolver.js +185 -0
  45. package/dist/dataverse/agent-resolver.js.map +1 -0
  46. package/dist/dataverse/client.d.ts +104 -0
  47. package/dist/dataverse/client.d.ts.map +1 -0
  48. package/dist/dataverse/client.js +272 -0
  49. package/dist/dataverse/client.js.map +1 -0
  50. package/dist/dataverse/connection-refs.d.ts +115 -0
  51. package/dist/dataverse/connection-refs.d.ts.map +1 -0
  52. package/dist/dataverse/connection-refs.js +203 -0
  53. package/dist/dataverse/connection-refs.js.map +1 -0
  54. package/dist/dataverse/index.d.ts +20 -0
  55. package/dist/dataverse/index.d.ts.map +1 -0
  56. package/dist/dataverse/index.js +20 -0
  57. package/dist/dataverse/index.js.map +1 -0
  58. package/dist/dataverse/solution-ops.d.ts +100 -0
  59. package/dist/dataverse/solution-ops.d.ts.map +1 -0
  60. package/dist/dataverse/solution-ops.js +288 -0
  61. package/dist/dataverse/solution-ops.js.map +1 -0
  62. package/dist/errors.d.ts +171 -0
  63. package/dist/errors.d.ts.map +1 -0
  64. package/dist/errors.js +178 -0
  65. package/dist/errors.js.map +1 -0
  66. package/dist/index.d.ts +27 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +40 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/mock/demo-data.d.ts +213 -0
  71. package/dist/mock/demo-data.d.ts.map +1 -0
  72. package/dist/mock/demo-data.js +1096 -0
  73. package/dist/mock/demo-data.js.map +1 -0
  74. package/dist/mock/demo-deployment-store.d.ts +77 -0
  75. package/dist/mock/demo-deployment-store.d.ts.map +1 -0
  76. package/dist/mock/demo-deployment-store.js +85 -0
  77. package/dist/mock/demo-deployment-store.js.map +1 -0
  78. package/dist/powerplatform/admin-client.d.ts +226 -0
  79. package/dist/powerplatform/admin-client.d.ts.map +1 -0
  80. package/dist/powerplatform/admin-client.js +315 -0
  81. package/dist/powerplatform/admin-client.js.map +1 -0
  82. package/dist/powerplatform/index.d.ts +18 -0
  83. package/dist/powerplatform/index.d.ts.map +1 -0
  84. package/dist/powerplatform/index.js +18 -0
  85. package/dist/powerplatform/index.js.map +1 -0
  86. package/dist/powerplatform/tenant-discovery.d.ts +100 -0
  87. package/dist/powerplatform/tenant-discovery.d.ts.map +1 -0
  88. package/dist/powerplatform/tenant-discovery.js +205 -0
  89. package/dist/powerplatform/tenant-discovery.js.map +1 -0
  90. package/dist/preconditions/check.d.ts +41 -0
  91. package/dist/preconditions/check.d.ts.map +1 -0
  92. package/dist/preconditions/check.js +173 -0
  93. package/dist/preconditions/check.js.map +1 -0
  94. package/dist/preconditions/index.d.ts +20 -0
  95. package/dist/preconditions/index.d.ts.map +1 -0
  96. package/dist/preconditions/index.js +20 -0
  97. package/dist/preconditions/index.js.map +1 -0
  98. package/dist/preconditions/loader.d.ts +33 -0
  99. package/dist/preconditions/loader.d.ts.map +1 -0
  100. package/dist/preconditions/loader.js +65 -0
  101. package/dist/preconditions/loader.js.map +1 -0
  102. package/dist/preconditions/schema.d.ts +103 -0
  103. package/dist/preconditions/schema.d.ts.map +1 -0
  104. package/dist/preconditions/schema.js +93 -0
  105. package/dist/preconditions/schema.js.map +1 -0
  106. package/dist/preconditions/types.d.ts +118 -0
  107. package/dist/preconditions/types.d.ts.map +1 -0
  108. package/dist/preconditions/types.js +17 -0
  109. package/dist/preconditions/types.js.map +1 -0
  110. package/dist/queue/index.d.ts +17 -0
  111. package/dist/queue/index.d.ts.map +1 -0
  112. package/dist/queue/index.js +17 -0
  113. package/dist/queue/index.js.map +1 -0
  114. package/dist/queue/memory-queue.d.ts +86 -0
  115. package/dist/queue/memory-queue.d.ts.map +1 -0
  116. package/dist/queue/memory-queue.js +221 -0
  117. package/dist/queue/memory-queue.js.map +1 -0
  118. package/dist/services/audit-log.d.ts +59 -0
  119. package/dist/services/audit-log.d.ts.map +1 -0
  120. package/dist/services/audit-log.js +193 -0
  121. package/dist/services/audit-log.js.map +1 -0
  122. package/dist/services/auth-error-parser.d.ts +36 -0
  123. package/dist/services/auth-error-parser.d.ts.map +1 -0
  124. package/dist/services/auth-error-parser.js +90 -0
  125. package/dist/services/auth-error-parser.js.map +1 -0
  126. package/dist/services/deployment-doctor.d.ts +109 -0
  127. package/dist/services/deployment-doctor.d.ts.map +1 -0
  128. package/dist/services/deployment-doctor.js +476 -0
  129. package/dist/services/deployment-doctor.js.map +1 -0
  130. package/dist/services/deployment-notifications.d.ts +41 -0
  131. package/dist/services/deployment-notifications.d.ts.map +1 -0
  132. package/dist/services/deployment-notifications.js +161 -0
  133. package/dist/services/deployment-notifications.js.map +1 -0
  134. package/dist/services/deployment-progress.d.ts +89 -0
  135. package/dist/services/deployment-progress.d.ts.map +1 -0
  136. package/dist/services/deployment-progress.js +244 -0
  137. package/dist/services/deployment-progress.js.map +1 -0
  138. package/dist/services/deployment-service.d.ts +97 -0
  139. package/dist/services/deployment-service.d.ts.map +1 -0
  140. package/dist/services/deployment-service.js +375 -0
  141. package/dist/services/deployment-service.js.map +1 -0
  142. package/dist/services/drift-analyzer.d.ts +86 -0
  143. package/dist/services/drift-analyzer.d.ts.map +1 -0
  144. package/dist/services/drift-analyzer.js +273 -0
  145. package/dist/services/drift-analyzer.js.map +1 -0
  146. package/dist/services/environment-setup.d.ts +97 -0
  147. package/dist/services/environment-setup.d.ts.map +1 -0
  148. package/dist/services/environment-setup.js +250 -0
  149. package/dist/services/environment-setup.js.map +1 -0
  150. package/dist/services/health-check.d.ts +168 -0
  151. package/dist/services/health-check.d.ts.map +1 -0
  152. package/dist/services/health-check.js +705 -0
  153. package/dist/services/health-check.js.map +1 -0
  154. package/dist/services/index.d.ts +39 -0
  155. package/dist/services/index.d.ts.map +1 -0
  156. package/dist/services/index.js +39 -0
  157. package/dist/services/index.js.map +1 -0
  158. package/dist/services/logger.d.ts +139 -0
  159. package/dist/services/logger.d.ts.map +1 -0
  160. package/dist/services/logger.js +268 -0
  161. package/dist/services/logger.js.map +1 -0
  162. package/dist/services/notification-service.d.ts +55 -0
  163. package/dist/services/notification-service.d.ts.map +1 -0
  164. package/dist/services/notification-service.js +184 -0
  165. package/dist/services/notification-service.js.map +1 -0
  166. package/dist/services/risk-analyzer.d.ts +252 -0
  167. package/dist/services/risk-analyzer.d.ts.map +1 -0
  168. package/dist/services/risk-analyzer.js +866 -0
  169. package/dist/services/risk-analyzer.js.map +1 -0
  170. package/dist/services/rollback.d.ts +57 -0
  171. package/dist/services/rollback.d.ts.map +1 -0
  172. package/dist/services/rollback.js +270 -0
  173. package/dist/services/rollback.js.map +1 -0
  174. package/dist/services/scheduler.d.ts +80 -0
  175. package/dist/services/scheduler.d.ts.map +1 -0
  176. package/dist/services/scheduler.js +350 -0
  177. package/dist/services/scheduler.js.map +1 -0
  178. package/dist/services/secrets.d.ts +31 -0
  179. package/dist/services/secrets.d.ts.map +1 -0
  180. package/dist/services/secrets.js +206 -0
  181. package/dist/services/secrets.js.map +1 -0
  182. package/dist/services/settings-service.d.ts +132 -0
  183. package/dist/services/settings-service.d.ts.map +1 -0
  184. package/dist/services/settings-service.js +378 -0
  185. package/dist/services/settings-service.js.map +1 -0
  186. package/dist/services/solution-diff.d.ts +127 -0
  187. package/dist/services/solution-diff.d.ts.map +1 -0
  188. package/dist/services/solution-diff.js +260 -0
  189. package/dist/services/solution-diff.js.map +1 -0
  190. package/dist/services/solution-mode-detector.d.ts +35 -0
  191. package/dist/services/solution-mode-detector.d.ts.map +1 -0
  192. package/dist/services/solution-mode-detector.js +84 -0
  193. package/dist/services/solution-mode-detector.js.map +1 -0
  194. package/dist/services/tenant-resolver.d.ts +55 -0
  195. package/dist/services/tenant-resolver.d.ts.map +1 -0
  196. package/dist/services/tenant-resolver.js +126 -0
  197. package/dist/services/tenant-resolver.js.map +1 -0
  198. package/dist/services/unmanaged-customizations.d.ts +104 -0
  199. package/dist/services/unmanaged-customizations.d.ts.map +1 -0
  200. package/dist/services/unmanaged-customizations.js +521 -0
  201. package/dist/services/unmanaged-customizations.js.map +1 -0
  202. package/dist/services/url-templater.d.ts +184 -0
  203. package/dist/services/url-templater.d.ts.map +1 -0
  204. package/dist/services/url-templater.js +327 -0
  205. package/dist/services/url-templater.js.map +1 -0
  206. package/dist/services/version-checker.d.ts +108 -0
  207. package/dist/services/version-checker.d.ts.map +1 -0
  208. package/dist/services/version-checker.js +403 -0
  209. package/dist/services/version-checker.js.map +1 -0
  210. package/dist/services/waves.d.ts +90 -0
  211. package/dist/services/waves.d.ts.map +1 -0
  212. package/dist/services/waves.js +222 -0
  213. package/dist/services/waves.js.map +1 -0
  214. package/dist/services/webhook.d.ts +95 -0
  215. package/dist/services/webhook.d.ts.map +1 -0
  216. package/dist/services/webhook.js +244 -0
  217. package/dist/services/webhook.js.map +1 -0
  218. package/dist/utils/deployment-tools.d.ts +110 -0
  219. package/dist/utils/deployment-tools.d.ts.map +1 -0
  220. package/dist/utils/deployment-tools.js +121 -0
  221. package/dist/utils/deployment-tools.js.map +1 -0
  222. package/dist/utils/index.d.ts +17 -0
  223. package/dist/utils/index.d.ts.map +1 -0
  224. package/dist/utils/index.js +18 -0
  225. package/dist/utils/index.js.map +1 -0
  226. package/package.json +49 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Copyright 2024 Pax8, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import crypto from "node:crypto";
17
+ import { DEFAULT_MEMORY_QUEUE_CONCURRENCY, DEFAULT_MEMORY_QUEUE_RETRIES, DEFAULT_MEMORY_QUEUE_RETRY_DELAY_MS, } from "../constants.js";
18
+ /**
19
+ * In-memory job queue for simple single-process deployments
20
+ *
21
+ * This provides a Redis-free alternative for:
22
+ * - Local development
23
+ * - Single-instance deployments
24
+ * - Serverless environments (Vercel, Netlify)
25
+ *
26
+ * Limitations:
27
+ * - Jobs are lost on restart
28
+ * - No persistence
29
+ * - No multi-process scaling
30
+ * - For production with multiple instances, use Redis
31
+ */
32
+ import { coreLogger } from "../services/logger.js";
33
+ const logger = coreLogger;
34
+ export class MemoryQueue {
35
+ name;
36
+ jobs = new Map();
37
+ queue = [];
38
+ processing = new Set();
39
+ processor;
40
+ concurrency;
41
+ maxRetries;
42
+ retryDelay;
43
+ isRunning = false;
44
+ eventListeners = new Map();
45
+ constructor(name, options = {}) {
46
+ this.name = name;
47
+ this.concurrency = options.concurrency ?? DEFAULT_MEMORY_QUEUE_CONCURRENCY;
48
+ this.maxRetries = options.maxRetries ?? DEFAULT_MEMORY_QUEUE_RETRIES;
49
+ this.retryDelay = options.retryDelay ?? DEFAULT_MEMORY_QUEUE_RETRY_DELAY_MS;
50
+ }
51
+ /**
52
+ * Add a job to the queue
53
+ */
54
+ async add(name, data) {
55
+ const job = {
56
+ id: crypto.randomUUID(),
57
+ name,
58
+ data,
59
+ status: "pending",
60
+ progress: 0,
61
+ createdAt: new Date(),
62
+ attempts: 0,
63
+ maxAttempts: this.maxRetries,
64
+ };
65
+ this.jobs.set(job.id, job);
66
+ this.queue.push(job.id);
67
+ this.emit("waiting", job);
68
+ // Process if we have capacity
69
+ this.processNext();
70
+ return job;
71
+ }
72
+ /**
73
+ * Add multiple jobs at once
74
+ */
75
+ async addBulk(jobs) {
76
+ return Promise.all(jobs.map((j) => this.add(j.name, j.data)));
77
+ }
78
+ /**
79
+ * Set the job processor
80
+ */
81
+ process(processor) {
82
+ this.processor = processor;
83
+ this.isRunning = true;
84
+ this.processNext();
85
+ }
86
+ /**
87
+ * Get a job by ID
88
+ */
89
+ getJob(id) {
90
+ return this.jobs.get(id);
91
+ }
92
+ /**
93
+ * Get all jobs with optional status filter
94
+ */
95
+ getJobs(status) {
96
+ const jobs = Array.from(this.jobs.values());
97
+ if (status) {
98
+ return jobs.filter((j) => j.status === status);
99
+ }
100
+ return jobs;
101
+ }
102
+ /**
103
+ * Get queue counts
104
+ */
105
+ getCounts() {
106
+ const jobs = Array.from(this.jobs.values());
107
+ return {
108
+ pending: jobs.filter((j) => j.status === "pending").length,
109
+ active: jobs.filter((j) => j.status === "active").length,
110
+ completed: jobs.filter((j) => j.status === "completed").length,
111
+ failed: jobs.filter((j) => j.status === "failed").length,
112
+ };
113
+ }
114
+ /**
115
+ * Update job progress
116
+ */
117
+ updateProgress(jobId, progress) {
118
+ const job = this.jobs.get(jobId);
119
+ if (job) {
120
+ job.progress = progress;
121
+ this.emit("progress", job);
122
+ }
123
+ }
124
+ /**
125
+ * Listen to queue events
126
+ */
127
+ on(event, listener) {
128
+ const listeners = this.eventListeners.get(event) ?? [];
129
+ listeners.push(listener);
130
+ this.eventListeners.set(event, listeners);
131
+ }
132
+ emit(event, job, result, error) {
133
+ const listeners = this.eventListeners.get(event) ?? [];
134
+ for (const listener of listeners) {
135
+ try {
136
+ listener(job, result, error);
137
+ }
138
+ catch (e) {
139
+ logger.error("Error in queue event listener", e instanceof Error ? e : new Error(String(e)), {
140
+ event,
141
+ jobId: job.id,
142
+ });
143
+ }
144
+ }
145
+ }
146
+ /**
147
+ * Stop processing
148
+ */
149
+ close() {
150
+ this.isRunning = false;
151
+ }
152
+ /**
153
+ * Clear all jobs
154
+ */
155
+ clear() {
156
+ this.jobs.clear();
157
+ this.queue = [];
158
+ this.processing.clear();
159
+ }
160
+ async processNext() {
161
+ if (!this.isRunning || !this.processor)
162
+ return;
163
+ if (this.processing.size >= this.concurrency)
164
+ return;
165
+ if (this.queue.length === 0)
166
+ return;
167
+ const jobId = this.queue.shift();
168
+ if (!jobId)
169
+ return;
170
+ const job = this.jobs.get(jobId);
171
+ if (!job)
172
+ return;
173
+ this.processing.add(jobId);
174
+ job.status = "active";
175
+ job.startedAt = new Date();
176
+ job.attempts++;
177
+ this.emit("active", job);
178
+ try {
179
+ const result = await this.processor(job);
180
+ job.status = "completed";
181
+ job.result = result;
182
+ job.completedAt = new Date();
183
+ job.progress = 100;
184
+ this.emit("completed", job, result);
185
+ }
186
+ catch (error) {
187
+ const err = error instanceof Error ? error : new Error(String(error));
188
+ if (job.attempts < job.maxAttempts) {
189
+ // Retry
190
+ job.status = "pending";
191
+ job.error = err.message;
192
+ setTimeout(() => {
193
+ this.queue.push(jobId);
194
+ this.processNext();
195
+ }, this.retryDelay);
196
+ }
197
+ else {
198
+ // Failed permanently
199
+ job.status = "failed";
200
+ job.error = err.message;
201
+ job.completedAt = new Date();
202
+ this.emit("failed", job, undefined, err);
203
+ }
204
+ }
205
+ finally {
206
+ this.processing.delete(jobId);
207
+ this.processNext();
208
+ }
209
+ }
210
+ }
211
+ // Cache for named queues
212
+ const queueCache = new Map();
213
+ export function getMemoryQueue(name = "default", options) {
214
+ let queue = queueCache.get(name);
215
+ if (!queue) {
216
+ queue = new MemoryQueue(name, options);
217
+ queueCache.set(name, queue);
218
+ }
219
+ return queue;
220
+ }
221
+ //# sourceMappingURL=memory-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-queue.js","sourceRoot":"","sources":["../../src/queue/memory-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,gCAAgC,EAChC,4BAA4B,EAC5B,mCAAmC,GACpC,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,MAAM,GAAG,UAAU,CAAC;AA2B1B,MAAM,OAAO,WAAW;IAeJ;IAdV,IAAI,GAAiC,IAAI,GAAG,EAAE,CAAC;IAC/C,KAAK,GAAa,EAAE,CAAC;IACrB,UAAU,GAAgB,IAAI,GAAG,EAAE,CAAC;IACpC,SAAS,CAAsB;IAC/B,WAAW,CAAS;IACpB,UAAU,CAAS;IACnB,UAAU,CAAS;IACnB,SAAS,GAAG,KAAK,CAAC;IAClB,cAAc,GAGlB,IAAI,GAAG,EAAE,CAAC;IAEd,YACkB,IAAY,EAC5B,UAA8B,EAAE;QADhB,SAAI,GAAJ,IAAI,CAAQ;QAG5B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,gCAAgC,CAAC;QAC3E,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,4BAA4B,CAAC;QACrE,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mCAAmC,CAAC;IAC9E,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,IAAO;QAC7B,MAAM,GAAG,GAAoB;YAC3B,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;YACvB,IAAI;YACJ,IAAI;YACJ,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,IAAI,CAAC,UAAU;SAC7B,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAExB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAE1B,8BAA8B;QAC9B,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,IAAiC;QAC7C,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,SAA6B;QACnC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,MAAkB;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5C,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,SAAS;QACP,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5C,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;YAC1D,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM;YACxD,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM;YAC9D,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM;SACzD,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,KAAa,EAAE,QAAgB;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,GAAG,EAAE,CAAC;YACR,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,EAAE,CACA,KAAiE,EACjE,QAAmE;QAEnE,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACvD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IAEO,IAAI,CACV,KAAiE,EACjE,GAAoB,EACpB,MAAU,EACV,KAAa;QAEb,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACvD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAC/B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,CAAC,KAAK,CACV,+BAA+B,EAC/B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAC7C;oBACE,KAAK;oBACL,KAAK,EAAE,GAAG,CAAC,EAAE;iBACd,CACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAC/C,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QACrD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG;YAAE,OAAO;QAEjB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;QACtB,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC3B,GAAG,CAAC,QAAQ,EAAE,CAAC;QAEf,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACzC,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;YACzB,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;YACpB,GAAG,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;YAC7B,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtE,IAAI,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;gBACnC,QAAQ;gBACR,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBACvB,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC;gBACxB,UAAU,CAAC,GAAG,EAAE;oBACd,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACvB,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,qBAAqB;gBACrB,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACtB,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC;gBACxB,GAAG,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9B,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AAED,yBAAyB;AACzB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyC,CAAC;AAEpE,MAAM,UAAU,cAAc,CAC5B,OAAe,SAAS,EACxB,OAA4B;IAE5B,IAAI,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,WAAW,CAAmB,IAAI,EAAE,OAAO,CAAC,CAAC;QACzD,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,KAAqC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,59 @@
1
+ export type AuditAction = "deployment.created" | "deployment.started" | "deployment.completed" | "deployment.failed" | "deployment.cancelled" | "deployment.retried" | "rollback.initiated" | "rollback.completed" | "rollback.failed" | "solution.exported" | "solution.imported" | "tenant.added" | "tenant.updated" | "tenant.removed" | "config.changed" | "user.login" | "user.logout" | "api.access" | "scheduled.deployment.triggered" | "scheduled.deployment.registered" | "scheduled.deployment.removed";
2
+ export interface AuditLogEntry {
3
+ id: string;
4
+ timestamp: Date;
5
+ action: AuditAction;
6
+ userId: string;
7
+ userEmail?: string;
8
+ userRoles?: string[];
9
+ resourceType: string;
10
+ resourceId?: string;
11
+ resourceName?: string;
12
+ details?: Record<string, unknown>;
13
+ ipAddress?: string;
14
+ userAgent?: string;
15
+ success: boolean;
16
+ errorMessage?: string;
17
+ }
18
+ export interface AuditLogQuery {
19
+ startDate?: Date;
20
+ endDate?: Date;
21
+ userId?: string;
22
+ action?: AuditAction;
23
+ resourceType?: string;
24
+ resourceId?: string;
25
+ success?: boolean;
26
+ limit?: number;
27
+ offset?: number;
28
+ }
29
+ export interface AuditLogStorage {
30
+ write(entry: AuditLogEntry): Promise<void>;
31
+ query(query: AuditLogQuery): Promise<AuditLogEntry[]>;
32
+ count(query: AuditLogQuery): Promise<number>;
33
+ }
34
+ export declare class AuditLogService {
35
+ private storages;
36
+ constructor(storages?: AuditLogStorage[]);
37
+ log(action: AuditAction, context: {
38
+ userId: string;
39
+ userEmail?: string;
40
+ userRoles?: string[];
41
+ resourceType: string;
42
+ resourceId?: string;
43
+ resourceName?: string;
44
+ details?: Record<string, unknown>;
45
+ ipAddress?: string;
46
+ userAgent?: string;
47
+ success?: boolean;
48
+ errorMessage?: string;
49
+ }): Promise<void>;
50
+ query(query: AuditLogQuery): Promise<AuditLogEntry[]>;
51
+ count(query: AuditLogQuery): Promise<number>;
52
+ logDeploymentCreated(userId: string, deploymentId: string, details: Record<string, unknown>): Promise<void>;
53
+ logDeploymentCompleted(userId: string, deploymentId: string, success: boolean, details: Record<string, unknown>): Promise<void>;
54
+ logRollback(userId: string, tenantId: string, tenantName: string, previousVersion: string, success: boolean, errorMessage?: string): Promise<void>;
55
+ logUserLogin(userId: string, userEmail: string, ipAddress: string, userAgent: string, success: boolean): Promise<void>;
56
+ logApiAccess(userId: string, method: string, path: string, ipAddress: string, statusCode: number): Promise<void>;
57
+ }
58
+ export declare function getAuditLog(): AuditLogService;
59
+ //# sourceMappingURL=audit-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../src/services/audit-log.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,WAAW,GACnB,oBAAoB,GACpB,oBAAoB,GACpB,sBAAsB,GACtB,mBAAmB,GACnB,sBAAsB,GACtB,oBAAoB,GACpB,oBAAoB,GACpB,oBAAoB,GACpB,iBAAiB,GACjB,mBAAmB,GACnB,mBAAmB,GACnB,cAAc,GACd,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,gCAAgC,GAChC,iCAAiC,GACjC,8BAA8B,CAAC;AAEnC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACtD,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AA2ED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,QAAQ,CAAC,EAAE,eAAe,EAAE;IAYlC,GAAG,CACP,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GACA,OAAO,CAAC,IAAI,CAAC;IAqBV,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAWrD,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAW5C,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IASV,sBAAsB,CAC1B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAUV,WAAW,CACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAYV,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC;IAWV,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;CAUjB;AAKD,wBAAgB,WAAW,IAAI,eAAe,CAK7C"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Copyright 2024 Pax8, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import crypto from "node:crypto";
17
+ // In-memory storage for development/testing
18
+ class InMemoryAuditStorage {
19
+ entries = [];
20
+ maxEntries = 10000;
21
+ async write(entry) {
22
+ this.entries.unshift(entry);
23
+ if (this.entries.length > this.maxEntries) {
24
+ this.entries = this.entries.slice(0, this.maxEntries);
25
+ }
26
+ }
27
+ async query(query) {
28
+ const results = this.entries.filter((entry) => {
29
+ if (query.startDate && entry.timestamp < query.startDate)
30
+ return false;
31
+ if (query.endDate && entry.timestamp > query.endDate)
32
+ return false;
33
+ if (query.userId && entry.userId !== query.userId)
34
+ return false;
35
+ if (query.action && entry.action !== query.action)
36
+ return false;
37
+ if (query.resourceType && entry.resourceType !== query.resourceType)
38
+ return false;
39
+ if (query.resourceId && entry.resourceId !== query.resourceId)
40
+ return false;
41
+ if (query.success !== undefined && entry.success !== query.success)
42
+ return false;
43
+ return true;
44
+ });
45
+ const offset = query.offset || 0;
46
+ const limit = query.limit || 100;
47
+ return results.slice(offset, offset + limit);
48
+ }
49
+ async count(query) {
50
+ const results = await this.query({ ...query, limit: undefined, offset: undefined });
51
+ return results.length;
52
+ }
53
+ }
54
+ // Console/structured logging storage
55
+ class ConsoleAuditStorage {
56
+ structuredLogging;
57
+ constructor(structuredLogging = true) {
58
+ this.structuredLogging = structuredLogging;
59
+ }
60
+ async write(entry) {
61
+ if (this.structuredLogging) {
62
+ console.log(JSON.stringify({
63
+ level: entry.success ? "info" : "warn",
64
+ type: "audit",
65
+ ...entry,
66
+ timestamp: entry.timestamp.toISOString(),
67
+ }));
68
+ }
69
+ else {
70
+ const status = entry.success ? "SUCCESS" : "FAILED";
71
+ console.log(`[AUDIT] ${entry.timestamp.toISOString()} ${status} ${entry.action} ` +
72
+ `user=${entry.userId} resource=${entry.resourceType}/${entry.resourceId || "n/a"}`);
73
+ }
74
+ }
75
+ async query(_query) {
76
+ // Console storage doesn't support querying
77
+ return [];
78
+ }
79
+ async count(_query) {
80
+ return 0;
81
+ }
82
+ }
83
+ export class AuditLogService {
84
+ storages = [];
85
+ constructor(storages) {
86
+ if (storages && storages.length > 0) {
87
+ this.storages = storages;
88
+ }
89
+ else {
90
+ // Default: use both in-memory and console logging
91
+ this.storages = [
92
+ new InMemoryAuditStorage(),
93
+ new ConsoleAuditStorage(process.env.NODE_ENV === "production"),
94
+ ];
95
+ }
96
+ }
97
+ async log(action, context) {
98
+ const entry = {
99
+ id: crypto.randomUUID(),
100
+ timestamp: new Date(),
101
+ action,
102
+ userId: context.userId,
103
+ userEmail: context.userEmail,
104
+ userRoles: context.userRoles,
105
+ resourceType: context.resourceType,
106
+ resourceId: context.resourceId,
107
+ resourceName: context.resourceName,
108
+ details: context.details,
109
+ ipAddress: context.ipAddress,
110
+ userAgent: context.userAgent,
111
+ success: context.success ?? true,
112
+ errorMessage: context.errorMessage,
113
+ };
114
+ await Promise.all(this.storages.map((storage) => storage.write(entry)));
115
+ }
116
+ async query(query) {
117
+ // Use the first storage that supports querying
118
+ for (const storage of this.storages) {
119
+ const results = await storage.query(query);
120
+ if (results.length > 0) {
121
+ return results;
122
+ }
123
+ }
124
+ return [];
125
+ }
126
+ async count(query) {
127
+ for (const storage of this.storages) {
128
+ const count = await storage.count(query);
129
+ if (count > 0) {
130
+ return count;
131
+ }
132
+ }
133
+ return 0;
134
+ }
135
+ // Convenience methods for common actions
136
+ async logDeploymentCreated(userId, deploymentId, details) {
137
+ await this.log("deployment.created", {
138
+ userId,
139
+ resourceType: "deployment",
140
+ resourceId: deploymentId,
141
+ details,
142
+ });
143
+ }
144
+ async logDeploymentCompleted(userId, deploymentId, success, details) {
145
+ await this.log(success ? "deployment.completed" : "deployment.failed", {
146
+ userId,
147
+ resourceType: "deployment",
148
+ resourceId: deploymentId,
149
+ success,
150
+ details,
151
+ });
152
+ }
153
+ async logRollback(userId, tenantId, tenantName, previousVersion, success, errorMessage) {
154
+ await this.log(success ? "rollback.completed" : "rollback.failed", {
155
+ userId,
156
+ resourceType: "tenant",
157
+ resourceId: tenantId,
158
+ resourceName: tenantName,
159
+ success,
160
+ errorMessage,
161
+ details: { previousVersion },
162
+ });
163
+ }
164
+ async logUserLogin(userId, userEmail, ipAddress, userAgent, success) {
165
+ await this.log("user.login", {
166
+ userId,
167
+ userEmail,
168
+ resourceType: "auth",
169
+ ipAddress,
170
+ userAgent,
171
+ success,
172
+ });
173
+ }
174
+ async logApiAccess(userId, method, path, ipAddress, statusCode) {
175
+ await this.log("api.access", {
176
+ userId,
177
+ resourceType: "api",
178
+ resourceId: path,
179
+ success: statusCode < 400,
180
+ details: { method, statusCode },
181
+ ipAddress,
182
+ });
183
+ }
184
+ }
185
+ // Singleton instance
186
+ let auditLogInstance = null;
187
+ export function getAuditLog() {
188
+ if (!auditLogInstance) {
189
+ auditLogInstance = new AuditLogService();
190
+ }
191
+ return auditLogInstance;
192
+ }
193
+ //# sourceMappingURL=audit-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-log.js","sourceRoot":"","sources":["../../src/services/audit-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright 2024 Pax8, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Auth Error Parser
18
+ *
19
+ * Parses common Azure AD / Dataverse authentication errors into
20
+ * user-friendly messages with actionable fix suggestions.
21
+ *
22
+ * Extracted from CLI validate.ts and init.ts to make this logic
23
+ * reusable across CLI, MCP server, and web consumers.
24
+ */
25
+ export interface ParsedAuthError {
26
+ message: string;
27
+ fix: string;
28
+ }
29
+ /**
30
+ * Parse common Azure/Dataverse errors into user-friendly messages with fixes.
31
+ *
32
+ * Handles AADSTS error codes, permission errors, token acquisition failures,
33
+ * and other common authentication issues encountered during GDAP operations.
34
+ */
35
+ export declare function parseAuthError(errorMsg: string): ParsedAuthError;
36
+ //# sourceMappingURL=auth-error-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-error-parser.d.ts","sourceRoot":"","sources":["../../src/services/auth-error-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;GAQG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CA8EhE"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Copyright 2024 Pax8, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Parse common Azure/Dataverse errors into user-friendly messages with fixes.
18
+ *
19
+ * Handles AADSTS error codes, permission errors, token acquisition failures,
20
+ * and other common authentication issues encountered during GDAP operations.
21
+ */
22
+ export function parseAuthError(errorMsg) {
23
+ // Invalid client secret
24
+ if (errorMsg.includes("AADSTS7000215") || errorMsg.includes("Invalid client secret")) {
25
+ return {
26
+ message: "Invalid client secret",
27
+ fix: "Ensure PARTNER_CLIENT_SECRET contains the secret value (not the secret ID). Generate a new secret in Azure Portal if needed.",
28
+ };
29
+ }
30
+ // Client secret expired
31
+ if (errorMsg.includes("AADSTS7000222") || errorMsg.includes("expired")) {
32
+ return {
33
+ message: "Client secret has expired",
34
+ fix: "Generate a new client secret in Azure Portal → App registrations → Your app → Certificates & secrets",
35
+ };
36
+ }
37
+ // App not found
38
+ if (errorMsg.includes("AADSTS700016") || errorMsg.includes("Application.*not found")) {
39
+ return {
40
+ message: "Application not found in Azure AD",
41
+ fix: "Verify the PARTNER_CLIENT_ID is correct. Check Azure Portal → App registrations.",
42
+ };
43
+ }
44
+ // Tenant not found
45
+ if (errorMsg.includes("AADSTS90002") || errorMsg.includes("tenant.*not found")) {
46
+ return {
47
+ message: "Tenant not found",
48
+ fix: "Verify the PARTNER_TENANT_ID is correct. Check Azure Portal → Azure Active Directory → Overview.",
49
+ };
50
+ }
51
+ // Not a member of organization (GDAP/app user issue)
52
+ if (errorMsg.includes("not a member of the organization") ||
53
+ errorMsg.includes("is not a member")) {
54
+ return {
55
+ message: "App not registered in environment",
56
+ fix: "Create app user in Power Platform Admin Center, or run 'setup --all'",
57
+ };
58
+ }
59
+ // Permission denied
60
+ if (errorMsg.includes("prvRead") ||
61
+ errorMsg.includes("prvWrite") ||
62
+ errorMsg.includes("privilege") ||
63
+ errorMsg.includes("403")) {
64
+ return {
65
+ message: "Insufficient permissions",
66
+ fix: "Assign System Administrator role to the app user in Power Platform Admin Center",
67
+ };
68
+ }
69
+ // Token acquisition failed (generic)
70
+ if (errorMsg.includes("Token acquisition failed")) {
71
+ // Extract the AADSTS code if present
72
+ const aadstsMatch = errorMsg.match(/AADSTS\d+/);
73
+ if (aadstsMatch) {
74
+ return {
75
+ message: `Authentication failed (${aadstsMatch[0]})`,
76
+ fix: "Check Azure AD app configuration. Verify client ID, tenant ID, and secret are correct.",
77
+ };
78
+ }
79
+ return {
80
+ message: "Authentication failed",
81
+ fix: "Check client credentials. Run 'auth status' to verify configuration.",
82
+ };
83
+ }
84
+ // Default: return first line of error
85
+ return {
86
+ message: errorMsg.split("\n")[0].slice(0, 100),
87
+ fix: "Check the error message above and verify your configuration",
88
+ };
89
+ }
90
+ //# sourceMappingURL=auth-error-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-error-parser.js","sourceRoot":"","sources":["../../src/services/auth-error-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,wBAAwB;IACxB,IAAI,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;QACrF,OAAO;YACL,OAAO,EAAE,uBAAuB;YAChC,GAAG,EAAE,8HAA8H;SACpI,CAAC;IACJ,CAAC;IAED,wBAAwB;IACxB,IAAI,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACvE,OAAO;YACL,OAAO,EAAE,2BAA2B;YACpC,GAAG,EAAE,sGAAsG;SAC5G,CAAC;IACJ,CAAC;IAED,gBAAgB;IAChB,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;QACrF,OAAO;YACL,OAAO,EAAE,mCAAmC;YAC5C,GAAG,EAAE,kFAAkF;SACxF,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/E,OAAO;YACL,OAAO,EAAE,kBAAkB;YAC3B,GAAG,EAAE,kGAAkG;SACxG,CAAC;IACJ,CAAC;IAED,qDAAqD;IACrD,IACE,QAAQ,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QACrD,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EACpC,CAAC;QACD,OAAO;YACL,OAAO,EAAE,mCAAmC;YAC5C,GAAG,EAAE,sEAAsE;SAC5E,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,IACE,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5B,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC7B,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC9B,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EACxB,CAAC;QACD,OAAO;YACL,OAAO,EAAE,0BAA0B;YACnC,GAAG,EAAE,iFAAiF;SACvF,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,IAAI,QAAQ,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;QAClD,qCAAqC;QACrC,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO;gBACL,OAAO,EAAE,0BAA0B,WAAW,CAAC,CAAC,CAAC,GAAG;gBACpD,GAAG,EAAE,wFAAwF;aAC9F,CAAC;QACJ,CAAC;QACD,OAAO;YACL,OAAO,EAAE,uBAAuB;YAChC,GAAG,EAAE,sEAAsE;SAC5E,CAAC;IACJ,CAAC;IAED,sCAAsC;IACtC,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;QAC9C,GAAG,EAAE,6DAA6D;KACnE,CAAC;AACJ,CAAC"}